Beispiel #1
0
/* get next frame from the tx queue. because the ms has multiple datalinks,
 * each datalink's queue is read round-robin.
 */
static int l2_ph_data_conf(struct msgb *msg, struct lapdm_entity *le)
{
	struct osmo_phsap_prim pp;

	/* we may send again */
	le->tx_pending = 0;

	/* free confirm message */
	if (msg)
		msgb_free(msg);

	if (lapdm_phsap_dequeue_prim(le, &pp) < 0) {
		/* no message in all queues */

		/* If user didn't request PH-EMPTY_FRAME.req, abort */
		if (!(le->flags & LAPDM_ENT_F_EMPTY_FRAME))
			return 0;

		/* otherwise, send PH-EMPTY_FRAME.req */
		osmo_prim_init(&pp.oph, SAP_GSM_PH,
				PRIM_PH_EMPTY_FRAME,
				PRIM_OP_REQUEST, NULL);
	} else {
		le->tx_pending = 1;
	}

	return le->l1_prim_cb(&pp.oph, le->l1_ctx);
}
static void test_lapdm_polling()
{
	printf("I do some very simple LAPDm test.\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;
	struct lapdm_channel ms_to_bts_channel;
	memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
	memset(&ms_to_bts_channel, 0, sizeof(ms_to_bts_channel));

	memset(&test_state, 0, sizeof(test_state));
	test_state.bts = &bts_to_ms_channel;
	test_state.ms = &ms_to_bts_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);

	/* MS to BTS in direct mode */
	lapdm_channel_init(&ms_to_bts_channel, LAPDM_MODE_MS);
	lapdm_channel_set_l1(&ms_to_bts_channel, ms_to_bts_l1_cb, &test_state);
	lapdm_channel_set_l3(&ms_to_bts_channel, ms_to_bts_tx_cb, &test_state);

	/*
	 * We try to send messages from the MS to the BTS to the MS..
	 */
	/* 1. Start with MS -> BTS, BTS should have a pending message */
	printf("Establishing link.\n");
	lapdm_rslms_recvmsg(create_cm_serv_req(), &ms_to_bts_channel);

	/* 2. Poll on the BTS for sending out a confirmation */
	printf("\nConfirming\n");
	ASSERT(test_state.bts_read == 1)
	rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
	CHECK_RC(rc);
	ASSERT(pp.oph.msg->data == pp.oph.msg->l2h);
	send(pp.oph.msg, &ms_to_bts_channel);
	msgb_free(pp.oph.msg);
	ASSERT(test_state.ms_read == 1);

	/* 3. Send some data to the MS */
	printf("\nSending back to MS\n");
	lapdm_rslms_recvmsg(create_mm_id_req(), &bts_to_ms_channel);
	rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
	CHECK_RC(rc);
	send(pp.oph.msg, &ms_to_bts_channel);
	msgb_free(pp.oph.msg);
	ASSERT(test_state.ms_read == 2);

	/* verify that there is nothing more to poll */
	rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
	ASSERT(rc < 0);

	/* 3. And back to the BTS */
	printf("\nSending back to BTS\n");
	ASSERT(test_state.ms_read == 2);
	lapdm_rslms_recvmsg(create_dummy_data_req(), &ms_to_bts_channel);


	/* 4. And back to the MS, but let's move data/l2h apart */
	ASSERT(test_state.bts_read == 2)
	ASSERT(test_state.ms_read == 2);
	rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
	CHECK_RC(rc);
	send(pp.oph.msg, &ms_to_bts_channel);
	ASSERT(test_state.ms_read == 2);
	msgb_free(pp.oph.msg);

	/* verify that there is nothing more to poll */
	rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
	ASSERT(rc < 0);

	/* check sending an empty L3 message fails */
	rc = lapdm_rslms_recvmsg(create_empty_msg(), &bts_to_ms_channel);
	ASSERT(rc == -1);
	ASSERT(test_state.ms_read == 2);

	/* clean up */
	lapdm_channel_exit(&bts_to_ms_channel);
	lapdm_channel_exit(&ms_to_bts_channel);
}