aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/gprs/gprs_bssgp.h33
-rw-r--r--include/osmocom/gprs/gprs_bssgp_rim.h34
-rw-r--r--src/gb/gprs_bssgp.c41
-rw-r--r--src/gb/gprs_bssgp_internal.h2
-rw-r--r--src/gb/gprs_bssgp_rim.c270
-rw-r--r--src/gb/gprs_bssgp_util.c220
6 files changed, 307 insertions, 293 deletions
diff --git a/include/osmocom/gprs/gprs_bssgp.h b/include/osmocom/gprs/gprs_bssgp.h
index a7b363bd..e55fa527 100644
--- a/include/osmocom/gprs/gprs_bssgp.h
+++ b/include/osmocom/gprs/gprs_bssgp.h
@@ -42,39 +42,6 @@ int bssgp_tx_simple_bvci(uint8_t pdu_type, uint16_t nsei,
/* Chapter 10.4.14: Status */
int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg);
-/* Chapter 10.6.1: RAN-INFORMATION-REQUEST */
-struct bssgp_ran_information_pdu {
- struct bssgp_rim_routing_info routing_info_dest;
- struct bssgp_rim_routing_info routing_info_src;
-
- /* Encoded variant of the RIM container */
- uint8_t rim_cont_iei;
- const uint8_t *rim_cont;
- unsigned int rim_cont_len;
-
- /* Decoded variant of the RIM container */
- bool decoded_present;
- union {
- struct bssgp_ran_inf_req_rim_cont req_rim_cont;
- struct bssgp_ran_inf_rim_cont rim_cont;
- struct bssgp_ran_inf_ack_rim_cont ack_rim_cont;
- struct bssgp_ran_inf_err_rim_cont err_rim_cont;
- struct bssgp_ran_inf_app_err_rim_cont app_err_rim_cont;
- } decoded;
-
- /* When receiving a PDU from BSSGP the encoded variant of the RIM
- * container will always be present. The decoded variant will be
- * present in addition whenever BSSGP was able to decode the container.
- *
- * When sending a PDU to BSSGP, then the decoded variant is used when
- * it is available. The encoded variant (if present) will be ignored
- * then. */
-};
-int bssgp_tx_rim(const struct bssgp_ran_information_pdu *pdu, uint16_t nsei);
-
-int bssgp_parse_rim_pdu(struct bssgp_ran_information_pdu *pdu, const struct msgb *msg);
-struct msgb *bssgp_encode_rim_pdu(const struct bssgp_ran_information_pdu *pdu);
-
enum bssgp_prim {
PRIM_BSSGP_DL_UD,
PRIM_BSSGP_UL_UD,
diff --git a/include/osmocom/gprs/gprs_bssgp_rim.h b/include/osmocom/gprs/gprs_bssgp_rim.h
index 418c1bd2..5f397c98 100644
--- a/include/osmocom/gprs/gprs_bssgp_rim.h
+++ b/include/osmocom/gprs/gprs_bssgp_rim.h
@@ -236,3 +236,37 @@ struct bssgp_ran_inf_app_err_rim_cont {
int bssgp_dec_ran_inf_app_err_rim_cont(struct bssgp_ran_inf_app_err_rim_cont *cont, const uint8_t *buf, size_t len);
int bssgp_enc_ran_inf_app_err_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_app_err_rim_cont *cont);
+
+/* Chapter 10.6.1: RAN-INFORMATION-REQUEST */
+struct bssgp_ran_information_pdu {
+ struct bssgp_rim_routing_info routing_info_dest;
+ struct bssgp_rim_routing_info routing_info_src;
+
+ /* Encoded variant of the RIM container */
+ uint8_t rim_cont_iei;
+ const uint8_t *rim_cont;
+ unsigned int rim_cont_len;
+
+ /* Decoded variant of the RIM container */
+ bool decoded_present;
+ union {
+ struct bssgp_ran_inf_req_rim_cont req_rim_cont;
+ struct bssgp_ran_inf_rim_cont rim_cont;
+ struct bssgp_ran_inf_ack_rim_cont ack_rim_cont;
+ struct bssgp_ran_inf_err_rim_cont err_rim_cont;
+ struct bssgp_ran_inf_app_err_rim_cont app_err_rim_cont;
+ } decoded;
+
+ /* When receiving a PDU from BSSGP the encoded variant of the RIM
+ * container will always be present. The decoded variant will be
+ * present in addition whenever BSSGP was able to decode the container.
+ *
+ * When sending a PDU to BSSGP, then the decoded variant is used when
+ * it is available. The encoded variant (if present) will be ignored
+ * then. */
+};
+
+int bssgp_parse_rim_pdu(struct bssgp_ran_information_pdu *pdu, const struct msgb *msg);
+struct msgb *bssgp_encode_rim_pdu(const struct bssgp_ran_information_pdu *pdu);
+
+int bssgp_tx_rim(const struct bssgp_ran_information_pdu *pdu, uint16_t nsei);
diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c
index 4154c4b5..926b0efa 100644
--- a/src/gb/gprs_bssgp.c
+++ b/src/gb/gprs_bssgp.c
@@ -41,6 +41,7 @@
#include <osmocom/gprs/gprs_ns.h>
#include "osmocom/gsm/gsm48.h"
+#include "gprs_bssgp_internal.h"
void *bssgp_tall_ctx = NULL;
@@ -647,46 +648,6 @@ int bssgp_rx_status(struct msgb *msg, struct tlv_parsed *tp,
return bssgp_prim_cb(&nmp.oph, NULL);
}
-static int bssgp_rx_rim(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci)
-{
- struct osmo_bssgp_prim nmp;
- uint16_t nsei = msgb_nsei(msg);
- struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg);
- enum bssgp_prim prim;
- char ri_src_str[64];
- char ri_dest_str[64];
-
- /* Specify PRIM type based on the RIM PDU */
- switch (bgph->pdu_type) {
- case BSSGP_PDUT_RAN_INFO:
- case BSSGP_PDUT_RAN_INFO_REQ:
- case BSSGP_PDUT_RAN_INFO_ACK:
- case BSSGP_PDUT_RAN_INFO_ERROR:
- case BSSGP_PDUT_RAN_INFO_APP_ERROR:
- prim = PRIM_BSSGP_RIM_PDU_TRANSFER;
- break;
- default:
- /* Caller already makes sure that this can't happen. */
- OSMO_ASSERT(false);
- }
-
- /* Send BSSGP RIM indication to NM */
- memset(&nmp, 0, sizeof(nmp));
- nmp.nsei = nsei;
- nmp.bvci = bvci;
- nmp.tp = tp;
- if (bssgp_parse_rim_pdu(&nmp.u.rim_pdu, msg) < 0)
- return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
- DEBUGP(DLBSSGP, "BSSGP BVCI=%u Rx RIM-PDU:%s, src=%s, dest=%s\n",
- bvci, bssgp_pdu_str(bgph->pdu_type),
- bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &nmp.u.rim_pdu.routing_info_src),
- bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &nmp.u.rim_pdu.routing_info_dest));
- osmo_prim_init(&nmp.oph, SAP_BSSGP_RIM, prim, PRIM_OP_INDICATION, msg);
- bssgp_prim_cb(&nmp.oph, NULL);
-
- return 0;
-}
-
/* One element (msgb) in a BSSGP Flow Control queue */
struct bssgp_fc_queue_element {
/* linked list of queue elements */
diff --git a/src/gb/gprs_bssgp_internal.h b/src/gb/gprs_bssgp_internal.h
index 2ada027c..5022d32d 100644
--- a/src/gb/gprs_bssgp_internal.h
+++ b/src/gb/gprs_bssgp_internal.h
@@ -5,3 +5,5 @@
extern bssgp_bvc_send bssgp_ns_send;
extern void *bssgp_ns_send_data;
+
+int bssgp_rx_rim(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci);
diff --git a/src/gb/gprs_bssgp_rim.c b/src/gb/gprs_bssgp_rim.c
index 25f94066..63b303e5 100644
--- a/src/gb/gprs_bssgp_rim.c
+++ b/src/gb/gprs_bssgp_rim.c
@@ -27,6 +27,7 @@
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_bssgp_rim.h>
#include <osmocom/gsm/gsm0808_utils.h>
+#include "gprs_bssgp_internal.h"
/* TVLV IEs use a variable length field. To be sure we will do all buffer
* length checks with the maximum possible header length, which is
@@ -949,3 +950,272 @@ int bssgp_enc_ran_inf_app_err_rim_cont(uint8_t *buf, size_t len, const struct bs
return (int)(buf_ptr - buf);
}
+
+/*! Parse a given message buffer into a rim-pdu struct.
+ * \param[out] pdu user provided memory for the resulting RAN INFORMATION PDU.
+ * \param[in] msg BSSGP message buffer that contains the encoded RAN INFORMATION PDU.
+ * \returns 0 on sccess, -EINVAL on error. */
+int bssgp_parse_rim_pdu(struct bssgp_ran_information_pdu *pdu, const struct msgb *msg)
+{
+ struct tlv_parsed tp[2];
+ struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg);
+ int data_len;
+ int rc;
+ uint16_t nsei = msgb_nsei(msg);
+
+ memset(pdu, 0, sizeof(*pdu));
+
+ data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
+ if (data_len < 0)
+ return -EINVAL;
+
+ rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, tp, ARRAY_SIZE(tp), bgph->pdu_type, bgph->data, data_len, 0, 0,
+ DLBSSGP, __func__);
+ if (rc < 0)
+ return -EINVAL;
+
+ if (TLVP_PRESENT(&tp[0], BSSGP_IE_RIM_ROUTING_INFO)) {
+ rc = bssgp_parse_rim_ri(&pdu->routing_info_dest, TLVP_VAL(&tp[0], BSSGP_IE_RIM_ROUTING_INFO),
+ TLVP_LEN(&tp[0], BSSGP_IE_RIM_ROUTING_INFO));
+ if (rc < 0) {
+ LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei);
+ return -EINVAL;
+ }
+ } else {
+ LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Destination Cell Identifier IE\n", nsei);
+ return -EINVAL;
+ }
+
+ if (TLVP_PRESENT(&tp[1], BSSGP_IE_RIM_ROUTING_INFO)) {
+ rc = bssgp_parse_rim_ri(&pdu->routing_info_src, TLVP_VAL(&tp[1], BSSGP_IE_RIM_ROUTING_INFO),
+ TLVP_LEN(&tp[1], BSSGP_IE_RIM_ROUTING_INFO));
+ if (rc < 0) {
+ LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei);
+ return -EINVAL;
+ }
+ } else {
+ LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Source Cell Identifier IE\n", nsei);
+ return -EINVAL;
+ }
+
+ if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_REQ_RIM_CONTAINER))
+ pdu->rim_cont_iei = BSSGP_IE_RI_REQ_RIM_CONTAINER;
+ else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_RIM_CONTAINER))
+ pdu->rim_cont_iei = BSSGP_IE_RI_RIM_CONTAINER;
+ else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_APP_ERROR_RIM_CONT))
+ pdu->rim_cont_iei = BSSGP_IE_RI_APP_ERROR_RIM_CONT;
+ else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ACK_RIM_CONTAINER))
+ pdu->rim_cont_iei = BSSGP_IE_RI_ACK_RIM_CONTAINER;
+ else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ERROR_RIM_COINTAINER))
+ pdu->rim_cont_iei = BSSGP_IE_RI_ERROR_RIM_COINTAINER;
+ else {
+ LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing or wrong RIM Container IE\n", nsei);
+ return -EINVAL;
+ }
+
+ pdu->rim_cont = TLVP_VAL(&tp[0], pdu->rim_cont_iei);
+ pdu->rim_cont_len = TLVP_LEN(&tp[0], pdu->rim_cont_iei);
+
+ /* Make sure the rim container field is not empty */
+ if (pdu->rim_cont_len < 1)
+ return -EINVAL;
+ if (!pdu->rim_cont)
+ return -EINVAL;
+
+ /* Note: It is not an error if we fail to parse the RIM container,
+ * since there are applications where parsing the RIM container
+ * is not necessary (routing). It is up to the API user to check
+ * the results. */
+ switch (pdu->rim_cont_iei) {
+ case BSSGP_IE_RI_REQ_RIM_CONTAINER:
+ rc = bssgp_dec_ran_inf_req_rim_cont(&pdu->decoded.req_rim_cont, pdu->rim_cont, pdu->rim_cont_len);
+ break;
+ case BSSGP_IE_RI_RIM_CONTAINER:
+ rc = bssgp_dec_ran_inf_rim_cont(&pdu->decoded.rim_cont, pdu->rim_cont, pdu->rim_cont_len);
+ break;
+ case BSSGP_IE_RI_APP_ERROR_RIM_CONT:
+ rc = bssgp_dec_ran_inf_app_err_rim_cont(&pdu->decoded.app_err_rim_cont, pdu->rim_cont,
+ pdu->rim_cont_len);
+ break;
+ case BSSGP_IE_RI_ACK_RIM_CONTAINER:
+ rc = bssgp_dec_ran_inf_ack_rim_cont(&pdu->decoded.ack_rim_cont, pdu->rim_cont, pdu->rim_cont_len);
+ break;
+ case BSSGP_IE_RI_ERROR_RIM_COINTAINER:
+ rc = bssgp_dec_ran_inf_err_rim_cont(&pdu->decoded.err_rim_cont, pdu->rim_cont, pdu->rim_cont_len);
+ break;
+ default:
+ LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) cannot parse unknown RIM container.\n", nsei);
+ return 0;
+ }
+ if (rc < 0) {
+ LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) unable to parse RIM container.\n", nsei);
+ return 0;
+ }
+ pdu->decoded_present = true;
+
+ return 0;
+}
+
+/*! Encode a given rim-pdu struct into a message buffer.
+ * \param[out] pdu user provided memory that contains the RAN INFORMATION PDU to encode.
+ * \returns BSSGP message buffer on sccess, NULL on error. */
+struct msgb *bssgp_encode_rim_pdu(const struct bssgp_ran_information_pdu *pdu)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph;
+ uint8_t rim_ri_buf[BSSGP_RIM_ROUTING_INFO_MAXLEN];
+ uint8_t *rim_cont_buf;
+ int rc;
+
+ if (!msg)
+ return NULL;
+ bgph = (struct bssgp_normal_hdr *)msgb_put(msg, sizeof(*bgph));
+
+ /* Set PDU type based on RIM container type */
+ switch (pdu->rim_cont_iei) {
+ case BSSGP_IE_RI_REQ_RIM_CONTAINER:
+ bgph->pdu_type = BSSGP_PDUT_RAN_INFO_REQ;
+ break;
+ case BSSGP_IE_RI_RIM_CONTAINER:
+ bgph->pdu_type = BSSGP_PDUT_RAN_INFO;
+ break;
+ case BSSGP_IE_RI_APP_ERROR_RIM_CONT:
+ bgph->pdu_type = BSSGP_PDUT_RAN_INFO_APP_ERROR;
+ break;
+ case BSSGP_IE_RI_ACK_RIM_CONTAINER:
+ bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ACK;
+ break;
+ case BSSGP_IE_RI_ERROR_RIM_COINTAINER:
+ bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ERROR;
+ break;
+ default:
+ /* The caller must correctly specify the container type! */
+ OSMO_ASSERT(false);
+ }
+
+ /* Put RIM routing information */
+ rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_dest);
+ if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN)
+ goto error;
+ msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf);
+ rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_src);
+ if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN)
+ goto error;
+ msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf);
+
+ /* Put RIM container */
+ if (pdu->decoded_present) {
+ rim_cont_buf = talloc_zero_size(msg, msg->data_len);
+ if (!rim_cont_buf)
+ goto error;
+
+ switch (pdu->rim_cont_iei) {
+ case BSSGP_IE_RI_REQ_RIM_CONTAINER:
+ rc = bssgp_enc_ran_inf_req_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.req_rim_cont);
+ break;
+ case BSSGP_IE_RI_RIM_CONTAINER:
+ rc = bssgp_enc_ran_inf_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.rim_cont);
+ break;
+ case BSSGP_IE_RI_APP_ERROR_RIM_CONT:
+ rc = bssgp_enc_ran_inf_app_err_rim_cont(rim_cont_buf, msg->data_len,
+ &pdu->decoded.app_err_rim_cont);
+ break;
+ case BSSGP_IE_RI_ACK_RIM_CONTAINER:
+ rc = bssgp_enc_ran_inf_ack_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.ack_rim_cont);
+ break;
+ case BSSGP_IE_RI_ERROR_RIM_COINTAINER:
+ rc = bssgp_enc_ran_inf_err_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.err_rim_cont);
+ break;
+ default:
+ /* The API user must set the iei properly! */
+ OSMO_ASSERT(false);
+ }
+ if (rc < 0)
+ goto error;
+
+ msgb_tvlv_put(msg, pdu->rim_cont_iei, rc, rim_cont_buf);
+ talloc_free(rim_cont_buf);
+ } else {
+ /* Make sure the RIM container is actually present. */
+ OSMO_ASSERT(pdu->rim_cont_iei != 0 && pdu->rim_cont_len > 0 && pdu->rim_cont);
+ msgb_tvlv_put(msg, pdu->rim_cont_iei, pdu->rim_cont_len, pdu->rim_cont);
+ }
+
+ return msg;
+error:
+ talloc_free(rim_cont_buf);
+ msgb_free(msg);
+ return 0;
+}
+
+/*! Send RIM RAN INFORMATION REQUEST via BSSGP (3GPP TS 48.018, section 10.6.1).
+ * \param[in] pdu user provided memory for the RAN INFORMATION PDU to be sent.
+ * \param[in] nsei BSSGP network service entity identifier (NSEI).
+ * \returns 0 on sccess, -EINVAL on error. */
+int bssgp_tx_rim(const struct bssgp_ran_information_pdu *pdu, uint16_t nsei)
+{
+ struct msgb *msg;
+ struct bssgp_normal_hdr *bgph;
+ char ri_src_str[64];
+ char ri_dest_str[64];
+
+ /* Encode RIM PDU into mesage buffer */
+ msg = bssgp_encode_rim_pdu(pdu);
+ if (!msg) {
+ LOGP(DLBSSGP, LOGL_ERROR,
+ "BSSGP RIM (NSEI=%u) unable to encode BSSGP RIM PDU\n", nsei);
+ return -EINVAL;
+ }
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+
+ bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg);
+ DEBUGP(DLBSSGP, "BSSGP BVCI=0 Tx RIM-PDU:%s, src=%s, dest=%s\n",
+ bssgp_pdu_str(bgph->pdu_type),
+ bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &pdu->routing_info_src),
+ bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &pdu->routing_info_dest));
+
+ return bssgp_ns_send(bssgp_ns_send_data, msg);
+}
+
+/* For internal use only (called from gprs_bssgp.c) */
+int bssgp_rx_rim(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci)
+{
+ struct osmo_bssgp_prim nmp;
+ uint16_t nsei = msgb_nsei(msg);
+ struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg);
+ enum bssgp_prim prim;
+ char ri_src_str[64];
+ char ri_dest_str[64];
+
+ /* Specify PRIM type based on the RIM PDU */
+ switch (bgph->pdu_type) {
+ case BSSGP_PDUT_RAN_INFO:
+ case BSSGP_PDUT_RAN_INFO_REQ:
+ case BSSGP_PDUT_RAN_INFO_ACK:
+ case BSSGP_PDUT_RAN_INFO_ERROR:
+ case BSSGP_PDUT_RAN_INFO_APP_ERROR:
+ prim = PRIM_BSSGP_RIM_PDU_TRANSFER;
+ break;
+ default:
+ /* Caller already makes sure that this can't happen. */
+ OSMO_ASSERT(false);
+ }
+
+ /* Send BSSGP RIM indication to NM */
+ memset(&nmp, 0, sizeof(nmp));
+ nmp.nsei = nsei;
+ nmp.bvci = bvci;
+ nmp.tp = tp;
+ if (bssgp_parse_rim_pdu(&nmp.u.rim_pdu, msg) < 0)
+ return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
+ DEBUGP(DLBSSGP, "BSSGP BVCI=%u Rx RIM-PDU:%s, src=%s, dest=%s\n",
+ bvci, bssgp_pdu_str(bgph->pdu_type),
+ bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &nmp.u.rim_pdu.routing_info_src),
+ bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &nmp.u.rim_pdu.routing_info_dest));
+ osmo_prim_init(&nmp.oph, SAP_BSSGP_RIM, prim, PRIM_OP_INDICATION, msg);
+ bssgp_prim_cb(&nmp.oph, NULL);
+
+ return 0;
+}
diff --git a/src/gb/gprs_bssgp_util.c b/src/gb/gprs_bssgp_util.c
index e00aed96..92896c1f 100644
--- a/src/gb/gprs_bssgp_util.c
+++ b/src/gb/gprs_bssgp_util.c
@@ -588,223 +588,3 @@ int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg)
return bssgp_ns_send(bssgp_ns_send_data, msg);
}
-
-/* Chapter 10.6.1: RAN-INFORMATION-REQUEST */
-int bssgp_tx_rim(const struct bssgp_ran_information_pdu *pdu, uint16_t nsei)
-{
- struct msgb *msg;
- struct bssgp_normal_hdr *bgph;
- char ri_src_str[64];
- char ri_dest_str[64];
-
- /* Encode RIM PDU into mesage buffer */
- msg = bssgp_encode_rim_pdu(pdu);
- if (!msg) {
- LOGP(DLBSSGP, LOGL_ERROR,
- "BSSGP RIM (NSEI=%u) unable to encode BSSGP RIM PDU\n", nsei);
- return -EINVAL;
- }
-
- msgb_nsei(msg) = nsei;
- msgb_bvci(msg) = 0; /* Signalling */
-
- bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg);
- DEBUGP(DLBSSGP, "BSSGP BVCI=0 Tx RIM-PDU:%s, src=%s, dest=%s\n",
- bssgp_pdu_str(bgph->pdu_type),
- bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &pdu->routing_info_src),
- bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &pdu->routing_info_dest));
-
- return bssgp_ns_send(bssgp_ns_send_data, msg);
-}
-
-/* Parse a given message buffer into a rim-pdu struct */
-int bssgp_parse_rim_pdu(struct bssgp_ran_information_pdu *pdu, const struct msgb *msg)
-{
- struct tlv_parsed tp[2];
- struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg);
- int data_len;
- int rc;
- uint16_t nsei = msgb_nsei(msg);
-
- memset(pdu, 0, sizeof(*pdu));
-
- data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
- if (data_len < 0)
- return -EINVAL;
-
- rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, tp, ARRAY_SIZE(tp), bgph->pdu_type, bgph->data, data_len, 0, 0,
- DLBSSGP, __func__);
- if (rc < 0)
- return -EINVAL;
-
- if (TLVP_PRESENT(&tp[0], BSSGP_IE_RIM_ROUTING_INFO)) {
- rc = bssgp_parse_rim_ri(&pdu->routing_info_dest, TLVP_VAL(&tp[0], BSSGP_IE_RIM_ROUTING_INFO),
- TLVP_LEN(&tp[0], BSSGP_IE_RIM_ROUTING_INFO));
- if (rc < 0) {
- LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei);
- return -EINVAL;
- }
- } else {
- LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Destination Cell Identifier IE\n", nsei);
- return -EINVAL;
- }
-
- if (TLVP_PRESENT(&tp[1], BSSGP_IE_RIM_ROUTING_INFO)) {
- rc = bssgp_parse_rim_ri(&pdu->routing_info_src, TLVP_VAL(&tp[1], BSSGP_IE_RIM_ROUTING_INFO),
- TLVP_LEN(&tp[1], BSSGP_IE_RIM_ROUTING_INFO));
- if (rc < 0) {
- LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei);
- return -EINVAL;
- }
- } else {
- LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Source Cell Identifier IE\n", nsei);
- return -EINVAL;
- }
-
- if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_REQ_RIM_CONTAINER))
- pdu->rim_cont_iei = BSSGP_IE_RI_REQ_RIM_CONTAINER;
- else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_RIM_CONTAINER))
- pdu->rim_cont_iei = BSSGP_IE_RI_RIM_CONTAINER;
- else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_APP_ERROR_RIM_CONT))
- pdu->rim_cont_iei = BSSGP_IE_RI_APP_ERROR_RIM_CONT;
- else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ACK_RIM_CONTAINER))
- pdu->rim_cont_iei = BSSGP_IE_RI_ACK_RIM_CONTAINER;
- else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ERROR_RIM_COINTAINER))
- pdu->rim_cont_iei = BSSGP_IE_RI_ERROR_RIM_COINTAINER;
- else {
- LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing or wrong RIM Container IE\n", nsei);
- return -EINVAL;
- }
-
- pdu->rim_cont = TLVP_VAL(&tp[0], pdu->rim_cont_iei);
- pdu->rim_cont_len = TLVP_LEN(&tp[0], pdu->rim_cont_iei);
-
- /* Make sure the rim container field is not empty */
- if (pdu->rim_cont_len < 1)
- return -EINVAL;
- if (!pdu->rim_cont)
- return -EINVAL;
-
- /* Note: It is not an error if we fail to parse the RIM container,
- * since there are applications where parsing the RIM container
- * is not necessary (routing). It is up to the API user to check
- * the results. */
- switch (pdu->rim_cont_iei) {
- case BSSGP_IE_RI_REQ_RIM_CONTAINER:
- rc = bssgp_dec_ran_inf_req_rim_cont(&pdu->decoded.req_rim_cont, pdu->rim_cont, pdu->rim_cont_len);
- break;
- case BSSGP_IE_RI_RIM_CONTAINER:
- rc = bssgp_dec_ran_inf_rim_cont(&pdu->decoded.rim_cont, pdu->rim_cont, pdu->rim_cont_len);
- break;
- case BSSGP_IE_RI_APP_ERROR_RIM_CONT:
- rc = bssgp_dec_ran_inf_app_err_rim_cont(&pdu->decoded.app_err_rim_cont, pdu->rim_cont,
- pdu->rim_cont_len);
- break;
- case BSSGP_IE_RI_ACK_RIM_CONTAINER:
- rc = bssgp_dec_ran_inf_ack_rim_cont(&pdu->decoded.ack_rim_cont, pdu->rim_cont, pdu->rim_cont_len);
- break;
- case BSSGP_IE_RI_ERROR_RIM_COINTAINER:
- rc = bssgp_dec_ran_inf_err_rim_cont(&pdu->decoded.err_rim_cont, pdu->rim_cont, pdu->rim_cont_len);
- break;
- default:
- LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) cannot parse unknown RIM container.\n", nsei);
- return 0;
- }
- if (rc < 0) {
- LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) unable to parse RIM container.\n", nsei);
- return 0;
- }
- pdu->decoded_present = true;
-
- return 0;
-}
-
-/* Encode a given rim-pdu struct into a message buffer */
-struct msgb *bssgp_encode_rim_pdu(const struct bssgp_ran_information_pdu *pdu)
-{
- struct msgb *msg = bssgp_msgb_alloc();
- struct bssgp_normal_hdr *bgph;
- uint8_t rim_ri_buf[BSSGP_RIM_ROUTING_INFO_MAXLEN];
- uint8_t *rim_cont_buf;
- int rc;
-
- if (!msg)
- return NULL;
- bgph = (struct bssgp_normal_hdr *)msgb_put(msg, sizeof(*bgph));
-
- /* Set PDU type based on RIM container type */
- switch (pdu->rim_cont_iei) {
- case BSSGP_IE_RI_REQ_RIM_CONTAINER:
- bgph->pdu_type = BSSGP_PDUT_RAN_INFO_REQ;
- break;
- case BSSGP_IE_RI_RIM_CONTAINER:
- bgph->pdu_type = BSSGP_PDUT_RAN_INFO;
- break;
- case BSSGP_IE_RI_APP_ERROR_RIM_CONT:
- bgph->pdu_type = BSSGP_PDUT_RAN_INFO_APP_ERROR;
- break;
- case BSSGP_IE_RI_ACK_RIM_CONTAINER:
- bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ACK;
- break;
- case BSSGP_IE_RI_ERROR_RIM_COINTAINER:
- bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ERROR;
- break;
- default:
- /* The caller must correctly specify the container type! */
- OSMO_ASSERT(false);
- }
-
- /* Put RIM routing information */
- rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_dest);
- if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN)
- goto error;
- msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf);
- rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_src);
- if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN)
- goto error;
- msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf);
-
- /* Put RIM container */
- if (pdu->decoded_present) {
- rim_cont_buf = talloc_zero_size(msg, msg->data_len);
- if (!rim_cont_buf)
- goto error;
-
- switch (pdu->rim_cont_iei) {
- case BSSGP_IE_RI_REQ_RIM_CONTAINER:
- rc = bssgp_enc_ran_inf_req_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.req_rim_cont);
- break;
- case BSSGP_IE_RI_RIM_CONTAINER:
- rc = bssgp_enc_ran_inf_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.rim_cont);
- break;
- case BSSGP_IE_RI_APP_ERROR_RIM_CONT:
- rc = bssgp_enc_ran_inf_app_err_rim_cont(rim_cont_buf, msg->data_len,
- &pdu->decoded.app_err_rim_cont);
- break;
- case BSSGP_IE_RI_ACK_RIM_CONTAINER:
- rc = bssgp_enc_ran_inf_ack_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.ack_rim_cont);
- break;
- case BSSGP_IE_RI_ERROR_RIM_COINTAINER:
- rc = bssgp_enc_ran_inf_err_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.err_rim_cont);
- break;
- default:
- /* The API user must set the iei properly! */
- OSMO_ASSERT(false);
- }
- if (rc < 0)
- goto error;
-
- msgb_tvlv_put(msg, pdu->rim_cont_iei, rc, rim_cont_buf);
- talloc_free(rim_cont_buf);
- } else {
- /* Make sure the RIM container is actually present. */
- OSMO_ASSERT(pdu->rim_cont_iei != 0 && pdu->rim_cont_len > 0 && pdu->rim_cont);
- msgb_tvlv_put(msg, pdu->rim_cont_iei, pdu->rim_cont_len, pdu->rim_cont);
- }
-
- return msg;
-error:
- talloc_free(rim_cont_buf);
- msgb_free(msg);
- return 0;
-}