added support for advanced link defragmentation

the rx_tm_sdu and rx_tl_sdu did not belong in tetra_upper_mac and are removed. Instead, we use rx_tm_sdu in tetra_llc.c, who in turn invokes rx_tl_sdu in tetra_mle.c. The llc can now also make use of the advanced link defragmentation code that was already there but unused.

Change-Id: I294c684e97c55876f1a207a7152a83dad4ebaa26
This commit is contained in:
wbokslag 2022-09-18 15:12:50 +02:00
parent 1056d5986b
commit 8a4542a77f
6 changed files with 110 additions and 88 deletions

View File

@ -13,7 +13,7 @@ debug: all
libosmo-tetra-phy.a: phy/tetra_burst_sync.o phy/tetra_burst.o
$(AR) r $@ $^
libosmo-tetra-mac.a: lower_mac/tetra_conv_enc.o lower_mac/tch_reordering.o tetra_tdma.o lower_mac/tetra_scramb.o lower_mac/tetra_rm3014.o lower_mac/tetra_interleave.o lower_mac/crc_simple.o tetra_common.o lower_mac/viterbi.o lower_mac/viterbi_cch.o lower_mac/viterbi_tch.o lower_mac/tetra_lower_mac.o tetra_upper_mac.o tetra_mac_pdu.o tetra_llc_pdu.o tetra_llc.o tetra_mle_pdu.o tetra_mm_pdu.o tetra_cmce_pdu.o tetra_sndcp_pdu.o tetra_gsmtap.o tuntap.o
libosmo-tetra-mac.a: lower_mac/tetra_conv_enc.o lower_mac/tch_reordering.o tetra_tdma.o lower_mac/tetra_scramb.o lower_mac/tetra_rm3014.o lower_mac/tetra_interleave.o lower_mac/crc_simple.o tetra_common.o lower_mac/viterbi.o lower_mac/viterbi_cch.o lower_mac/viterbi_tch.o lower_mac/tetra_lower_mac.o tetra_upper_mac.o tetra_mac_pdu.o tetra_llc_pdu.o tetra_llc.o tetra_mle_pdu.o tetra_mle.o tetra_mm_pdu.o tetra_cmce_pdu.o tetra_sndcp_pdu.o tetra_gsmtap.o tuntap.o
$(AR) r $@ $^
float_to_bits: float_to_bits.o

View File

