2020-03-18 08:04:17 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2020 Software Radio Systems Limited
|
|
|
|
* Author: Vadim Yanitskiy <axilirator@gmail.com>
|
|
|
|
* Sponsored by Positive Technologies
|
|
|
|
*
|
|
|
|
* This file is part of srsLTE.
|
|
|
|
*
|
|
|
|
* srsLTE is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* srsLTE is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* A copy of the GNU Affero General Public License can be found in
|
|
|
|
* the LICENSE file in the top-level directory of this distribution
|
|
|
|
* and at http://www.gnu.org/licenses/.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
#include "srsue/hdr/stack/upper/rrctl.h"
|
|
|
|
|
|
|
|
namespace rrctl {
|
|
|
|
|
|
|
|
namespace proto {
|
|
|
|
|
|
|
|
std::string msg_hdr_desc(proto::msg_type type, proto::msg_disc disc, uint16_t len)
|
|
|
|
{
|
|
|
|
std::string desc;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case RRCTL_RESET:
|
|
|
|
desc += "Reset";
|
|
|
|
break;
|
|
|
|
case RRCTL_PLMN_SEARCH:
|
|
|
|
desc += "PLMN Search";
|
|
|
|
break;
|
|
|
|
case RRCTL_PLMN_SELECT:
|
|
|
|
desc += "PLMN Select";
|
|
|
|
break;
|
|
|
|
case RRCTL_CONN_ESTABLISH:
|
|
|
|
desc += "Connection Establish";
|
|
|
|
break;
|
|
|
|
case RRCTL_CONN_RELEASE:
|
|
|
|
desc += "Connection Release";
|
|
|
|
break;
|
|
|
|
case RRCTL_DATA:
|
|
|
|
desc += "Data (PDU)";
|
|
|
|
break;
|
|
|
|
case RRCTL_PAGING:
|
|
|
|
desc += "Paging";
|
|
|
|
break;
|
|
|
|
case RRCTL_PARAM:
|
|
|
|
desc += "Parameter";
|
|
|
|
break;
|
2020-11-07 12:14:56 +00:00
|
|
|
case RRCTL_SEC_MODE:
|
|
|
|
desc += "Security Mode";
|
|
|
|
break;
|
2020-11-06 22:11:19 +00:00
|
|
|
case RRCTL_EXT_USIM:
|
|
|
|
desc += "(U)SIM Specific";
|
|
|
|
break;
|
2020-11-02 20:24:49 +00:00
|
|
|
case RRCTL_RESERVED:
|
|
|
|
desc += "RFU (Reserved for Further Use)";
|
|
|
|
break;
|
2020-03-18 08:04:17 +00:00
|
|
|
default:
|
|
|
|
desc += "<UNKNOWN>";
|
|
|
|
}
|
|
|
|
|
|
|
|
desc += " ";
|
|
|
|
|
|
|
|
switch (disc) {
|
|
|
|
case RRCTL_REQ:
|
|
|
|
desc += "Request";
|
|
|
|
break;
|
|
|
|
case RRCTL_IND:
|
|
|
|
desc += "Indication";
|
|
|
|
break;
|
|
|
|
case RRCTL_CNF:
|
|
|
|
desc += "Confirmation";
|
|
|
|
break;
|
|
|
|
case RRCTL_ERR:
|
|
|
|
desc += "Error";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len > 0) {
|
|
|
|
desc += " (length ";
|
|
|
|
desc += std::to_string(len);
|
|
|
|
desc += ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace codec {
|
|
|
|
|
2020-11-04 05:53:12 +00:00
|
|
|
struct proto::msg_hdr* enc_hdr(srslte::byte_buffer_t& buf,
|
|
|
|
proto::msg_type type,
|
|
|
|
proto::msg_disc disc,
|
|
|
|
uint16_t len)
|
2020-03-18 08:04:17 +00:00
|
|
|
{
|
|
|
|
struct proto::msg_hdr hdr = {
|
|
|
|
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
|
|
|
.disc = (uint8_t) disc,
|
|
|
|
.type = (uint8_t) type,
|
|
|
|
#elif defined(__BIG_ENDIAN_BITFIELD)
|
|
|
|
.type = (uint8_t) type,
|
|
|
|
.disc = (uint8_t) disc,
|
|
|
|
#else
|
|
|
|
#error "Please fix <asm/byteorder.h>"
|
|
|
|
#endif
|
|
|
|
.len = ntohs(len),
|
|
|
|
};
|
|
|
|
|
|
|
|
buf.append_bytes((const uint8_t*) &hdr, sizeof(hdr));
|
2020-11-04 05:53:12 +00:00
|
|
|
|
|
|
|
return reinterpret_cast<struct proto::msg_hdr*> (&buf.msg[0]);
|
2020-03-18 08:04:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t* dec_hdr(const srslte::byte_buffer_t& buf,
|
|
|
|
proto::msg_type& type,
|
|
|
|
proto::msg_disc& disc,
|
|
|
|
uint16_t& len)
|
|
|
|
{
|
|
|
|
const struct proto::msg_hdr* hdr;
|
|
|
|
|
|
|
|
// Make sure at least header is present
|
|
|
|
if (buf.N_bytes < sizeof(*hdr))
|
|
|
|
throw codec::error("header is too short");
|
|
|
|
|
|
|
|
hdr = reinterpret_cast<const struct proto::msg_hdr*> (buf.msg);
|
|
|
|
type = static_cast<proto::msg_type> (hdr->type);
|
|
|
|
disc = static_cast<proto::msg_disc> (hdr->disc);
|
|
|
|
len = htons(hdr->len);
|
|
|
|
|
|
|
|
// Make sure the whole message fits
|
|
|
|
if (buf.N_bytes < sizeof(*hdr) + len)
|
|
|
|
throw codec::error("body is too short");
|
|
|
|
|
|
|
|
// Return pointer to the payload (if present)
|
|
|
|
return len ? hdr->data : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void enc_plmn_search_res(srslte::byte_buffer_t& buf,
|
|
|
|
const srsue::rrc_interface_nas::found_plmn_t* plmns,
|
|
|
|
size_t nof_plmns)
|
|
|
|
{
|
|
|
|
struct proto::msg_plmn_search_res msg;
|
|
|
|
uint16_t msg_len;
|
|
|
|
|
|
|
|
if (nof_plmns > 16)
|
|
|
|
throw codec::error("too many PLMNS to encode");
|
|
|
|
msg.nof_plmns = static_cast<uint8_t> (nof_plmns);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < nof_plmns; i++) {
|
|
|
|
plmns[i].plmn_id.to_rrctl_bytes(msg.plmns[i].mcc, msg.plmns[i].mnc);
|
|
|
|
msg.plmns[i].tac = htons(plmns[i].tac);
|
|
|
|
}
|
|
|
|
|
|
|
|
msg_len = sizeof(proto::msg_plmn_search_res::plmn) * nof_plmns + 1;
|
|
|
|
enc_hdr(buf, proto::RRCTL_PLMN_SEARCH, proto::RRCTL_CNF, msg_len);
|
|
|
|
buf.append_bytes((uint8_t *) &msg, msg_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dec_plmn_select_req(std::pair<uint16_t, uint16_t>& mcc_mnc,
|
|
|
|
const uint8_t* payload, size_t len)
|
|
|
|
{
|
|
|
|
const struct proto::msg_plmn_select_req* msg;
|
|
|
|
struct srslte::plmn_id_t plmn_id;
|
|
|
|
|
|
|
|
if (len < sizeof(*msg))
|
|
|
|
throw codec::error("body is too short");
|
|
|
|
|
|
|
|
msg = reinterpret_cast<const struct proto::msg_plmn_select_req*> (payload);
|
|
|
|
plmn_id.from_rrctl_bytes(msg->mcc, msg->mnc);
|
|
|
|
mcc_mnc = plmn_id.to_number();
|
|
|
|
}
|
|
|
|
|
|
|
|
void dec_conn_establish_req(srslte::establishment_cause_t& cause,
|
|
|
|
const uint8_t*& pdu, size_t& pdu_len,
|
|
|
|
const uint8_t* payload, size_t len)
|
|
|
|
{
|
|
|
|
const struct proto::msg_conn_establish_req* msg;
|
|
|
|
|
|
|
|
if (len < sizeof(*msg))
|
|
|
|
throw codec::error("body is too short");
|
|
|
|
|
|
|
|
msg = reinterpret_cast<const struct proto::msg_conn_establish_req*> (payload);
|
|
|
|
cause = static_cast<srslte::establishment_cause_t> (msg->cause);
|
|
|
|
pdu_len = len - 1;
|
|
|
|
pdu = msg->pdu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void enc_data_ind(srslte::byte_buffer_t& buf,
|
|
|
|
const uint8_t *pdu, size_t pdu_len,
|
|
|
|
uint32_t lcid)
|
|
|
|
{
|
|
|
|
struct proto::msg_data msg;
|
|
|
|
|
|
|
|
msg.lcid = htonl(lcid);
|
|
|
|
|
|
|
|
enc_hdr(buf, proto::RRCTL_DATA, proto::RRCTL_IND, sizeof(msg) + pdu_len);
|
|
|
|
buf.append_bytes((const uint8_t*) &msg, sizeof(msg));
|
|
|
|
buf.append_bytes(pdu, pdu_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void enc_paging_ind(srslte::byte_buffer_t& buf,
|
|
|
|
srslte::s_tmsi_t* ue_identity)
|
|
|
|
{
|
|
|
|
struct proto::msg_paging_ind msg;
|
|
|
|
|
|
|
|
msg.ueid.m_tmsi = htonl(ue_identity->m_tmsi);
|
|
|
|
msg.ueid.mmec = ue_identity->mmec;
|
|
|
|
|
|
|
|
enc_hdr(buf, proto::RRCTL_PAGING, proto::RRCTL_IND, sizeof(msg));
|
|
|
|
buf.append_bytes((const uint8_t*) &msg, sizeof(msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace codec
|
|
|
|
|
|
|
|
} // namespace rrctl
|