905 lines
31 KiB
C
905 lines
31 KiB
C
/* rlcmac_prim_test.c
|
|
*
|
|
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
#include <osmocom/core/application.h>
|
|
#include <osmocom/core/logging.h>
|
|
#include <osmocom/core/utils.h>
|
|
#include <osmocom/core/msgb.h>
|
|
#include <osmocom/core/fsm.h>
|
|
#include <osmocom/core/timer.h>
|
|
#include <osmocom/core/timer_compat.h>
|
|
#include <osmocom/core/select.h>
|
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
|
#include <osmocom/gsm/gsm48_rest_octets.h>
|
|
|
|
#include <osmocom/gprs/rlcmac/rlcmac.h>
|
|
#include <osmocom/gprs/rlcmac/csn1_defs.h>
|
|
#include <osmocom/gprs/rlcmac/gre.h>
|
|
#include <osmocom/gprs/rlcmac/rlc.h>
|
|
#include <osmocom/gprs/rlcmac/rlc_window.h>
|
|
#include <osmocom/gprs/rlcmac/types_private.h>
|
|
#include <osmocom/gprs/rlcmac/sched.h>
|
|
|
|
static void *tall_ctx = NULL;
|
|
|
|
uint8_t last_rach_req_ra = 0;
|
|
|
|
/**
|
|
MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: GPRS Mobility Management
|
|
Address field SAPI: LLGMM
|
|
0... .... = Protocol Discriminator_bit: OK
|
|
.0.. .... = Command/Response bit: DownLink/UpLink = Response/Command
|
|
.... 0001 = SAPI: GPRS Mobility Management (1)
|
|
Unconfirmed Information format - UI: UI format: 0x6, Spare bits: 0x0, N(U): 0, E bit: non encrypted frame, PM bit: FCS covers only the frame header and first N202 octets of the information field
|
|
110. .... .... .... = UI format: 0x6
|
|
...0 0... .... .... = Spare bits: 0x0
|
|
.... .000 0000 00.. = N(U): 0
|
|
.... .... .... ..0. = E bit: non encrypted frame
|
|
.... .... .... ...0 = PM bit: FCS covers only the frame header and first N202 octets of the information field
|
|
FCS: 0xf218e2 (correct)
|
|
GSM A-I/F DTAP - Attach Request
|
|
Protocol Discriminator: GPRS mobility management messages (8)
|
|
DTAP GPRS Mobility Management Message Type: Attach Request (0x01)
|
|
MS Network Capability
|
|
Attach Type
|
|
Ciphering Key Sequence Number
|
|
DRX Parameter
|
|
Mobile Identity - IMSI (262420000000017)
|
|
Routing Area Identification - Old routing area identification - RAI: 262-42-27780-68
|
|
MS Radio Access Capability
|
|
*/
|
|
static uint8_t pdu_llc_gmm_att_req[] = {
|
|
0x01, 0xc0, 0x00, 0x08, 0x01, 0x01, 0xd5, 0x71, 0x00, 0x00, 0x08, 0x29, 0x26,
|
|
0x24, 0x00, 0x00, 0x00, 0x00, 0x71, 0x62, 0xf2, 0x24, 0x6c, 0x84, 0x44, 0x04,
|
|
0x11, 0xe5, 0x10, 0x00, 0xe2, 0x18, 0xf2
|
|
};
|
|
|
|
/**
|
|
GSM CCCH - Immediate Assignment
|
|
L2 Pseudo Length
|
|
0010 11.. = L2 Pseudo Length value: 11
|
|
.... 0110 = Protocol discriminator: Radio Resources Management messages (0x6)
|
|
.... 0110 = Protocol discriminator: Radio Resources Management messages (0x6)
|
|
0000 .... = Skip Indicator: No indication of selected PLMN (0)
|
|
Message Type: Immediate Assignment
|
|
Page Mode
|
|
.... 0000 = Page Mode: Normal paging (0)
|
|
Dedicated mode or TBF
|
|
0001 .... = Dedicated mode or TBF: This message assigns an uplink TBF or is the second message of two in a two-message assignment of an uplink or downlink TBF (1)
|
|
Packet Channel Description
|
|
0000 1... = Channel Type: 1
|
|
.... .111 = Timeslot: 7
|
|
111. .... = Training Sequence: 7
|
|
.... .0.. = Spare: 0x00
|
|
.... ..11 0110 0111 = Single channel ARFCN: 871
|
|
Request Reference
|
|
Random Access Information (RA): 120
|
|
0000 1... = T1': 1
|
|
.... .001 011. .... = T3: 11
|
|
...0 1011 = T2: 11
|
|
[RFN: 1337]
|
|
Timing Advance
|
|
Timing advance value: 0
|
|
Mobile Allocation
|
|
Length: 0
|
|
IA Rest Octets
|
|
H... .... = First Discriminator Bit: High
|
|
.H.. .... = Second Discriminator Bit: High
|
|
..0. .... = Discriminator Bit: Packet Assignment
|
|
...0 .... = Discriminator Bit: Packet Uplink Assignment
|
|
Packet Uplink Assignment
|
|
.... 1... = Packet Uplink Assignment: Normal
|
|
.... .000 00.. .... = TFI_Assignment: 0
|
|
..0. .... = Polling: no action is required from MS
|
|
...0 .... = Allocation Type: Dynamic Allocation (mandatory after Rel-4)
|
|
.... 000. = USF: 0
|
|
.... ...0 = USF_granularity: the mobile station shall transmit one RLC/MAC block
|
|
0... .... = P0: Not Present
|
|
.01. .... = Channel_Coding_Command: CS-2 (1)
|
|
...1 .... = TLLI_Block_Channel_Coding: mobile station shall use coding scheme as specified by the corresponding CHANNEL CODING COMMAND or EGPRS CHANNEL CODING COMMAND field
|
|
.... 0... = Alpha: Not Present
|
|
.... .000 00.. .... = Gamma: 0 dB (0)
|
|
..0. .... = Timing Advance Index: Not Present
|
|
...0 .... = TBF Starting Time: Not Present
|
|
.... L... = Additions in R99: Not Present
|
|
.... .L.. = Additions in Rel-6: Not Present
|
|
.... ..L. = Additions in Rel-10: Not Present
|
|
.... ...L = Additions in Rel-13: Not Present
|
|
Padding Bits: default padding
|
|
*/
|
|
static uint8_t ccch_imm_ass_pkt_ul_tbf_normal[] = {
|
|
0x2d, 0x06, 0x3f, 0x10, 0x0f, 0xe3, 0x67, 0x78, 0x09, 0x6b,
|
|
0x00, 0x00, 0xc8, 0x00, 0x30, 0x0b,
|
|
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b
|
|
};
|
|
|
|
/*
|
|
GSM CCCH - Immediate Assignment
|
|
L2 Pseudo Length
|
|
0010 11.. = L2 Pseudo Length value: 11
|
|
.... 0110 = Protocol discriminator: Radio Resources Management messages (0x6)
|
|
.... 0110 = Protocol discriminator: Radio Resources Management messages (0x6)
|
|
0000 .... = Skip Indicator: No indication of selected PLMN (0)
|
|
Message Type: Immediate Assignment
|
|
Page Mode
|
|
.... 0000 = Page Mode: Normal paging (0)
|
|
Dedicated mode or TBF
|
|
0011 .... = Dedicated mode or TBF: This message assigns a downlink TBF to the mobile station identified in the IA Rest Octets IE (3)
|
|
Packet Channel Description
|
|
0000 1... = Channel Type: 1
|
|
.... .111 = Timeslot: 7
|
|
111. .... = Training Sequence: 7
|
|
.... .0.. = Spare: 0x00
|
|
.... ..11 0110 0111 = Single channel ARFCN: 871
|
|
Request Reference
|
|
Random Access Information (RA): 125
|
|
1000 0... = T1': 16
|
|
.... .000 000. .... = T3: 0
|
|
...0 0000 = T2: 0
|
|
[RFN: 21216]
|
|
Timing Advance
|
|
Timing advance value: 28
|
|
Mobile Allocation
|
|
Length: 0
|
|
IA Rest Octets
|
|
H... .... = First Discriminator Bit: High
|
|
.H.. .... = Second Discriminator Bit: High
|
|
..0. .... = Discriminator Bit: Packet Assignment
|
|
...1 .... = Discriminator Bit: Packet Downlink Assignment
|
|
Packet Downlink Assignment
|
|
.... 0000 0000 0000 0000 0000 0000 0000 0001 .... = TLLI: 0x00000001
|
|
.... 1... = TFI Assignment (etc): Present
|
|
.... .000 00.. .... = TFI_Assignment: 0
|
|
..0. .... = RLC_Mode: RLC acknowledged mode
|
|
...0 .... = Alpha: Not Present
|
|
.... 0000 0... .... = Gamma: 0 dB (0)
|
|
.0.. .... = Polling: no action is required from MS
|
|
..0. .... = TA_Valid: the timing advance value is not valid
|
|
...0 .... = Timing Advance Index: Not Present
|
|
.... 0... = TBF Starting Time: Not Present
|
|
.... .0.. = P0: Not Present
|
|
.... ..L. = Additions in R99: Not Present
|
|
.... ...L = Additions in Rel-6: Not Present
|
|
L... .... = Additions in Rel-7: Not Present
|
|
.L.. .... = Additions in Rel-10: Not Present
|
|
..L. .... = Additions in Rel-13: Not Present
|
|
Padding Bits: default padding
|
|
*/
|
|
static uint8_t ccch_imm_ass_pkt_dl_tbf[] = {
|
|
0x2d, 0x06, 0x3f, 0x30, 0x0f, 0xe3, 0x67, 0x7d, 0x80, 0x00,
|
|
0x1c, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03,
|
|
0x2b, 0x2b, 0x2b, 0x2b
|
|
};
|
|
|
|
#define clock_debug(fmt, args...) \
|
|
do { \
|
|
struct timespec ts; \
|
|
struct timeval tv; \
|
|
osmo_clock_gettime(CLOCK_MONOTONIC, &ts); \
|
|
osmo_gettimeofday(&tv, NULL); \
|
|
fprintf(stdout, "sys={%lu.%06lu}, mono={%lu.%06lu}: " fmt "\n", \
|
|
tv.tv_sec, tv.tv_usec, ts.tv_sec, ts.tv_nsec/1000, ##args); \
|
|
} while (0)
|
|
|
|
static void clock_override_enable(bool enable)
|
|
{
|
|
osmo_gettimeofday_override = enable;
|
|
osmo_clock_override_enable(CLOCK_MONOTONIC, enable);
|
|
}
|
|
|
|
static void clock_override_set(long sec, long usec)
|
|
{
|
|
struct timespec *mono;
|
|
osmo_gettimeofday_override_time.tv_sec = sec;
|
|
osmo_gettimeofday_override_time.tv_usec = usec;
|
|
mono = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
|
|
mono->tv_sec = sec;
|
|
mono->tv_nsec = usec*1000;
|
|
|
|
clock_debug("clock_override_set");
|
|
}
|
|
|
|
static void clock_override_add_debug(long sec, long usec, bool dbg)
|
|
{
|
|
osmo_gettimeofday_override_add(sec, usec);
|
|
osmo_clock_override_add(CLOCK_MONOTONIC, sec, usec*1000);
|
|
if (dbg)
|
|
clock_debug("clock_override_add");
|
|
}
|
|
#define clock_override_add(sec, usec) clock_override_add_debug(sec, usec, true)
|
|
|
|
|
|
static inline unsigned fn2bn(unsigned fn)
|
|
{
|
|
return (fn % 52) / 4;
|
|
}
|
|
|
|
static inline unsigned fn_next_block(unsigned fn)
|
|
{
|
|
unsigned bn = fn2bn(fn) + 1;
|
|
fn = fn - (fn % 52);
|
|
fn += bn * 4 + bn / 3;
|
|
return fn % GSM_MAX_FN;
|
|
}
|
|
|
|
static struct osmo_gprs_rlcmac_prim *create_dl_ctrl_block_buf(uint8_t *buf, int num_bytes, uint8_t tn, uint32_t fn)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
|
|
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(tn, fn, 0, 0, 0,
|
|
NULL, num_bytes);
|
|
rlcmac_prim->l1ctl.pdch_data_ind.data = msgb_put(rlcmac_prim->oph.msg, num_bytes);
|
|
memcpy(rlcmac_prim->l1ctl.pdch_data_ind.data, buf, num_bytes);
|
|
return rlcmac_prim;
|
|
}
|
|
|
|
static struct osmo_gprs_rlcmac_prim *create_dl_ctrl_block(RlcMacDownlink_t *dl_block, uint8_t tn, uint32_t fn)
|
|
{
|
|
struct bitvec *rlc_block;
|
|
uint8_t buf[64];
|
|
int num_bytes;
|
|
|
|
rlc_block = bitvec_alloc(23, tall_ctx);
|
|
|
|
OSMO_ASSERT(osmo_gprs_rlcmac_encode_downlink(rlc_block, dl_block) == 0);
|
|
num_bytes = bitvec_pack(rlc_block, &buf[0]);
|
|
OSMO_ASSERT((size_t)num_bytes < sizeof(buf));
|
|
bitvec_free(rlc_block);
|
|
|
|
return create_dl_ctrl_block_buf(&buf[0], num_bytes, tn, fn);
|
|
}
|
|
|
|
static void ul_ack_nack_init(RlcMacDownlink_t *dl_block, uint8_t ul_tfi, enum gprs_rlcmac_coding_scheme cs)
|
|
{
|
|
Packet_Uplink_Ack_Nack_t *ack = &dl_block->u.Packet_Uplink_Ack_Nack;
|
|
PU_AckNack_GPRS_t *gprs = &ack->u.PU_AckNack_GPRS_Struct;
|
|
|
|
memset(dl_block, 0, sizeof(*dl_block));
|
|
dl_block->PAYLOAD_TYPE = GPRS_RLCMAC_PT_CONTROL_BLOCK;
|
|
dl_block->RRBP = 0;
|
|
dl_block->SP = 0;
|
|
dl_block->USF = 0x00;
|
|
dl_block->u.MESSAGE_TYPE = OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ACK_NACK;
|
|
|
|
ack->MESSAGE_TYPE = OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ACK_NACK;
|
|
ack->PAGE_MODE = GPRS_RLCMAC_PAGE_MODE_NORMAL;
|
|
ack->UPLINK_TFI = ul_tfi;
|
|
ack->UnionType = 0; /* GPRS */
|
|
|
|
gprs->CHANNEL_CODING_COMMAND = cs;
|
|
}
|
|
|
|
static void ul_ack_nack_mark(Ack_Nack_Description_t *ack_desc, unsigned int idx, bool received)
|
|
{
|
|
//ack_desc->RECEIVED_BLOCK_BITMAP[sizeof(ack_desc->RECEIVED_BLOCK_BITMAP) - 1] = 0xff;
|
|
//memset(ack_desc->RECEIVED_BLOCK_BITMAP, 0xff, sizeof(ack_desc->RECEIVED_BLOCK_BITMAP));
|
|
if (received)
|
|
ack_desc->RECEIVED_BLOCK_BITMAP[sizeof(ack_desc->RECEIVED_BLOCK_BITMAP) - idx/8 - 1] |= (1 << (idx & 0x03));
|
|
else
|
|
ack_desc->RECEIVED_BLOCK_BITMAP[sizeof(ack_desc->RECEIVED_BLOCK_BITMAP) - idx/8 - 1] &= ~(1 << (idx & 0x03));
|
|
}
|
|
|
|
static uint8_t *create_si13(uint8_t bs_cv_max /* 0..15 */)
|
|
{
|
|
static uint8_t si13_buf[GSM_MACBLOCK_LEN];
|
|
struct gsm48_system_information_type_13 *si13 = (struct gsm48_system_information_type_13 *)&si13_buf[0];
|
|
struct osmo_gsm48_si13_info si13_info;
|
|
int ret;
|
|
|
|
memset(si13, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
|
|
|
|
si13->header.rr_protocol_discriminator = GSM48_PDISC_RR;
|
|
si13->header.skip_indicator = 0;
|
|
si13->header.system_information = GSM48_MT_RR_SYSINFO_13;
|
|
|
|
si13_info = (struct osmo_gsm48_si13_info){
|
|
.cell_opts = {
|
|
.nmo = GPRS_NMO_II,
|
|
.t3168 = 2000,
|
|
.t3192 = 1500,
|
|
.drx_timer_max = 3,
|
|
.bs_cv_max = bs_cv_max,
|
|
.ctrl_ack_type_use_block = 1,
|
|
.ext_info_present = true,
|
|
.ext_info = {
|
|
.egprs_supported = 1,
|
|
.use_egprs_p_ch_req = 1,
|
|
.bep_period = 5,
|
|
.pfc_supported = 0,
|
|
.dtm_supported = 0,
|
|
.bss_paging_coordination = 1,
|
|
.ccn_active = true,
|
|
},
|
|
},
|
|
.pwr_ctrl_pars = {
|
|
.alpha = 0, /* a = 0.0 */
|
|
.t_avg_w = 16,
|
|
.t_avg_t = 16,
|
|
.pc_meas_chan = 0, /* downling measured on CCCH */
|
|
.n_avg_i = 8,
|
|
},
|
|
.bcch_change_mark = 1, /* Information about the other SIs */
|
|
.si_change_field = 0,
|
|
.rac = 33,
|
|
.spgc_ccch_sup = 0,
|
|
.net_ctrl_ord = 1 /* NC1 */,
|
|
.prio_acc_thr = 6,
|
|
};
|
|
|
|
ret = osmo_gsm48_rest_octets_si13_encode(si13->rest_octets, &si13_info);
|
|
if (ret < 0)
|
|
return NULL;
|
|
|
|
/* length is coded in bit 2 an up */
|
|
si13->header.l2_plen = 0x01;
|
|
|
|
return &si13_buf[0];
|
|
}
|
|
|
|
static int test_rlcmac_prim_up_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void *user_data)
|
|
{
|
|
const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim);
|
|
|
|
switch (rlcmac_prim->oph.sap) {
|
|
case OSMO_GPRS_RLCMAC_SAP_GMMRR:
|
|
printf("%s(): Rx %s TLLI=0x%08x\n", __func__, pdu_name, rlcmac_prim->gmmrr.page_ind.tlli);
|
|
break;
|
|
case OSMO_GPRS_RLCMAC_SAP_GRR:
|
|
printf("%s(): Rx %s TLLI=0x%08x ll=[%s]\n", __func__, pdu_name,
|
|
rlcmac_prim->grr.tlli,
|
|
osmo_hexdump(rlcmac_prim->grr.ll_pdu, rlcmac_prim->grr.ll_pdu_len));
|
|
break;
|
|
default:
|
|
printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
|
|
OSMO_ASSERT(0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int test_rlcmac_prim_down_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void *user_data)
|
|
{
|
|
const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim);
|
|
|
|
switch (rlcmac_prim->oph.sap) {
|
|
case OSMO_GPRS_RLCMAC_SAP_L1CTL:
|
|
switch (OSMO_PRIM_HDR(&rlcmac_prim->oph)) {
|
|
case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, PRIM_OP_REQUEST):
|
|
printf("%s(): Rx %s fn=%u ts=%u data_len=%u data=[%s]\n", __func__, pdu_name,
|
|
rlcmac_prim->l1ctl.pdch_data_req.fn,
|
|
rlcmac_prim->l1ctl.pdch_data_req.ts_nr,
|
|
rlcmac_prim->l1ctl.pdch_data_req.data_len,
|
|
osmo_hexdump(rlcmac_prim->l1ctl.pdch_data_req.data, rlcmac_prim->l1ctl.pdch_data_req.data_len));
|
|
break;
|
|
case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_RACH, PRIM_OP_REQUEST):
|
|
last_rach_req_ra = rlcmac_prim->l1ctl.rach_req.ra;
|
|
printf("%s(): Rx %s ra=0x%02x\n", __func__, pdu_name, last_rach_req_ra);
|
|
break;
|
|
case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF, PRIM_OP_REQUEST):
|
|
printf("%s(): Rx %s ul_tbf_nr=%u ul_slotmask=0x%02x\n", __func__, pdu_name,
|
|
rlcmac_prim->l1ctl.cfg_ul_tbf_req.ul_tbf_nr,
|
|
rlcmac_prim->l1ctl.cfg_ul_tbf_req.ul_slotmask);
|
|
break;
|
|
case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF, PRIM_OP_REQUEST):
|
|
printf("%s(): Rx %s dl_tbf_nr=%u dl_slotmask=0x%02x dl_tfi=%u\n", __func__, pdu_name,
|
|
rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_tbf_nr,
|
|
rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_slotmask,
|
|
rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_tfi);
|
|
break;
|
|
default:
|
|
printf("%s(): Rx %s\n", __func__, pdu_name);
|
|
}
|
|
break;
|
|
default:
|
|
printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
|
|
OSMO_ASSERT(0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static const uint8_t llc_dummy_command[] = {
|
|
0x43, 0xc0, 0x01, 0x2b, 0x2b, 0x2b
|
|
};
|
|
|
|
static struct msgb *create_dl_data_block(uint8_t dl_tfi, uint8_t usf, enum gprs_rlcmac_coding_scheme cs, uint8_t bsn, bool fbi, bool s_p, uint8_t rrbp)
|
|
{
|
|
struct msgb *msg = msgb_alloc(128, __func__);
|
|
struct gprs_rlcmac_rlc_dl_data_header *hdr;
|
|
struct gprs_rlcmac_rlc_li_field *lime;
|
|
|
|
hdr = (struct gprs_rlcmac_rlc_dl_data_header *)msgb_put(msg, gprs_rlcmac_mcs_size_dl(cs));
|
|
hdr->pt = 0; /* RLC/MAC block contains an RLC data block */
|
|
hdr->rrbp = rrbp;
|
|
hdr->s_p = s_p ? 1 : 0;
|
|
hdr->usf = usf;
|
|
hdr->pr = 0;
|
|
hdr->tfi = dl_tfi;
|
|
hdr->fbi = fbi ? 1 : 0;
|
|
hdr->tfi = dl_tfi;
|
|
hdr->bsn = bsn;
|
|
hdr->e = 0;
|
|
lime = &hdr->lime[0];
|
|
lime->li = sizeof(llc_dummy_command);
|
|
lime->m = 0;
|
|
lime->e = 1;
|
|
msg->l3h = &lime->ll_pdu[0];
|
|
memset(msg->l3h, 0x2b, msgb_l3len(msg));
|
|
memcpy(msg->l3h, llc_dummy_command, sizeof(llc_dummy_command));
|
|
return msg;
|
|
}
|
|
|
|
void prepare_test(void)
|
|
{
|
|
int rc;
|
|
clock_override_set(0, 0);
|
|
|
|
rc = osmo_gprs_rlcmac_init(OSMO_GPRS_RLCMAC_LOCATION_MS);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
osmo_gprs_rlcmac_prim_set_up_cb(test_rlcmac_prim_up_cb, NULL);
|
|
osmo_gprs_rlcmac_prim_set_down_cb(test_rlcmac_prim_down_cb, NULL);
|
|
}
|
|
|
|
void cleanup_test(void)
|
|
{
|
|
/* Reinit the RLCMAC layer so that data generated during the test is freed within the test context: */
|
|
osmo_gprs_rlcmac_init(OSMO_GPRS_RLCMAC_LOCATION_MS);
|
|
}
|
|
|
|
static void test_ul_tbf_attach(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
RlcMacDownlink_t dl_block;
|
|
Ack_Nack_Description_t *ack_desc = &dl_block.u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description;
|
|
uint32_t tlli = 0x2342;
|
|
uint8_t ul_tfi = 0;
|
|
uint8_t ts_nr = 7;
|
|
uint8_t usf = 0;
|
|
uint32_t rts_fn = 4;
|
|
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
sizeof(pdu_llc_gmm_att_req));
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_ul_tbf_normal) == GSM_MACBLOCK_LEN);
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) (first part) */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) (second part) */
|
|
rts_fn = fn_next_block(rts_fn);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* PCU acks it: */
|
|
ul_ack_nack_init(&dl_block, ul_tfi, GPRS_RLCMAC_CS_2);
|
|
ack_desc->STARTING_SEQUENCE_NUMBER = 1;
|
|
ack_desc->FINAL_ACK_INDICATION = 1;
|
|
ul_ack_nack_mark(ack_desc, 0, true);
|
|
ul_ack_nack_mark(ack_desc, 1, true);
|
|
/* Final ACK has Poll set: */
|
|
dl_block.SP = 1;
|
|
dl_block.RRBP = GPRS_RLCMAC_RRBP_N_plus_13;
|
|
rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* Trigger transmission of PKT CTRL ACK */
|
|
rts_fn = rrbp2fn(rts_fn, dl_block.RRBP);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
/* Test UL TBF requesting assignment of a new UL TBF through PACCH when
|
|
* answering UL ACK/NACK w/ FinalACK=1 */
|
|
static void test_ul_tbf_request_another_ul_tbf(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
RlcMacDownlink_t dl_block;
|
|
PU_AckNack_GPRS_t *ack_gprs = &dl_block.u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct;
|
|
Ack_Nack_Description_t *ack_desc = &ack_gprs->Ack_Nack_Description;
|
|
uint32_t tlli = 0x2342;
|
|
uint8_t ul_tfi = 0;
|
|
uint8_t ts_nr = 7;
|
|
uint8_t usf = 0;
|
|
uint32_t rts_fn = 4;
|
|
|
|
/* Send only 14 data to feed it in 1 UL block and speed up test length: */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
14);
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_ul_tbf_normal) == GSM_MACBLOCK_LEN);
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* PCU acks it: */
|
|
ul_ack_nack_init(&dl_block, ul_tfi, GPRS_RLCMAC_CS_2);
|
|
ack_desc->STARTING_SEQUENCE_NUMBER = 1;
|
|
ack_desc->FINAL_ACK_INDICATION = 1;
|
|
ul_ack_nack_mark(ack_desc, 0, true);
|
|
ul_ack_nack_mark(ack_desc, 1, true);
|
|
/* TBF Est is set: */
|
|
ack_gprs->Exist_AdditionsR99 = 1;
|
|
ack_gprs->AdditionsR99.TBF_EST = 1;
|
|
/* Final ACK has Poll set: */
|
|
dl_block.SP = 1;
|
|
dl_block.RRBP = GPRS_RLCMAC_RRBP_N_plus_13;
|
|
rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* New data from upper layers arrive which needs to be transmitted. This
|
|
* will make UL_TBF request a new UL_TBF when triggered to answer the final
|
|
* UL ACK/NACK, because there's no active DL TBF: */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
14);
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
/* Trigger transmission of PKT RES REQ: */
|
|
rts_fn = rrbp2fn(rts_fn, dl_block.RRBP);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
static void test_ul_tbf_t3164_timeout(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
unsigned int i;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
uint32_t tlli = 0x2342;
|
|
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
sizeof(pdu_llc_gmm_att_req));
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_ul_tbf_normal) == GSM_MACBLOCK_LEN);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* increase time 5 seconds, timeout should trigger */
|
|
clock_override_add(5, 0);
|
|
clock_debug("Expect T3164 timeout");
|
|
osmo_select_main(0);
|
|
}
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
static void test_ul_tbf_t3166_timeout(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
uint32_t tlli = 0x2342;
|
|
uint8_t ts_nr = 7;
|
|
uint8_t usf = 0;
|
|
uint32_t rts_fn = 4;
|
|
unsigned int i;
|
|
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
sizeof(pdu_llc_gmm_att_req));
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_ul_tbf_normal) == GSM_MACBLOCK_LEN);
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) (first part) */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* increase time 5 seconds, timeout should trigger */
|
|
clock_override_add(5, 0);
|
|
clock_debug("Expect T3166 timeout");
|
|
osmo_select_main(0);
|
|
}
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
static void test_ul_tbf_n3104_timeout(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
uint32_t tlli = 0x2342;
|
|
uint8_t ts_nr = 7;
|
|
uint8_t usf = 0;
|
|
uint32_t rts_fn = 4;
|
|
unsigned int i;
|
|
const unsigned int bs_cv_max = 0;
|
|
const unsigned int num_ts = 1;
|
|
const unsigned int n3104_max = 3 * (bs_cv_max + 3) * num_ts;
|
|
|
|
/* Submit an SI13 with bs_cv_max=0: */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, create_si13(bs_cv_max));
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
sizeof(pdu_llc_gmm_att_req));
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
for (i = 0; i < n3104_max; i++) {
|
|
rts_fn = fn_next_block(rts_fn);
|
|
printf("RTS %u: FN=%u\n", i, rts_fn);
|
|
/* Trigger transmission of LLC data (GMM Attach) (first part) */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
}
|
|
|
|
/* After N3104 triggers, MS re-tries pkt access: */
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
static void test_ul_tbf_t3182_timeout(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
uint32_t tlli = 0x2342;
|
|
uint8_t ul_tfi = 0;
|
|
uint8_t ts_nr = 7;
|
|
uint8_t usf = 0;
|
|
uint32_t rts_fn = 4;
|
|
RlcMacDownlink_t dl_block;
|
|
Ack_Nack_Description_t *ack_desc = &dl_block.u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description;
|
|
|
|
/* Submit 14 bytes to fit in 1 RLCMAC block to shorten test and end up in FINISHED state quickly: */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
sizeof(pdu_llc_gmm_att_req));
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) (first part) */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* PCU acks it: */
|
|
ul_ack_nack_init(&dl_block, ul_tfi, GPRS_RLCMAC_CS_2);
|
|
ack_desc->STARTING_SEQUENCE_NUMBER = 1;
|
|
ack_desc->FINAL_ACK_INDICATION = 0;
|
|
ul_ack_nack_mark(ack_desc, 0, true);
|
|
rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) (second part, CV=0) */
|
|
rts_fn = fn_next_block(rts_fn);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* increase time 5 seconds, timeout should trigger */
|
|
clock_override_add(5, 0);
|
|
clock_debug("Expect T3182 timeout");
|
|
osmo_select_main(0);
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
/* 9.3.3.3.2: The block with CV=0 shall not be retransmitted more than four times. */
|
|
static void test_ul_tbf_last_data_cv0_retrans_max(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
uint32_t tlli = 0x2342;
|
|
uint8_t ul_tfi = 0;
|
|
uint8_t ts_nr = 7;
|
|
uint8_t usf = 0;
|
|
uint32_t rts_fn = 4;
|
|
unsigned int i;
|
|
RlcMacDownlink_t dl_block;
|
|
Ack_Nack_Description_t *ack_desc = &dl_block.u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description;
|
|
|
|
/* Submit 14 bytes to fit in 1 RLCMAC block to shorten test and end up in FINISHED state quickly: */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
|
|
sizeof(pdu_llc_gmm_att_req));
|
|
rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) (first part) */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* PCU acks it: */
|
|
ul_ack_nack_init(&dl_block, ul_tfi, GPRS_RLCMAC_CS_2);
|
|
ack_desc->STARTING_SEQUENCE_NUMBER = 1;
|
|
ack_desc->FINAL_ACK_INDICATION = 0;
|
|
ul_ack_nack_mark(ack_desc, 0, true);
|
|
rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* Trigger transmission of LLC data (GMM Attach) (second part) */
|
|
rts_fn = fn_next_block(rts_fn);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
rts_fn = fn_next_block(rts_fn);
|
|
printf("RTS %u: FN=%u\n", i, rts_fn);
|
|
/* Trigger transmission of LLC data (GMM Attach) (second part) */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
}
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
/* PCU allocates a DL TBF through PCH ImmAss for MS (when in packet-idle) */
|
|
static void test_dl_tbf_ccch_assign(void)
|
|
{
|
|
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
|
|
int rc;
|
|
struct msgb *dl_data_msg;
|
|
|
|
printf("=== %s start ===\n", __func__);
|
|
prepare_test();
|
|
uint32_t tlli = 0x0000001;
|
|
uint8_t ts_nr = 7;
|
|
uint8_t usf = 0;
|
|
uint32_t rts_fn = 4;
|
|
uint8_t dl_tfi = 0;
|
|
uint8_t rrbp = GPRS_RLCMAC_RRBP_N_plus_17_18;
|
|
|
|
/* Notify RLCMAC about our TLLI */
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_gmmrr_assign_req(tlli);
|
|
rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
|
|
|
|
OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_dl_tbf) == GSM_MACBLOCK_LEN);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_dl_tbf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
/* Transmit some DL LLC data MS<-PCU */
|
|
dl_data_msg = create_dl_data_block(dl_tfi, usf, GPRS_RLCMAC_CS_1, 0, true, true, rrbp);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(ts_nr, rts_fn, 0, 0, 0,
|
|
msgb_data(dl_data_msg),
|
|
msgb_length(dl_data_msg));
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
msgb_free(dl_data_msg);
|
|
|
|
/* Trigger transmission of DL ACK/NACK */
|
|
rts_fn = rrbp2fn(rts_fn, rrbp);
|
|
rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
|
|
rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
|
|
OSMO_ASSERT(rc == 0);
|
|
|
|
printf("=== %s end ===\n", __func__);
|
|
cleanup_test();
|
|
}
|
|
|
|
static const struct log_info_cat test_log_categories[] = { };
|
|
static const struct log_info test_log_info = {
|
|
.cat = test_log_categories,
|
|
.num_cat = ARRAY_SIZE(test_log_categories),
|
|
};
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
tall_ctx = talloc_named_const(NULL, 1, __FILE__);
|
|
|
|
osmo_init_logging2(tall_ctx, &test_log_info);
|
|
log_parse_category_mask(osmo_stderr_target, "DLGLOBAL,1:");
|
|
osmo_fsm_log_addr(false);
|
|
|
|
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
|
log_set_print_category_hex(osmo_stderr_target, 0);
|
|
log_set_print_category(osmo_stderr_target, 1);
|
|
log_set_print_level(osmo_stderr_target, 1);
|
|
log_set_use_color(osmo_stderr_target, 0);
|
|
|
|
clock_override_enable(true);
|
|
|
|
test_ul_tbf_attach();
|
|
test_ul_tbf_t3164_timeout();
|
|
test_ul_tbf_t3166_timeout();
|
|
test_ul_tbf_n3104_timeout();
|
|
test_ul_tbf_t3182_timeout();
|
|
test_ul_tbf_last_data_cv0_retrans_max();
|
|
test_ul_tbf_request_another_ul_tbf();
|
|
test_dl_tbf_ccch_assign();
|
|
|
|
talloc_free(tall_ctx);
|
|
}
|