@ -28,6 +28,7 @@
#include <osmocom/core/bits.h>
#include "tetra_llc_pdu.h"
#include "tetra_mle.h"
#include "tuntap.h"
static int tun_fd = -1;
@ -36,8 +37,6 @@ static struct tllc_state g_llcs = {
.rx.defrag_list = LLIST_HEAD_INIT(g_llcs.rx.defrag_list),
};
int rx_tl_sdu(struct msgb *msg, unsigned int len);
static struct tllc_defrag_q_e *
get_dqe_for_ns(struct tllc_state *llcs, uint8_t ns, int alloc_if_missing)
{
@ -79,8 +78,7 @@ static int tllc_defrag_in(struct tllc_state *llcs,
return 0;
}
static int tllc_defrag_out(struct tllc_state *llcs,
struct tetra_llc_pdu *lpp)
static int tllc_defrag_out(struct tetra_mac_state *tms, struct tllc_state *llcs, struct tetra_llc_pdu *lpp)
{
struct tllc_defrag_q_e *dqe;
struct msgb *msg;
@ -90,7 +88,7 @@ static int tllc_defrag_out(struct tllc_state *llcs,
printf("<<REMOVE>> ");
msg->l3h = msg->data;
rx_tl_sdu(msg, msgb_l3len(msg));
rx_tl_sdu(tms, msg, msgb_l3len(msg));
if (tun_fd < 0) {
tun_fd = tun_alloc("tun0");
@ -110,16 +108,34 @@ static int tllc_defrag_out(struct tllc_state *llcs,
/* Receive TM-SDU (MAC SDU == LLC PDU) */
/* this resembles TMA-UNITDATA.ind (TM-SDU / length) */
int rx_tm_sdu(struct msgb *msg, unsigned int len)
int rx_tm_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len)
{
struct tetra_llc_pdu lpp;
if (!len) {
return -1;
} else if (len < 4) {
printf("WARNING rx_tm_sdu: l2len too small: %d\n", len);
return -1;
}
struct tetra_llc_pdu lpp;
memset(&lpp, 0, sizeof(lpp));
tetra_llc_pdu_parse(&lpp, msg->l2h, len);
msg->l3h = lpp.tl_sdu;
msg->tail = msg->l3h + lpp.tl_sdu_len; // Strips off FCS (if present)
printf("TM-SDU(%s,%u,%u): ",
tetra_get_llc_pdut_dec_name(lpp.pdu_type), lpp.ns, lpp.ss);
printf("TM-SDU(%s)", tetra_get_llc_pdut_dec_name(lpp.pdu_type));
if (lpp.have_fcs) {
printf(" fcs=%s ", (lpp.have_fcs && lpp.fcs_invalid ? "BAD" : "OK"));
}
printf(" l3len=%d", msgb_l3len(msg));
if (msgb_l3len(msg)) {
printf(" %s", osmo_ubit_dump(msg->l3h, msgb_l3len(msg)));
}
printf("\n");
if (!lpp.tl_sdu_len) {
return len;
}
switch (lpp.pdu_type) {
case TLLC_PDUT_DEC_BL_ADATA:
@ -132,7 +148,7 @@ int rx_tm_sdu(struct msgb *msg, unsigned int len)
case TLLC_PDUT_DEC_AL_RECONNECT:
case TLLC_PDUT_DEC_AL_DISC:
/* directly hand it to MLE */
rx_tl_sdu(msg, lpp.tl_sdu_len);
rx_tl_sdu(tms, msg, lpp.tl_sdu_len);
break;
case TLLC_PDUT_DEC_AL_DATA:
case TLLC_PDUT_DEC_AL_UDATA:
@ -148,7 +164,7 @@ int rx_tm_sdu(struct msgb *msg, unsigned int len)
/* input into LLC defragmenter */
tllc_defrag_in(&g_llcs, &lpp, msg, len);
/* check if the fragment is complete and hand it off*/
tllc_defrag_out(&g_llcs, &lpp);
tllc_defrag_out(tms, &g_llcs, &lpp);
break;
case TLLC_PDUT_DEC_UNKNOWN:
@ -158,9 +174,5 @@ int rx_tm_sdu(struct msgb *msg, unsigned int len)
break;
}
if (lpp.tl_sdu && lpp.ss == 0) {
/* this resembles TMA-UNITDATA.ind */
//rx_tl_sdu(msg, lpp.tl_sdu_len);
}
return len;
}

8
src/tetra_llc.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef TETRA_LLC_H
#define TETRA_LLC_H
#include "tetra_common.h"
int rx_tm_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len);
#endif

53
src/tetra_mle.c Normal file
View File

@ -0,0 +1,53 @@
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/bits.h>
#include "tetra_mle_pdu.h"
#include "tetra_mle.h"
#include "tetra_mm_pdu.h"
#include "tetra_cmce_pdu.h"
#include "tetra_sndcp_pdu.h"
#include "tetra_mle_pdu.h"
/* Receive TL-SDU (LLC SDU == MLE PDU) */
int rx_tl_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len)
{
uint8_t *bits = msg->l3h;
uint8_t mle_pdisc = bits_to_uint(bits, 3);
printf("TL-SDU(%s): %s ", tetra_get_mle_pdisc_name(mle_pdisc),
osmo_ubit_dump(bits, len));
switch (mle_pdisc) {
case TMLE_PDISC_MM:
printf("%s\n", tetra_get_mm_pdut_name(bits_to_uint(bits+3, 4), 0));
break;
case TMLE_PDISC_CMCE:
printf("%s\n", tetra_get_cmce_pdut_name(bits_to_uint(bits+3, 5), 0));
break;
case TMLE_PDISC_SNDCP:
printf("%s ", tetra_get_sndcp_pdut_name(bits_to_uint(bits+3, 4), 0));
printf(" NSAPI=%u PCOMP=%u, DCOMP=%u",
bits_to_uint(bits+3+4, 4),
bits_to_uint(bits+3+4+4, 4),
bits_to_uint(bits+3+4+4+4, 4));
printf(" V%u, IHL=%u",
bits_to_uint(bits+3+4+4+4+4, 4),
4*bits_to_uint(bits+3+4+4+4+4+4, 4));
printf(" Proto=%u\n",
bits_to_uint(bits+3+4+4+4+4+4+4+64, 8));
break;
case TMLE_PDISC_MLE:
printf("%s\n", tetra_get_mle_pdut_name(bits_to_uint(bits+3, 3), 0));
break;
default:
break;
}
return len;
}

8
src/tetra_mle.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef TETRA_MLE_H
#define TETRA_MLE_H
#include "tetra_common.h"
int rx_tl_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len);
#endif

View File

@ -32,14 +32,9 @@
#include "tetra_upper_mac.h"
#include "tetra_mac_pdu.h"
#include "tetra_llc_pdu.h"
#include "tetra_mm_pdu.h"
#include "tetra_cmce_pdu.h"
#include "tetra_sndcp_pdu.h"
#include "tetra_mle_pdu.h"
#include "tetra_llc.h"
#include "tetra_gsmtap.h"
static int rx_tm_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len);
/* FIXME move global fragslots to context variable */
struct fragslot fragslots[FRAGSLOT_NR_SLOTS] = {0};
@ -144,64 +139,6 @@ const char *tetra_alloc_dump(const struct tetra_chan_alloc_decoded *cad, struct
return buf;
}
/* Receive TL-SDU (LLC SDU == MLE PDU) */
static int rx_tl_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len)
{
uint8_t *bits = msg->l3h;
uint8_t mle_pdisc = bits_to_uint(bits, 3);
printf("TL-SDU(%s): %s", tetra_get_mle_pdisc_name(mle_pdisc),
osmo_ubit_dump(bits, len));
switch (mle_pdisc) {
case TMLE_PDISC_MM:
printf(" %s", tetra_get_mm_pdut_name(bits_to_uint(bits+3, 4), 0));
break;
case TMLE_PDISC_CMCE:
printf(" %s", tetra_get_cmce_pdut_name(bits_to_uint(bits+3, 5), 0));
break;
case TMLE_PDISC_SNDCP:
printf(" %s", tetra_get_sndcp_pdut_name(bits_to_uint(bits+3, 4), 0));
printf(" NSAPI=%u PCOMP=%u, DCOMP=%u",
bits_to_uint(bits+3+4, 4),
bits_to_uint(bits+3+4+4, 4),
bits_to_uint(bits+3+4+4+4, 4));
printf(" V%u, IHL=%u",
bits_to_uint(bits+3+4+4+4+4, 4),
4*bits_to_uint(bits+3+4+4+4+4+4, 4));
printf(" Proto=%u",
bits_to_uint(bits+3+4+4+4+4+4+4+64, 8));
break;
case TMLE_PDISC_MLE:
printf(" %s", tetra_get_mle_pdut_name(bits_to_uint(bits+3, 3), 0));
break;
default:
break;
}
return len;
}
static int rx_tm_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len)
{
struct tetra_llc_pdu lpp;
uint8_t *bits = msg->l2h;
memset(&lpp, 0, sizeof(lpp));
tetra_llc_pdu_parse(&lpp, bits, len);
printf("TM-SDU(%s,%u,%u)",
tetra_get_llc_pdut_dec_name(lpp.pdu_type), lpp.ns, lpp.ss);
if (lpp.have_fcs) {
printf("(FCS: %s)", lpp.fcs_invalid ? "BAD" : "OK");
}
printf(": ");
if (lpp.tl_sdu && lpp.ss == 0) {
msg->l3h = lpp.tl_sdu;
rx_tl_sdu(tms, msg, lpp.tl_sdu_len);
}
return len;
}
static int rx_resrc(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
{
struct msgb *msg = tmvp->oph.msg;
@ -231,22 +168,26 @@ static int rx_resrc(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
/* We now have accurate length and start of TM-SDU, set LLC start in msg->l2h */
msg->l2h = msg->l1h + tmpdu_offset;
printf("RESOURCE Encr=%u, len=%d l1_len=%d l2_len %d Addr=%s ",
printf("RESOURCE Encr=%u len_field=%d l1_len=%d l2_len %d Addr=%s",
rsd.encryption_mode, rsd.macpdu_length, msgb_l1len(msg), msgb_l2len(msg),
tetra_addr_dump(&rsd.addr));
if (rsd.chan_alloc_pres)
printf(" ChanAlloc=%s", tetra_alloc_dump(&rsd.cad, tms));
if (rsd.slot_granting.pres)
printf(" SlotGrant=%u/%u", rsd.slot_granting.nr_slots,
rsd.slot_granting.delay);
if (rsd.addr.type == ADDR_TYPE_NULL) {
pdu_bits = -1; /* No more PDUs in slot */
goto out;
}
if (msgb_l2len(msg) == 0) {
goto out; /* No l2 data */
}
if (rsd.chan_alloc_pres)
printf("ChanAlloc=%s ", tetra_alloc_dump(&rsd.cad, tms));
if (rsd.slot_granting.pres)
printf("SlotGrant=%u/%u ", rsd.slot_granting.nr_slots,
rsd.slot_granting.delay);
printf(": %s\n", osmo_ubit_dump(msg->l2h, msgb_l2len(msg)));
if (rsd.macpdu_length != MACPDU_LEN_START_FRAG || !REASSEMBLE_FRAGMENTS) {
/* Non-fragmented resource (or no reassembly desired) */
if (!rsd.is_encrypted) {