diff options
author | Sebastian Stumpf <sebastian.stumpf87@googlemail.com> | 2017-02-02 18:52:17 +0100 |
---|---|---|
committer | Sebastian Stumpf <sebastian.stumpf87@googlemail.com> | 2017-02-02 18:52:17 +0100 |
commit | f0f95a9b8a662641faa7bc51e2465f7cf7575c47 (patch) | |
tree | 9ef7b04e9587d71d1d35373df296ca973f2b9399 | |
parent | fad85d2d0d04328dd4dffed91555a109a595aa1b (diff) |
VIRT_PHY: Proper gsmtap hdr info to rsl chan_nr parsing and vice-versa.
-rw-r--r-- | src/osmo-bts-virtual/l1_if.c | 160 | ||||
-rw-r--r-- | src/osmo-bts-virtual/scheduler_virtbts.c | 62 |
2 files changed, 170 insertions, 52 deletions
diff --git a/src/osmo-bts-virtual/l1_if.c b/src/osmo-bts-virtual/l1_if.c index e663767e..2de50822 100644 --- a/src/osmo-bts-virtual/l1_if.c +++ b/src/osmo-bts-virtual/l1_if.c @@ -28,6 +28,7 @@ #include <osmocom/core/linuxlist.h> #include <osmocom/core/gsmtap.h> #include <osmocom/gsm/protocol/gsm_08_58.h> +#include <osmocom/gsm/rsl.h> #include <osmo-bts/logging.h> #include <osmo-bts/bts.h> @@ -42,6 +43,82 @@ #include "virtual_um.h" +extern int vbts_sched_start(struct gsm_bts *bts); + +/*! \brief convert GSMTAP channel type to RSL channel number + * \param[in] gsmtap_chantype GSMTAP channel type + * \param[out] rsl_chantype rsl channel type + * \param[out] rsl_chantype rsl link id + * + * Mapping from gsmtap channel: + * GSMTAP_CHANNEL_UNKNOWN * 0x00 + * GSMTAP_CHANNEL_BCCH * 0x01 + * GSMTAP_CHANNEL_CCCH * 0x02 + * GSMTAP_CHANNEL_RACH * 0x03 + * GSMTAP_CHANNEL_AGCH * 0x04 + * GSMTAP_CHANNEL_PCH * 0x05 + * GSMTAP_CHANNEL_SDCCH * 0x06 + * GSMTAP_CHANNEL_SDCCH4 * 0x07 + * GSMTAP_CHANNEL_SDCCH8 * 0x08 + * GSMTAP_CHANNEL_TCH_F * 0x09 + * GSMTAP_CHANNEL_TCH_H * 0x0a + * GSMTAP_CHANNEL_PACCH * 0x0b + * GSMTAP_CHANNEL_CBCH52 * 0x0c + * GSMTAP_CHANNEL_PDCH * 0x0d + * GSMTAP_CHANNEL_PTCCH * 0x0e + * GSMTAP_CHANNEL_CBCH51 * 0x0f + * to rsl channel type: + * RSL_CHAN_NR_MASK * 0xf8 + * RSL_CHAN_NR_1 * * 0x08 + * RSL_CHAN_Bm_ACCHs * 0x08 + * RSL_CHAN_Lm_ACCHs * 0x10 + * RSL_CHAN_SDCCH4_ACCH * 0x20 + * RSL_CHAN_SDCCH8_ACCH * 0x40 + * RSL_CHAN_BCCH * * 0x80 + * RSL_CHAN_RACH * * 0x88 + * RSL_CHAN_PCH_AGCH * 0x90 + * RSL_CHAN_OSMO_PDCH * 0xc0 + * and logical channel link id: + * LID_SACCH * * 0x40 + * LID_DEDIC * * 0x00 + * + * TODO: move this to a library used by both ms and bts virt um + */ +void chantype_gsmtap2rsl(uint8_t gsmtap_chantype, uint8_t *rsl_chantype, uint8_t *link_id) +{ + // switch case with removed acch flag + switch (gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH & 0xff) { + case GSMTAP_CHANNEL_TCH_F: // TCH/F, FACCH/F + *rsl_chantype = RSL_CHAN_Bm_ACCHs; + break; + case GSMTAP_CHANNEL_TCH_H: // TCH/H, FACCH/H + *rsl_chantype = RSL_CHAN_Lm_ACCHs; + break; + case GSMTAP_CHANNEL_SDCCH4: // SDCCH/4 + *rsl_chantype = RSL_CHAN_SDCCH4_ACCH; + break; + case GSMTAP_CHANNEL_SDCCH8: // SDCCH/8 + *rsl_chantype = RSL_CHAN_SDCCH8_ACCH; + break; + case GSMTAP_CHANNEL_BCCH: // BCCH + *rsl_chantype = RSL_CHAN_BCCH; + break; + case GSMTAP_CHANNEL_RACH: // RACH + *rsl_chantype = RSL_CHAN_RACH; + break; + case GSMTAP_CHANNEL_PCH: // PCH + case GSMTAP_CHANNEL_AGCH: // AGCH + *rsl_chantype = RSL_CHAN_PCH_AGCH; + break; + case GSMTAP_CHANNEL_PDCH: + *rsl_chantype = GSMTAP_CHANNEL_PDCH; + break; + } + + *link_id = gsmtap_chantype & GSMTAP_CHANNEL_ACCH ? LID_SACCH : LID_DEDIC; + +} + /** * Callback to handle incoming messages from the MS. * The incoming message should be GSM_TAP encapsulated. @@ -49,46 +126,81 @@ */ static void virt_um_rcv_cb(struct virt_um_inst *vui, struct msgb *msg) { - struct gsmtap_hdr *gh; - struct osmo_phsap_prim l1sap; + struct gsmtap_hdr *gh = msgb_l1(msg); + uint32_t fn = ntohl(gh->frame_number); // frame number of the rcv msg + uint16_t arfcn = ntohs(gh->arfcn); // arfcn of the cell we currently camp on + uint8_t gsmtap_chantype = gh->sub_type; // gsmtap channel type + uint8_t signal_dbm = gh->signal_dbm; // signal strength, 63 is best + uint8_t snr = gh->snr_db; // signal noise ratio, 63 is best + uint8_t subslot = gh->sub_slot; // multiframe subslot to send msg in (tch -> 0-26, bcch/ccch -> 0-51) + uint8_t timeslot = gh->timeslot; // tdma timeslot to send in (0-7) + uint8_t rsl_chantype; // rsl chan type (8.58, 9.3.1) + uint8_t link_id; // rsl link id tells if this is an ssociated or dedicated link + uint8_t chan_nr; // encoded rsl channel type, timeslot and mf subslot struct phy_link *plink = (struct phy_link *)vui->priv; // TODO: is there more than one physical instance? Where do i get the corresponding pinst number? Maybe gsmtap_hdr->antenna? struct phy_instance *pinst = phy_instance_by_num(plink, 0); + struct l1sched_trx *l1t = &pinst->u.virt.sched; + struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, timeslot); + struct osmo_phsap_prim l1sap; memset(&l1sap, 0, sizeof(l1sap)); - msg->l1h = msgb_data(msg); + // get rid of l1 gsmtap hdr msg->l2h = msgb_pull(msg, sizeof(*gh)); - gh = msgb_l1(msg); - switch (gh->sub_type) { - case GSMTAP_CHANNEL_RACH: + // convert gsmtap chan to rsl chan and link id + chantype_gsmtap2rsl(gsmtap_chantype, &rsl_chantype, &link_id); + chan_nr = rsl_enc_chan_nr(rsl_chantype, subslot, timeslot); + // switch case with removed acch flag + switch (gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH & 0xff) { + case GSMTAP_CHANNEL_RACH: // generate primitive for upper layer + // see 04.08 - 3.3.1.3.1: the IMMEDIATE_ASSIGNMENT coming back from the network has to be + // sent with the same ra reference as in the CHANNEL_REQUEST that was received osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, msg); - l1sap.u.rach_ind.chan_nr = RSL_CHAN_RACH; - // get the random access content - l1sap.u.rach_ind.ra = msgb_pull_u8(msg); - l1sap.u.rach_ind.fn = ntohl(gh->frame_number); + + l1sap.u.rach_ind.chan_nr = chan_nr; + // TODO: why is ra her 16bits long instead of 8 like in the reference 04.08 - 9.1.8 - Channel request? + l1sap.u.rach_ind.ra = msgb_pull_u8(msg); // directly after gh hdr comes ra + l1sap.u.rach_ind.acc_delay = 0; // probably not used in virt um + l1sap.u.rach_ind.is_11bit = 0; // We dont use that + l1sap.u.rach_ind.fn = fn; + l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_NONE; // FIXME: what comes here break; - case GSMTAP_CHANNEL_SDCCH: case GSMTAP_CHANNEL_SDCCH4: + // TODO: check if separate handling is needed case GSMTAP_CHANNEL_SDCCH8: - // TODO: implement channel handling - break; + // TODO: check if separate handling is needed case GSMTAP_CHANNEL_TCH_F: - // TODO: implement channel handling - break; + // TODO: check if separate handling is needed case GSMTAP_CHANNEL_TCH_H: - // TODO: implement channel handling + // check if associated control flag is set + if(gsmtap_chantype & GSMTAP_CHANNEL_ACCH) { + // TODO: check if handling is different for ACCH + // TODO: does FACCH need special handling? + } + osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_DATA, + PRIM_OP_INDICATION, msg); + + l1sap.u.data.chan_nr = chan_nr; + l1sap.u.data.link_id = link_id; + l1sap.u.data.fn = fn; + l1sap.u.data.rssi = 0; // Radio Signal Strength Indicator. Best -> 0. + l1sap.u.data.ber10k = 0; // Bit Error Rate in 0.01%. Best -> 0. + l1sap.u.data.ta_offs_qbits = 0; // Burst time of arrival in quarter bits. Probably used for Timing Advance calc. Best -> 0. + l1sap.u.data.lqual_cb = 10 * signal_dbm; // Link quality in centiBel = 10 * db. + l1sap.u.data.pdch_presence_info = PRES_INFO_UNKNOWN; break; case GSMTAP_CHANNEL_AGCH: case GSMTAP_CHANNEL_PCH: case GSMTAP_CHANNEL_BCCH: LOGP(LOGL_NOTICE, DL1P, - "Ignore incoming msg - channel type downlink only!"); + "Ignore incoming msg - channel type downlink only!\n"); goto nomessage; + case GSMTAP_CHANNEL_SDCCH: case GSMTAP_CHANNEL_CCCH: case GSMTAP_CHANNEL_PACCH: case GSMTAP_CHANNEL_PDCH: @@ -96,21 +208,21 @@ static void virt_um_rcv_cb(struct virt_um_inst *vui, struct msgb *msg) case GSMTAP_CHANNEL_CBCH51: case GSMTAP_CHANNEL_CBCH52: LOGP(LOGL_NOTICE, DL1P, - "Ignore incoming msg - channel type not supported!"); + "Ignore incoming msg - channel type not supported!\n"); goto nomessage; default: LOGP(LOGL_NOTICE, DL1P, - "Ignore incoming msg - channel type unknown."); + "Ignore incoming msg - channel type unknown.\n"); goto nomessage; } - /* forward primitive */ + /* forward primitive, forwarded msg will not be freed */ l1sap_up(pinst->trx, &l1sap); - DEBUGP(DL1P, "Message forwarded to layer 2."); + DEBUGP(DL1P, "Message forwarded to layer 2.\n"); return; // handle memory deallocation - nomessage: free(msg); + nomessage: talloc_free(msg); } /* called by common part once OML link is established */ @@ -333,9 +445,9 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) break; } /* activate dedicated channel */ - trx_sched_set_lchan(sched, chan_nr, 0x00, 1); + trx_sched_set_lchan(sched, chan_nr, LID_DEDIC, 1); /* activate associated channel */ - trx_sched_set_lchan(sched, chan_nr, 0x40, 1); + trx_sched_set_lchan(sched, chan_nr, LID_SACCH, 1); /* set mode */ trx_sched_set_mode(sched, chan_nr, lchan->rsl_cmode, diff --git a/src/osmo-bts-virtual/scheduler_virtbts.c b/src/osmo-bts-virtual/scheduler_virtbts.c index 1e9630e0..9d4a211a 100644 --- a/src/osmo-bts-virtual/scheduler_virtbts.c +++ b/src/osmo-bts-virtual/scheduler_virtbts.c @@ -44,50 +44,57 @@ #include "virtual_um.h" -extern void *tall_bts_ctx; - /** * Send a message over the virtual um interface. * This will at first wrap the msg with a gsmtap header and then write it to the declared multicast socket. + * TODO: we might want to remove unused argument uint8_t tn */ static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, enum trx_chan_type chan, struct msgb *msg) { const struct trx_chan_desc *chdesc = &trx_chan_desc[chan]; - uint8_t chan_type, timeslot, subslot, signal_dbm, signal_snr; - rsl_dec_chan_nr(chdesc->chan_nr, &chan_type, &subslot, ×lot); - if (chan_type == RSL_CHAN_PCH_AGCH) { - if (L1SAP_FN2CCCHBLOCK(fn) >= 1) { - chan_type = GSMTAP_CHANNEL_PCH; - } else { - chan_type = GSMTAP_CHANNEL_AGCH; - } + struct msgb *outmsg; // msg to send with gsmtap header prepended + uint16_t arfcn = l1t->trx->arfcn; // arfcn of the tranceiver the message is send with + uint8_t signal_dbm = 63; // signal strength, 63 is best + uint8_t snr = 63; // signal noise ratio, 63 is best + uint8_t *data = msgb_l2(msg); // data to transmit (whole message without l1 header) + uint8_t data_len = msgb_l2len(msg); // length of data + uint8_t rsl_chantype; // rsl chan type (8.58, 9.3.1) + uint8_t subslot; // multiframe subslot to send msg in (tch -> 0-26, bcch/ccch -> 0-51) + uint8_t timeslot; // tdma timeslot to send in (0-7) + uint8_t gsmtap_chantype; // the gsmtap channel + + rsl_dec_chan_nr(chdesc->chan_nr, &rsl_chantype, &subslot, ×lot); + // in osmocom, agch is only sent on ccch block 0. no idea why. this seems to cause false gsmtap channel types for agch and pch. + if (rsl_chantype == RSL_CHAN_PCH_AGCH && L1SAP_FN2CCCHBLOCK(fn) == 0) { + gsmtap_chantype = GSMTAP_CHANNEL_PCH; } else { - chan_type = chantype_rsl2gsmtap(chan_type, chdesc->link_id); // the logical channel type + gsmtap_chantype = chantype_rsl2gsmtap(rsl_chantype, + chdesc->link_id); // the logical channel type } - //uint8_t timeslot = tn; // indicates the physical channel - //uint8_t subslot = 0; // indicates the logical channel subslot on the physical channel FIXME: calculate - signal_dbm = 63; // the signal strength is not needed in virt phy - signal_snr = 40; // the signal to noice ratio is not needed in virt phy - uint8_t *data = msgb_l2(msg); // data bits to transmit (whole message without l1 header) - uint8_t data_len = msgb_l2len(msg); - struct msgb *outmsg; + + outmsg = gsmtap_makemsg(l1t->trx->arfcn, timeslot, gsmtap_chantype, + subslot, fn, signal_dbm, snr, data, data_len); // TODO: encrypt and encode message data - outmsg = gsmtap_makemsg(l1t->trx->arfcn, timeslot, chan_type, subslot, - fn, signal_dbm, signal_snr, data, data_len); if (outmsg) { struct phy_instance *pinst = trx_phy_instance(l1t->trx); - struct virt_um_inst *virt_um = pinst->phy_link->u.virt.virt_um; - if (virt_um_write_msg(virt_um, outmsg) == -1) { - struct gsmtap_hdr *gh = (struct gsmtap_hdr *)msgb_data( - outmsg); + struct gsmtap_hdr *gh = msgb_data(outmsg); + if (virt_um_write_msg(pinst->phy_link->u.virt.virt_um, outmsg) + == -1) { LOGP(DL1C, LOGL_ERROR, - "Message could not be written to virtual UM! arfcn = %u gsmtap_chan=%u fn=%u ts=%u\n", - gh->arfcn, gh->type, gh->frame_number, - gh->timeslot); + "Gsmtap msg could not send to virt um - (arfcn=%u, type=%u, subtype=%u, timeslot=%u, subslot=%u)\n", + gh->arfcn, gh->type, gh->sub_type, + gh->timeslot, gh->sub_slot); + } else { + DEBUGP(DL1C, + "Sending gsmtap msg to virt um - (arfcn=%u, type=%u, subtype=%u, timeslot=%u, subslot=%u)\n", + gh->arfcn, gh->type, gh->sub_type, + gh->timeslot, gh->sub_slot); } + } else { + LOGP(DL1C, LOGL_ERROR, "Gsmtap msg could not be created!\n"); } /* free message */ @@ -128,7 +135,6 @@ ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, return NULL; /* get mac block from queue */ - // what queue is that and who does fill it? msg = _sched_dequeue_prim(l1t, tn, fn, chan); if (msg) goto got_msg; |