MCS: move HeaderType enum outside of class definition

Move functions which compute number of blocks or bits depending on
header type and corresponding enum outside of GprsCodingScheme
class. This will allows us to use standard libosmocore value_sting
functions in upcoming patches for IA Rest Octet encoding/decoding.

Change-Id: Id0873f85e1f16a72e17e7fbc4ad76b194917067f
This commit is contained in:
Max 2019-03-13 17:14:13 +01:00
parent d5ffeb5e63
commit 51754b6f35
12 changed files with 126 additions and 92 deletions

1
debian/copyright vendored
View File

@ -15,6 +15,7 @@ Files: src/gprs_ms_storage.h
src/gprs_ms.h
src/gprs_coding_scheme.cpp
src/gprs_coding_scheme.h
src/coding_scheme.c
src/coding_scheme.h
src/cxx_linuxlist.h
src/pcu_vty_functions.cpp

View File

@ -63,6 +63,7 @@ libgprs_la_SOURCES = \
rlc.cpp \
osmobts_sock.cpp \
gprs_codel.c \
coding_scheme.c \
gprs_coding_scheme.cpp \
egprs_rlc_compression.cpp

65
src/coding_scheme.c Normal file
View File

@ -0,0 +1,65 @@
/* coding_scheme.c
*
* Copyright (C) 2019 by sysmocom s.f.m.c. GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdint.h>
#include <stdbool.h>
#include <osmocom/core/utils.h>
#include "coding_scheme.h"
static struct {
struct {
uint8_t data_header_bits;
} uplink, downlink;
uint8_t data_block_header_bits;
uint8_t num_blocks;
const char *name;
} hdr_type_info[NUM_HEADER_TYPES] = {
{ { 0 }, { 0 }, 0, 0, "INVALID" },
{ { 1 * 8 + 0 }, { 1 * 8 + 0 }, 0, 0, "CONTROL" },
{ { 3 * 8 + 0 }, { 3 * 8 + 0 }, 0, 1, "GPRS_DATA" },
{ { 5 * 8 + 6 }, { 5 * 8 + 0 }, 2, 2, "EGPRS_DATA_TYPE1" },
{ { 4 * 8 + 5 }, { 3 * 8 + 4 }, 2, 1, "EGPRS_DATA_TYPE2" },
{ { 3 * 8 + 7 }, { 3 * 8 + 7 }, 2, 1, "EGPRS_DATA_TYPE3" },
};
uint8_t num_data_blocks(enum HeaderType ht)
{
OSMO_ASSERT(ht < NUM_HEADER_TYPES);
return hdr_type_info[ht].num_blocks;
}
uint8_t num_data_header_bits_UL(enum HeaderType ht)
{
OSMO_ASSERT(ht < NUM_HEADER_TYPES);
return hdr_type_info[ht].uplink.data_header_bits;
}
uint8_t num_data_header_bits_DL(enum HeaderType ht)
{
OSMO_ASSERT(ht < NUM_HEADER_TYPES);
return hdr_type_info[ht].downlink.data_header_bits;
}
uint8_t num_data_block_header_bits(enum HeaderType ht)
{
OSMO_ASSERT(ht < NUM_HEADER_TYPES);
return hdr_type_info[ht].data_block_header_bits;
}

View File

@ -27,3 +27,20 @@ enum CodingScheme {
MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9,
NUM_SCHEMES
};
enum HeaderType {
HEADER_INVALID,
HEADER_GPRS_CONTROL,
HEADER_GPRS_DATA,
HEADER_EGPRS_DATA_TYPE_1,
HEADER_EGPRS_DATA_TYPE_2,
HEADER_EGPRS_DATA_TYPE_3,
NUM_HEADER_TYPES
};
enum HeaderType headerTypeData(enum CodingScheme mcs);
uint8_t num_data_blocks(enum HeaderType ht);
uint8_t num_data_header_bits_UL(enum HeaderType ht);
uint8_t num_data_header_bits_DL(enum HeaderType ht);
uint8_t num_data_block_header_bits(enum HeaderType ht);

View File

@ -355,16 +355,16 @@ int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
{
unsigned int cur_bit = 0;
switch(cs.headerTypeData()) {
case GprsCodingScheme::HEADER_GPRS_DATA :
case HEADER_GPRS_DATA :
cur_bit = rlc_parse_ul_data_header_gprs(rlc, data, cs);
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3 :
case HEADER_EGPRS_DATA_TYPE_3 :
cur_bit = rlc_parse_ul_data_header_egprs_type_3(rlc, data, cs);
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2 :
case HEADER_EGPRS_DATA_TYPE_2 :
cur_bit = rlc_parse_ul_data_header_egprs_type_2(rlc, data, cs);
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1 :
case HEADER_EGPRS_DATA_TYPE_1 :
cur_bit = rlc_parse_ul_data_header_egprs_type_1(rlc, data, cs);
break;
default:

View File

@ -1118,7 +1118,7 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
unsigned int bsn_delta;
switch(cs.headerTypeData()) {
case GprsCodingScheme::HEADER_GPRS_DATA:
case HEADER_GPRS_DATA:
gprs = static_cast<struct rlc_dl_header *>
((void *)data);
@ -1134,7 +1134,7 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
gprs->bsn = rlc->block_info[0].bsn;
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1:
case HEADER_EGPRS_DATA_TYPE_1:
egprs1 = static_cast<struct gprs_rlc_dl_header_egprs_1 *>
((void *)data);
@ -1173,7 +1173,7 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
data[offs] = (data[offs] & 0b11110011) | e_fbi_header;
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2:
case HEADER_EGPRS_DATA_TYPE_2:
egprs2 = static_cast<struct gprs_rlc_dl_header_egprs_2 *>
((void *)data);
@ -1197,7 +1197,7 @@ int Encoding::rlc_write_dl_data_header(const struct gprs_rlc_data_info *rlc,
data[offs] = (data[offs] & 0b11001111) | e_fbi_header;
break;
case GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3:
case HEADER_EGPRS_DATA_TYPE_3:
egprs3 = static_cast<struct gprs_rlc_dl_header_egprs_3 *>
((void *)data);

View File

@ -26,6 +26,7 @@
#include <tbf.h>
#include <gprs_coding_scheme.h>
#include <pdch.h>
#include "coding_scheme.h"
#define BSSGP_TIMER_T1 30 /* Guards the (un)blocking procedures */
#define BSSGP_TIMER_T2 30 /* Guards the reset procedure */
@ -607,7 +608,7 @@ static unsigned count_pdch(const struct gprs_rlcmac_bts *bts)
static uint32_t gprs_bssgp_max_leak_rate(GprsCodingScheme cs, int num_pdch)
{
int bytes_per_rlc_block = cs.maxDataBlockBytes() * cs.numDataBlocks();
int bytes_per_rlc_block = cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData());
/* n byte payload per 20ms */
return bytes_per_rlc_block * (1000 / 20) * num_pdch;

