mirror of https://gerrit.osmocom.org/libosmocore
gprs_bssgp: agregate RIM related code in gprs_bssgp_rim.c
gprs_bssgp and gprs_bssgp_util.c also contains code related to send and receive RIM PDUs via BSSGP and also code to encode and decode RAN INFORMATION PDUs. Lets move this to gprs_bssgp_rim.c Change-Id: Icda279452962b06e552cb1361d2a27b7dc8a6b04 Related: SYS#5103
This commit is contained in:
parent
3e3f377749
commit
4d40047c50
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue