diff --git a/debian/copyright b/debian/copyright index 2e800a7a..0069d0cc 100644 --- a/debian/copyright +++ b/debian/copyright @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index eb4a2bba..51b047ef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/coding_scheme.c b/src/coding_scheme.c new file mode 100644 index 00000000..a6f2905c --- /dev/null +++ b/src/coding_scheme.c @@ -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 +#include + +#include + +#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; +} diff --git a/src/coding_scheme.h b/src/coding_scheme.h index 3705ea42..b0b85e34 100644 --- a/src/coding_scheme.h +++ b/src/coding_scheme.h @@ -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); diff --git a/src/decoding.cpp b/src/decoding.cpp index 0dbb10aa..3410291e 100644 --- a/src/decoding.cpp +++ b/src/decoding.cpp @@ -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: diff --git a/src/encoding.cpp b/src/encoding.cpp index 019de52f..58df95f0 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -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 ((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 ((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 ((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 ((void *)data); diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index f63fac30..7ac5ab16 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -26,6 +26,7 @@ #include #include #include +#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; diff --git a/src/gprs_coding_scheme.cpp b/src/gprs_coding_scheme.cpp index c0955d33..0616a49c 100644 --- a/src/gprs_coding_scheme.cpp +++ b/src/gprs_coding_scheme.cpp @@ -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; } diff --git a/src/gprs_coding_scheme.h b/src/gprs_coding_scheme.h index 80f85024..56ee0023 100644 --- a/src/gprs_coding_scheme.h +++ b/src/gprs_coding_scheme.h @@ -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); diff --git a/src/rlc.cpp b/src/rlc.cpp index 323fde40..e5067c9d 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -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, diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 7b0052fb..2f4781ca 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -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) == diff --git a/tests/edge/EdgeTest.cpp b/tests/edge/EdgeTest.cpp index 9db90ca1..23abadab 100644 --- a/tests/edge/EdgeTest.cpp +++ b/tests/edge/EdgeTest.cpp @@ -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;