View File

@ -82,55 +82,39 @@ static struct {
uint8_t data_bytes;
uint8_t optional_padding_bits;
const char *name;
GprsCodingScheme::HeaderType data_hdr;
enum HeaderType data_hdr;
enum Family family;
} mcs_info[NUM_SCHEMES] = {
{{0, 0}, {0, 0}, 0, 0, "UNKNOWN",
GprsCodingScheme::HEADER_INVALID, FAMILY_INVALID},
HEADER_INVALID, FAMILY_INVALID},
{{23, 0}, {23, 0}, 20, 0, "CS-1",
GprsCodingScheme::HEADER_GPRS_DATA, FAMILY_INVALID},
HEADER_GPRS_DATA, FAMILY_INVALID},
{{33, 7}, {33, 7}, 30, 0, "CS-2",
GprsCodingScheme::HEADER_GPRS_DATA, FAMILY_INVALID},
HEADER_GPRS_DATA, FAMILY_INVALID},
{{39, 3}, {39, 3}, 36, 0, "CS-3",
GprsCodingScheme::HEADER_GPRS_DATA, FAMILY_INVALID},
HEADER_GPRS_DATA, FAMILY_INVALID},
{{53, 7}, {53, 7}, 50, 0, "CS-4",
GprsCodingScheme::HEADER_GPRS_DATA, FAMILY_INVALID},
HEADER_GPRS_DATA, FAMILY_INVALID},
{{26, 1}, {26, 1}, 22, 0, "MCS-1",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
{{32, 1}, {32, 1}, 28, 0, "MCS-2",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, FAMILY_B},
HEADER_EGPRS_DATA_TYPE_3, FAMILY_B},
{{41, 1}, {41, 1}, 37, 48, "MCS-3",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, FAMILY_A},
HEADER_EGPRS_DATA_TYPE_3, FAMILY_A},
{{48, 1}, {48, 1}, 44, 0, "MCS-4",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
HEADER_EGPRS_DATA_TYPE_3, FAMILY_C},
{{60, 7}, {59, 6}, 56, 0, "MCS-5",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2, FAMILY_B},
HEADER_EGPRS_DATA_TYPE_2, FAMILY_B},
{{78, 7}, {77, 6}, 74, 48, "MCS-6",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2, FAMILY_A},
HEADER_EGPRS_DATA_TYPE_2, FAMILY_A},
{{118, 2}, {117, 4}, 56, 0, "MCS-7",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1, FAMILY_B},
HEADER_EGPRS_DATA_TYPE_1, FAMILY_B},
{{142, 2}, {141, 4}, 68, 0, "MCS-8",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
{{154, 2}, {153, 4}, 74, 0, "MCS-9",
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
};
static struct {
struct {
uint8_t data_header_bits;
} uplink, downlink;
uint8_t data_block_header_bits;
uint8_t num_blocks;
const char *name;
} hdr_type_info[GprsCodingScheme::NUM_HEADER_TYPES] = {
{{0}, {0}, 0, 0, "INVALID"},
{{1*8 + 0}, {1*8 + 0}, 0, 0, "CONTROL"},
{{3*8 + 0}, {3*8 + 0}, 0, 1, "GPRS_DATA"},
{{5*8 + 6}, {5*8 + 0}, 2, 2, "EGPRS_DATA_TYPE1"},
{{4*8 + 5}, {3*8 + 4}, 2, 1, "EGPRS_DATA_TYPE2"},
{{3*8 + 7}, {3*8 + 7}, 2, 1, "EGPRS_DATA_TYPE3"},
HEADER_EGPRS_DATA_TYPE_1, FAMILY_A},
};
GprsCodingScheme GprsCodingScheme::getBySizeUL(unsigned size)
@ -210,32 +194,12 @@ uint8_t GprsCodingScheme::optionalPaddingBits() const
return mcs_info[m_scheme].optional_padding_bits;
}
uint8_t GprsCodingScheme::numDataBlocks() const
{
return hdr_type_info[headerTypeData()].num_blocks;
}
uint8_t GprsCodingScheme::numDataHeaderBitsUL() const
{
return hdr_type_info[headerTypeData()].uplink.data_header_bits;
}
uint8_t GprsCodingScheme::numDataHeaderBitsDL() const
{
return hdr_type_info[headerTypeData()].downlink.data_header_bits;
}
uint8_t GprsCodingScheme::numDataBlockHeaderBits() const
{
return hdr_type_info[headerTypeData()].data_block_header_bits;
}
const char *GprsCodingScheme::name() const
{
return mcs_info[m_scheme].name;
}
GprsCodingScheme::HeaderType GprsCodingScheme::headerTypeData() const
enum HeaderType GprsCodingScheme::headerTypeData() const
{
return mcs_info[m_scheme].data_hdr;
}

