Fix: LAPDm contention resoltion must acknowledge subsequent SABM

After reception of SABM, the network responds with UA and enters the
establised multiframe state. If UA is not received by mobile, the SABM
is transmitted again, and the network must respond with UA again, unless
it is from a different mobile.

Add LAPDm collision test (contention resolution on network side).
This commit is contained in:
Andreas Eversberg 2013-02-06 14:13:21 +01:00 committed by Holger Hans Peter Freyther
parent b64b2b0313
commit 6e182087f4
3 changed files with 87 additions and 2 deletions

View File

@ -820,7 +820,12 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
"frame established state\n");
/* If link is lost on the remote side, we start over
* and send DL-ESTABLISH indication again. */
if (dl->v_send != dl->v_recv) {
/* Additionally, continue in case of content resoltion
* (GSM network). This happens, if the mobile has not
* yet received UA or another mobile (collision) tries
* to establish connection. The mobile must receive
* UA again. */
if (!dl->cont_res && dl->v_send != dl->v_recv) {
LOGP(DLLAPD, LOGL_INFO, "Remote reestablish\n");
mdl_error(MDL_CAUSE_SABM_MF, lctx);
break;
@ -831,7 +836,8 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
#ifdef TEST_CONTENT_RESOLUTION_NETWORK
dl->cont_res->data[0] ^= 0x01;
#endif
if (memcmp(dl->cont_res, msg->data, length)) {
if (memcmp(dl->cont_res->data, msg->data,
length)) {
LOGP(DLLAPD, LOGL_INFO, "Another SABM "
"with diffrent content - "
"ignoring!\n");

View File

@ -67,6 +67,12 @@ static const uint8_t cm_padded[] = {
0x2b, 0x2b, 0x2b, 0x2b
};
static const uint8_t ua[] = {
0x01, 0x73, 0x41, 0x05, 0x24, 0x31, 0x03, 0x50,
0x18, 0x93, 0x08, 0x29, 0x47, 0x80, 0x00, 0x00,
0x00, 0x00, 0x80, 0x2b, 0x2b, 0x2b, 0x2b
};
static const uint8_t mm[] = {
0x00, 0x0c, 0x00, 0x03, 0x01, 0x01, 0x20, 0x02,
0x00, 0x0b, 0x00, 0x03, 0x05, 0x04, 0x0d
@ -153,6 +159,32 @@ static int send(struct msgb *in_msg, struct lapdm_channel *chan)
return 0;
}
static int send_sabm(struct lapdm_channel *chan, int second_ms)
{
struct osmo_phsap_prim pp;
struct msgb *msg;
int rc;
msg = msgb_alloc_headroom(128, 64, "PH-DATA.ind");
osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
PRIM_OP_INDICATION, msg);
/* copy over actual MAC block */
msg->l2h = msgb_put(msg, 23);
msg->l2h[0] = 0x01;
msg->l2h[1] = 0x3f;
msg->l2h[2] = 0x01 | (sizeof(cm) << 2);
memcpy(msg->l2h + 3, cm_padded, sizeof(cm_padded));
msg->l2h[3] += second_ms; /* alter message, for second mobile */
/* LAPDm requires those... */
pp.u.data.chan_nr = 0;
pp.u.data.link_id = 0;
/* feed into the LAPDm code of libosmogsm */
rc = lapdm_phsap_up(&pp.oph, &chan->lapdm_dcch);
OSMO_ASSERT(rc == 0 || rc == -EBUSY);
return 0;
}
/*
* I get called from the LAPDm code when something was sent my way...
*/
@ -348,12 +380,56 @@ static void test_lapdm_early_release()
lapdm_channel_exit(&bts_to_ms_channel);
}
static void test_lapdm_contention_resolution()
{
printf("I test contention resultion by having two mobiles collide and "
"first mobile repeating SABM.\n");
int rc;
struct lapdm_polling_state test_state;
struct osmo_phsap_prim pp;
/* Configure LAPDm on both sides */
struct lapdm_channel bts_to_ms_channel;
memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
memset(&test_state, 0, sizeof(test_state));
test_state.bts = &bts_to_ms_channel;
/* BTS to MS in polling mode */
lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS);
lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY);
lapdm_channel_set_l1(&bts_to_ms_channel, NULL, &test_state);
lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_tx_cb, &test_state);
/* Send SABM MS 1, we must get UA */
send_sabm(&bts_to_ms_channel, 0);
rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
CHECK_RC(rc);
OSMO_ASSERT(memcmp(pp.oph.msg->l2h, ua, ARRAY_SIZE(ua)) == 0);
/* Send SABM MS 2, we must get nothing, due to collision */
send_sabm(&bts_to_ms_channel, 1);
rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
OSMO_ASSERT(rc == -ENODEV);
/* Send SABM MS 1 again, we must get UA gain */
send_sabm(&bts_to_ms_channel, 0);
rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
CHECK_RC(rc);
OSMO_ASSERT(memcmp(pp.oph.msg->l2h, ua, ARRAY_SIZE(ua)) == 0);
/* clean up */
lapdm_channel_exit(&bts_to_ms_channel);
}
int main(int argc, char **argv)
{
osmo_init_logging(&info);
test_lapdm_polling();
test_lapdm_early_release();
test_lapdm_contention_resolution();
printf("Success.\n");
return 0;

View File

@ -18,4 +18,7 @@ ms_to_bts_l1_cb: MS(us) -> BTS prim message
bts_to_ms_tx_cb: MS->BTS(us) message 14
BTS: Verifying dummy message.
I test RF channel release of an unestablished channel.
I test contention resultion by having two mobiles collide and first mobile repeating SABM.
bts_to_ms_tx_cb: MS->BTS(us) message 29
BTS: Verifying CM request.
Success.