mirror of https://gerrit.osmocom.org/osmo-tetra
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:
parent
1056d5986b
commit
8a4542a77f
|
@ -13,7 +13,7 @@ debug: all
|
||||||
libosmo-tetra-phy.a: phy/tetra_burst_sync.o phy/tetra_burst.o
|
libosmo-tetra-phy.a: phy/tetra_burst_sync.o phy/tetra_burst.o
|
||||||
$(AR) r $@ $^
|
$(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 $@ $^
|
$(AR) r $@ $^
|
||||||
|
|
||||||
float_to_bits: float_to_bits.o
|
float_to_bits: float_to_bits.o
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <osmocom/core/bits.h>
|
#include <osmocom/core/bits.h>
|
||||||
|
|
||||||
#include "tetra_llc_pdu.h"
|
#include "tetra_llc_pdu.h"
|
||||||
|
#include "tetra_mle.h"
|
||||||
#include "tuntap.h"
|
#include "tuntap.h"
|
||||||
|
|
||||||
static int tun_fd = -1;
|
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),
|
.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 *
|
static struct tllc_defrag_q_e *
|
||||||
get_dqe_for_ns(struct tllc_state *llcs, uint8_t ns, int alloc_if_missing)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tllc_defrag_out(struct tllc_state *llcs,
|
static int tllc_defrag_out(struct tetra_mac_state *tms, struct tllc_state *llcs, struct tetra_llc_pdu *lpp)
|
||||||
struct tetra_llc_pdu *lpp)
|
|
||||||
{
|
{
|
||||||
struct tllc_defrag_q_e *dqe;
|
struct tllc_defrag_q_e *dqe;
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
|
@ -90,7 +88,7 @@ static int tllc_defrag_out(struct tllc_state *llcs,
|
||||||
|
|
||||||
printf("<<REMOVE>> ");
|
printf("<<REMOVE>> ");
|
||||||
msg->l3h = msg->data;
|
msg->l3h = msg->data;
|
||||||
rx_tl_sdu(msg, msgb_l3len(msg));
|
rx_tl_sdu(tms, msg, msgb_l3len(msg));
|
||||||
|
|
||||||
if (tun_fd < 0) {
|
if (tun_fd < 0) {
|
||||||
tun_fd = tun_alloc("tun0");
|
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) */
|
/* Receive TM-SDU (MAC SDU == LLC PDU) */
|
||||||
/* this resembles TMA-UNITDATA.ind (TM-SDU / length) */
|
/* 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));
|
memset(&lpp, 0, sizeof(lpp));
|
||||||
tetra_llc_pdu_parse(&lpp, msg->l2h, len);
|
tetra_llc_pdu_parse(&lpp, msg->l2h, len);
|
||||||
msg->l3h = lpp.tl_sdu;
|
msg->l3h = lpp.tl_sdu;
|
||||||
|
msg->tail = msg->l3h + lpp.tl_sdu_len; // Strips off FCS (if present)
|
||||||
|
|
||||||
printf("TM-SDU(%s,%u,%u): ",
|
printf("TM-SDU(%s)", tetra_get_llc_pdut_dec_name(lpp.pdu_type));
|
||||||
tetra_get_llc_pdut_dec_name(lpp.pdu_type), lpp.ns, lpp.ss);
|
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) {
|
switch (lpp.pdu_type) {
|
||||||
case TLLC_PDUT_DEC_BL_ADATA:
|
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_RECONNECT:
|
||||||
case TLLC_PDUT_DEC_AL_DISC:
|
case TLLC_PDUT_DEC_AL_DISC:
|
||||||
/* directly hand it to MLE */
|
/* directly hand it to MLE */
|
||||||
rx_tl_sdu(msg, lpp.tl_sdu_len);
|
rx_tl_sdu(tms, msg, lpp.tl_sdu_len);
|
||||||
break;
|
break;
|
||||||
case TLLC_PDUT_DEC_AL_DATA:
|
case TLLC_PDUT_DEC_AL_DATA:
|
||||||
case TLLC_PDUT_DEC_AL_UDATA:
|
case TLLC_PDUT_DEC_AL_UDATA:
|
||||||
|
@ -148,7 +164,7 @@ int rx_tm_sdu(struct msgb *msg, unsigned int len)
|
||||||
/* input into LLC defragmenter */
|
/* input into LLC defragmenter */
|
||||||
tllc_defrag_in(&g_llcs, &lpp, msg, len);
|
tllc_defrag_in(&g_llcs, &lpp, msg, len);
|
||||||
/* check if the fragment is complete and hand it off*/
|
/* check if the fragment is complete and hand it off*/
|
||||||
tllc_defrag_out(&g_llcs, &lpp);
|
tllc_defrag_out(tms, &g_llcs, &lpp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TLLC_PDUT_DEC_UNKNOWN:
|
case TLLC_PDUT_DEC_UNKNOWN:
|
||||||
|
@ -158,9 +174,5 @@ int rx_tm_sdu(struct msgb *msg, unsigned int len)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpp.tl_sdu && lpp.ss == 0) {
|
|
||||||
/* this resembles TMA-UNITDATA.ind */
|
|
||||||
//rx_tl_sdu(msg, lpp.tl_sdu_len);
|
|
||||||
}
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -32,14 +32,9 @@
|
||||||
#include "tetra_upper_mac.h"
|
#include "tetra_upper_mac.h"
|
||||||
#include "tetra_mac_pdu.h"
|
#include "tetra_mac_pdu.h"
|
||||||
#include "tetra_llc_pdu.h"
|
#include "tetra_llc_pdu.h"
|
||||||
#include "tetra_mm_pdu.h"
|
#include "tetra_llc.h"
|
||||||
#include "tetra_cmce_pdu.h"
|
|
||||||
#include "tetra_sndcp_pdu.h"
|
|
||||||
#include "tetra_mle_pdu.h"
|
|
||||||
#include "tetra_gsmtap.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 */
|
/* FIXME move global fragslots to context variable */
|
||||||
struct fragslot fragslots[FRAGSLOT_NR_SLOTS] = {0};
|
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;
|
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)
|
static int rx_resrc(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
|
||||||
{
|
{
|
||||||
struct msgb *msg = tmvp->oph.msg;
|
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 */
|
/* We now have accurate length and start of TM-SDU, set LLC start in msg->l2h */
|
||||||
msg->l2h = msg->l1h + tmpdu_offset;
|
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),
|
rsd.encryption_mode, rsd.macpdu_length, msgb_l1len(msg), msgb_l2len(msg),
|
||||||
tetra_addr_dump(&rsd.addr));
|
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) {
|
if (rsd.addr.type == ADDR_TYPE_NULL) {
|
||||||
pdu_bits = -1; /* No more PDUs in slot */
|
pdu_bits = -1; /* No more PDUs in slot */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (msgb_l2len(msg) == 0) {
|
||||||
|
goto out; /* No l2 data */
|
||||||
|
}
|
||||||
|
|
||||||
if (rsd.chan_alloc_pres)
|
printf(": %s\n", osmo_ubit_dump(msg->l2h, msgb_l2len(msg)));
|
||||||
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.macpdu_length != MACPDU_LEN_START_FRAG || !REASSEMBLE_FRAGMENTS) {
|
if (rsd.macpdu_length != MACPDU_LEN_START_FRAG || !REASSEMBLE_FRAGMENTS) {
|
||||||
/* Non-fragmented resource (or no reassembly desired) */
|
/* Non-fragmented resource (or no reassembly desired) */
|
||||||
if (!rsd.is_encrypted) {
|
if (!rsd.is_encrypted) {
|
||||||
|
|
Loading…
Reference in New Issue