View File

@ -40,16 +40,6 @@ public:
EGPRS,
};
enum HeaderType {
HEADER_INVALID,
HEADER_GPRS_CONTROL,
HEADER_GPRS_DATA,
HEADER_EGPRS_DATA_TYPE_1,
HEADER_EGPRS_DATA_TYPE_2,
HEADER_EGPRS_DATA_TYPE_3,
NUM_HEADER_TYPES
};
GprsCodingScheme(CodingScheme s = UNKNOWN);
operator bool() const {return m_scheme != UNKNOWN;}
@ -83,13 +73,9 @@ public:
uint8_t spareBitsUL() const;
uint8_t spareBitsDL() const;
uint8_t maxDataBlockBytes() const;
uint8_t numDataBlocks() const;
uint8_t numDataHeaderBitsUL() const;
uint8_t numDataHeaderBitsDL() const;
uint8_t numDataBlockHeaderBits() const;
uint8_t optionalPaddingBits() const;
const char *name() const;
HeaderType headerTypeData() const;
enum HeaderType headerTypeData() const;
static GprsCodingScheme getBySizeUL(unsigned size);
static GprsCodingScheme getGprsByNum(unsigned num);

View File

@ -336,7 +336,7 @@ static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
rlc->es_p = 0;
rlc->rrbp = 0;
rlc->pr = 0;
rlc->num_data_blocks = cs.numDataBlocks();
rlc->num_data_blocks = num_data_blocks(cs.headerTypeData());
rlc->with_padding = with_padding;
OSMO_ASSERT(rlc->num_data_blocks <= ARRAY_SIZE(rlc->block_info));
@ -347,7 +347,7 @@ static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
rlc->data_offs_bits[i] =
header_bits + padding_bits +
(i+1) * cs.numDataBlockHeaderBits() +
(i+1) * num_data_block_header_bits(cs.headerTypeData()) +
i * 8 * rlc->block_info[0].data_len;
}
}
@ -356,7 +356,7 @@ void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
GprsCodingScheme cs, bool with_padding, const unsigned int spb)
{
return gprs_rlc_data_header_init(rlc, cs, with_padding,
cs.numDataHeaderBitsDL(), spb);
num_data_header_bits_DL(cs.headerTypeData()), spb);
}
void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
@ -367,7 +367,7 @@ void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
* for both DL and UL
*/
return gprs_rlc_data_header_init(rlc, cs, with_padding,
cs.numDataHeaderBitsUL(), 0);
num_data_header_bits_UL(cs.headerTypeData()), 0);
}
void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,

