mirror of https://gerrit.osmocom.org/libosmocore
Add mnc_t for 3 digit mncs.
Signed-off-by: Michael McTernan <mike.mcternan@wavemobile.com>
This commit is contained in:
parent
0c50b17a26
commit
dc18606cae
|
@ -21,10 +21,11 @@
|
|||
#define OSMOCORE_GSM0808_H
|
||||
|
||||
#include "tlv.h"
|
||||
#include "gsm48.h"
|
||||
|
||||
struct msgb;
|
||||
|
||||
struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, uint16_t ci);
|
||||
struct msgb *gsm0808_create_layer3(struct msgb *msg, gsm_mnc_t netcode, uint16_t countrycode, int lac, uint16_t ci);
|
||||
struct msgb *gsm0808_create_reset(void);
|
||||
struct msgb *gsm0808_create_reset_ack(void);
|
||||
struct msgb *gsm0808_create_clear_command(uint8_t reason);
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
#ifndef _OSMOCORE_GSM48_H
|
||||
#define _OSMOCORE_GSM48_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/gsm48_ie.h>
|
||||
|
||||
typedef struct {
|
||||
int16_t network_code:15; /**< MNC, 00-999. Signed to allow -1 as invalid placeholder. */
|
||||
bool two_digits:1; /**< If true, MNC is 2 digits, otherwise 3. */
|
||||
} gsm_mnc_t;
|
||||
|
||||
/* A parsed GPRS routing area */
|
||||
struct gprs_ra_id {
|
||||
uint16_t mnc;
|
||||
uint16_t mcc;
|
||||
gsm_mnc_t mnc;
|
||||
uint16_t lac;
|
||||
uint8_t rac;
|
||||
};
|
||||
|
@ -21,9 +29,9 @@ const char *gsm48_cc_msg_name(uint8_t msgtype);
|
|||
const char *rr_cause_name(uint8_t cause);
|
||||
|
||||
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
|
||||
uint16_t *mnc, uint16_t *lac);
|
||||
gsm_mnc_t *mnc, uint16_t *lac);
|
||||
void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
|
||||
uint16_t mnc, uint16_t lac);
|
||||
gsm_mnc_t mnc, uint16_t lac);
|
||||
int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi);
|
||||
int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);
|
||||
|
||||
|
@ -37,4 +45,20 @@ int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid);
|
|||
|
||||
int gsm48_number_of_paging_subchannels(struct gsm48_control_channel_descr *chan_desc);
|
||||
|
||||
static inline gsm_mnc_t gsm48_str_to_mnc(const char *s)
|
||||
{
|
||||
gsm_mnc_t r;
|
||||
|
||||
r.two_digits = strlen(s) <= 2;
|
||||
r.network_code = atoi(s);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int gsm48_mnc_are_equal(gsm_mnc_t a, gsm_mnc_t b)
|
||||
{
|
||||
return a.network_code == b.network_code &&
|
||||
a.two_digits == b.two_digits;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -267,9 +267,10 @@ static int bssgp_rx_bvc_reset(struct msgb *msg, struct tlv_parsed *tp,
|
|||
/* actually extract RAC / CID */
|
||||
bctx->cell_id = bssgp_parse_cell_id(&bctx->ra_id,
|
||||
TLVP_VAL(tp, BSSGP_IE_CELL_ID));
|
||||
LOGP(DBSSGP, LOGL_NOTICE, "Cell %u-%u-%u-%u CI %u on BVCI %u\n",
|
||||
bctx->ra_id.mcc, bctx->ra_id.mnc, bctx->ra_id.lac,
|
||||
bctx->ra_id.rac, bctx->cell_id, bvci);
|
||||
LOGP(DBSSGP, LOGL_NOTICE, "Cell %u-%0*u-%u-%u CI %u on BVCI %u\n",
|
||||
bctx->ra_id.mcc,
|
||||
bctx->ra_id.mnc.two_digits ? 2 : 3, bctx->ra_id.mnc.network_code,
|
||||
bctx->ra_id.lac, bctx->ra_id.rac, bctx->cell_id, bvci);
|
||||
}
|
||||
|
||||
/* Send NM_BVC_RESET.ind to NM */
|
||||
|
@ -587,7 +588,7 @@ static int fc_queue_timer_cfg(struct bssgp_flow_control *fc)
|
|||
if (llist_empty(&fc->queue))
|
||||
return 0;
|
||||
|
||||
fcqe = llist_entry(&fc->queue.next, struct bssgp_fc_queue_element,
|
||||
fcqe = llist_entry(fc->queue.next, struct bssgp_fc_queue_element,
|
||||
list);
|
||||
|
||||
if (fc->bucket_leak_rate != 0) {
|
||||
|
|
|
@ -83,9 +83,10 @@ DEFUN(cfg_bssgp, cfg_bssgp_cmd,
|
|||
|
||||
static void dump_bvc(struct vty *vty, struct bssgp_bvc_ctx *bvc, int stats)
|
||||
{
|
||||
vty_out(vty, "NSEI %5u, BVCI %5u, RA-ID: %u-%u-%u-%u, CID: %u, "
|
||||
vty_out(vty, "NSEI %5u, BVCI %5u, RA-ID: %u-%0*u-%u-%u, CID: %u, "
|
||||
"STATE: %s%s", bvc->nsei, bvc->bvci, bvc->ra_id.mcc,
|
||||
bvc->ra_id.mnc, bvc->ra_id.lac, bvc->ra_id.rac, bvc->cell_id,
|
||||
bvc->ra_id.mnc.two_digits ? 2 : 3, bvc->ra_id.mnc.network_code,
|
||||
bvc->ra_id.lac, bvc->ra_id.rac, bvc->cell_id,
|
||||
bvc->state & BVC_S_BLOCKED ? "BLOCKED" : "UNBLOCKED",
|
||||
VTY_NEWLINE);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define BSSMAP_MSG_SIZE 512
|
||||
#define BSSMAP_MSG_HEADROOM 128
|
||||
|
||||
struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, uint16_t _ci)
|
||||
struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, gsm_mnc_t nc, uint16_t cc, int lac, uint16_t _ci)
|
||||
{
|
||||
struct msgb* msg;
|
||||
struct {
|
||||
|
|
|
@ -265,7 +265,7 @@ static void to_bcd(uint8_t *bcd, uint16_t val)
|
|||
}
|
||||
|
||||
void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
|
||||
uint16_t mnc, uint16_t lac)
|
||||
gsm_mnc_t mnc, uint16_t lac)
|
||||
{
|
||||
uint8_t bcd[3];
|
||||
|
||||
|
@ -273,9 +273,8 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
|
|||
lai48->digits[0] = bcd[0] | (bcd[1] << 4);
|
||||
lai48->digits[1] = bcd[2];
|
||||
|
||||
to_bcd(bcd, mnc);
|
||||
/* FIXME: do we need three-digit MNC? See Table 10.5.3 */
|
||||
if (mnc > 99) {
|
||||
to_bcd(bcd, mnc.network_code);
|
||||
if (!mnc.two_digits) {
|
||||
lai48->digits[1] |= bcd[2] << 4;
|
||||
lai48->digits[2] = bcd[0] | (bcd[1] << 4);
|
||||
} else {
|
||||
|
@ -288,19 +287,21 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
|
|||
|
||||
/* Attention: this function retunrs true integers, not hex! */
|
||||
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
|
||||
uint16_t *mnc, uint16_t *lac)
|
||||
gsm_mnc_t *mnc, uint16_t *lac)
|
||||
{
|
||||
*mcc = (lai->digits[0] & 0x0f) * 100
|
||||
+ (lai->digits[0] >> 4) * 10
|
||||
+ (lai->digits[1] & 0x0f);
|
||||
|
||||
if ((lai->digits[1] & 0xf0) == 0xf0) {
|
||||
*mnc = (lai->digits[2] & 0x0f) * 10
|
||||
+ (lai->digits[2] >> 4);
|
||||
mnc->two_digits = true;
|
||||
mnc->network_code = (lai->digits[2] & 0x0f) * 10
|
||||
| (lai->digits[2] >> 4);
|
||||
} else {
|
||||
*mnc = (lai->digits[2] & 0x0f) * 100
|
||||
+ (lai->digits[2] >> 4) * 10
|
||||
+ (lai->digits[1] >> 4);
|
||||
mnc->two_digits = false;
|
||||
mnc->network_code = (lai->digits[2] & 0x0f) * 100
|
||||
| (lai->digits[2] >> 4) * 10
|
||||
| (lai->digits[1] >> 4);
|
||||
}
|
||||
*lac = ntohs(lai->lac);
|
||||
|
||||
|
@ -401,12 +402,14 @@ void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf)
|
|||
/* I wonder who came up with the stupidity of encoding the MNC
|
||||
* differently depending on how many digits its decimal number has! */
|
||||
if ((buf[1] >> 4) == 0xf) {
|
||||
raid->mnc = (buf[2] & 0xf) * 10;
|
||||
raid->mnc += (buf[2] >> 4) * 1;
|
||||
raid->mnc.two_digits = true;
|
||||
raid->mnc.network_code = (buf[2] & 0xf) * 10;
|
||||
raid->mnc.network_code |= (buf[2] >> 4) * 1;
|
||||
} else {
|
||||
raid->mnc = (buf[2] & 0xf) * 100;
|
||||
raid->mnc += (buf[2] >> 4) * 10;
|
||||
raid->mnc += (buf[1] >> 4) * 1;
|
||||
raid->mnc.two_digits = false;
|
||||
raid->mnc.network_code = (buf[2] & 0xf) * 100;
|
||||
raid->mnc.network_code |= (buf[2] >> 4) * 10;
|
||||
raid->mnc.network_code |= (buf[1] >> 4) * 1;
|
||||
}
|
||||
|
||||
raid->lac = ntohs(*(uint16_t *)(buf + 3));
|
||||
|
@ -415,21 +418,21 @@ void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf)
|
|||
|
||||
int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid)
|
||||
{
|
||||
uint16_t mcc = raid->mcc;
|
||||
uint16_t mnc = raid->mnc;
|
||||
uint16_t _lac;
|
||||
uint16_t mcc = raid->mcc;
|
||||
gsm_mnc_t mnc = raid->mnc;
|
||||
uint16_t _lac;
|
||||
|
||||
buf[0] = ((mcc / 100) % 10) | (((mcc / 10) % 10) << 4);
|
||||
buf[1] = (mcc % 10);
|
||||
|
||||
/* I wonder who came up with the stupidity of encoding the MNC
|
||||
* differently depending on how many digits its decimal number has! */
|
||||
if (mnc < 100) {
|
||||
if (mnc.two_digits) {
|
||||
buf[1] |= 0xf0;
|
||||
buf[2] = ((mnc / 10) % 10) | ((mnc % 10) << 4);
|
||||
buf[2] = ((mnc.network_code / 10) % 10) | ((mnc.network_code % 10) << 4);
|
||||
} else {
|
||||
buf[1] |= (mnc % 10) << 4;
|
||||
buf[2] = ((mnc / 100) % 10) | (((mnc / 10) % 10) << 4);
|
||||
buf[1] |= (mnc.network_code % 10) << 4;
|
||||
buf[2] = ((mnc.network_code / 100) % 10) | (((mnc.network_code / 10) % 10) << 4);
|
||||
}
|
||||
|
||||
_lac = htons(raid->lac);
|
||||
|
|
Loading…
Reference in New Issue