Add mnc_t for 3 digit mncs.

Signed-off-by: Michael McTernan <mike.mcternan@wavemobile.com>
This commit is contained in:
Michael McTernan 2015-07-03 10:33:50 +01:00
parent 0c50b17a26
commit dc18606cae
6 changed files with 63 additions and 33 deletions

View File

@ -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);

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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 {

View File

@ -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);