View File

@ -457,7 +457,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn,
bts->rlc_resent();
}
*may_combine = m_rlc.block(bsn)->cs_current_trans.numDataBlocks() > 1;
*may_combine = num_data_blocks(m_rlc.block(bsn)->cs_current_trans.headerTypeData()) > 1;
return bsn;
}
@ -1259,7 +1259,7 @@ enum egprs_rlc_dl_reseg_bsn_state
* MCS4: second segment starts at 44/2 = 22
*/
if (cs_current_trans.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3) {
HEADER_EGPRS_DATA_TYPE_3) {
if (*block_status_dl == EGPRS_RESEG_FIRST_SEG_SENT) {
switch (CodingScheme(cs_init)) {
case MCS6 :
@ -1287,9 +1287,9 @@ enum egprs_rlc_dl_reseg_bsn_state
}
return EGPRS_RESEG_SECOND_SEG_SENT;
} else if ((cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1) ||
HEADER_EGPRS_DATA_TYPE_1) ||
(cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2)) {
HEADER_EGPRS_DATA_TYPE_2)) {
return EGPRS_RESEG_FIRST_SEG_SENT;
} else if ((CodingScheme(cs_init) ==
MCS4) &&
@ -1327,7 +1327,7 @@ enum egprs_rlcmac_dl_spb gprs_rlcmac_dl_tbf::get_egprs_dl_spb(const int bsn)
/* Table 10.4.8b.1 of 44.060 */
if (cs_current_trans.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3) {
HEADER_EGPRS_DATA_TYPE_3) {
/*
* if we are sending the second segment the spb should be 3
* other wise it should be 2
@ -1338,9 +1338,9 @@ enum egprs_rlcmac_dl_spb gprs_rlcmac_dl_tbf::get_egprs_dl_spb(const int bsn)
bts->spb_downlink_second_segment();
return EGPRS_RLCMAC_DL_SEC_SEG;
} else if ((cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1) ||
HEADER_EGPRS_DATA_TYPE_1) ||
(cs_init.headerTypeData() ==
GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2)) {
HEADER_EGPRS_DATA_TYPE_2)) {
bts->spb_downlink_first_segment();
return EGPRS_RLCMAC_DL_FIRST_SEG;
} else if ((CodingScheme(cs_init) ==

View File

@ -71,8 +71,8 @@ static void check_coding_scheme(GprsCodingScheme& cs, GprsCodingScheme::Mode mod
OSMO_ASSERT(expected_size == cs.sizeDL());
/* Check data block sizes */
OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesDL());
OSMO_ASSERT(cs.maxDataBlockBytes() * cs.numDataBlocks() < cs.maxBytesUL());
OSMO_ASSERT(cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData()) < cs.maxBytesDL());
OSMO_ASSERT(cs.maxDataBlockBytes() * num_data_blocks(cs.headerTypeData()) < cs.maxBytesUL());
/* Check inc/dec */
new_cs = cs;
@ -168,8 +168,7 @@ static void test_coding_scheme()
last_size_DL = current_cs.maxBytesDL();
/* Check header types */
OSMO_ASSERT(current_cs.headerTypeData() ==
GprsCodingScheme::HEADER_GPRS_DATA);
OSMO_ASSERT(current_cs.headerTypeData() == HEADER_GPRS_DATA);
check_coding_scheme(current_cs, GprsCodingScheme::GPRS);
}
@ -1099,7 +1098,7 @@ static void test_rlc_unaligned_copy()
test_block[cs.maxDataBlockBytes()-1] = pattern ^ 0xff;
for (block_idx = 0;
block_idx < cs.numDataBlocks();
block_idx < num_data_blocks(cs.headerTypeData());
block_idx++)
{
struct gprs_rlc_data_info rlc;