llc: implement LLC PDU codec based on code from osmo-sgsn.git

osmo-sgsn.git 13ccbc1e6120fe78f6f9f950d7242090920ca41b

Change-Id: I61d7e2e6d0a8f2cdfc2113e637e447dc428cc70d
This commit is contained in:
Vadim Yanitskiy 2022-09-09 19:20:55 +07:00
parent bae1ec285b
commit c1ca5406bc
9 changed files with 626 additions and 0 deletions

View File

@ -86,6 +86,7 @@ AC_CONFIG_FILES([libosmo-csn1.pc
src/llc/Makefile
src/rlcmac/Makefile
tests/Makefile
tests/llc_pdu_codec/Makefile
tests/ts_44_018/Makefile
tests/ts_44_060/Makefile
Makefile

View File

@ -130,4 +130,36 @@ struct osmo_gprs_llc_params {
uint16_t kU;
};
#define OSMO_GPRS_LLC_PDU_F_CMD_RSP (1 << 0) /* 6.2.2 Commmand/Response bit (C/R) */
#define OSMO_GPRS_LLC_PDU_F_FOLL_FIN (1 << 1) /* 6.3.5.1 Poll/Final bit (P/F) */
#define OSMO_GPRS_LLC_PDU_F_ACK_REQ (1 << 2) /* 6.3.5.2 Acknowledgement request bit (A) */
#define OSMO_GPRS_LLC_PDU_F_MAC_PRES (1 << 3) /* 6.3.5.2a Integrity Protection bit (IP) */
#define OSMO_GPRS_LLC_PDU_F_ENC_MODE (1 << 4) /* 6.3.5.5.1 Encryption mode bit (E) */
#define OSMO_GPRS_LLC_PDU_F_PROT_MODE (1 << 5) /* 6.3.5.5.2 Protected Mode bit (PM) */
struct osmo_gprs_llc_pdu_decoded {
enum osmo_gprs_llc_sapi sapi;
enum osmo_gprs_llc_frame_fmt fmt;
enum osmo_gprs_llc_frame_func func;
uint32_t flags; /* see OSMO_GPRS_LLC_PDU_F_* above */
uint32_t seq_rx; /* 6.3.5.4.5 Receive sequence number N(R) */
uint32_t seq_tx; /* 6.3.5.4.3 Send sequence number N(S) */
uint32_t fcs; /* 5.5 Frame Check Sequence (FCS) field */
uint32_t mac; /* 5.5a Message Authentication Code (MAC) field */
struct {
uint8_t len; /* Indicates the number of octets in the bitmap */
uint8_t r[32]; /* The R(n) bitmap */
} sack; /* 6.3.5.4.6 SACK bitmap R(n) */
size_t data_len;
const uint8_t *data;
};
void osmo_gprs_llc_pdu_hdr_dump_buf(char *buf, size_t buf_size,
const struct osmo_gprs_llc_pdu_decoded *pdu);
const char *osmo_gprs_llc_pdu_hdr_dump(const struct osmo_gprs_llc_pdu_decoded *pdu);
int osmo_gprs_llc_pdu_decode(struct osmo_gprs_llc_pdu_decoded *pdu,
const uint8_t *data, size_t data_len);
int osmo_gprs_llc_pdu_encode(struct msgb *msg, const struct osmo_gprs_llc_pdu_decoded *pdu);
uint32_t osmo_gprs_llc_fcs(const uint8_t *data, size_t len);

View File

@ -20,10 +20,22 @@
*
*/
#include <stdint.h>
#include <errno.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>
#include <osmocom/gprs/llc/llc.h>
/* TODO: make logging category configurable */
#define DLLC DLGLOBAL
#define UI_HDR_LEN 3
#define N202 4
#define CRC24_LENGTH 3
const struct value_string osmo_gprs_llc_frame_fmt_names[] = {
{ OSMO_GPRS_LLC_FMT_I, "I" },
{ OSMO_GPRS_LLC_FMT_S, "U" },
@ -64,3 +76,410 @@ uint32_t osmo_gprs_llc_fcs(const uint8_t *data, size_t len)
return fcs_calc;
}
void osmo_gprs_llc_pdu_hdr_dump_buf(char *buf, size_t buf_size,
const struct osmo_gprs_llc_pdu_decoded *pdu)
{
struct osmo_strbuf sb = { .buf = buf, .len = buf_size };
OSMO_STRBUF_PRINTF(sb, "SAPI=%u, %s func=%s C/R=%c",
pdu->sapi, /* TODO: print value_string */
osmo_gprs_llc_frame_fmt_name(pdu->fmt),
osmo_gprs_llc_frame_func_name(pdu->func),
pdu->flags & OSMO_GPRS_LLC_PDU_F_CMD_RSP ? '1' : '0');
switch (pdu->fmt) {
case OSMO_GPRS_LLC_FMT_I:
OSMO_STRBUF_PRINTF(sb, " A=%c N(R)=%u N(S)=%u",
pdu->flags & OSMO_GPRS_LLC_PDU_F_ACK_REQ ? '1' : '0',
pdu->seq_rx, pdu->seq_tx);
break;
case OSMO_GPRS_LLC_FMT_S:
OSMO_STRBUF_PRINTF(sb, " A=%c N(R)=%u",
pdu->flags & OSMO_GPRS_LLC_PDU_F_ACK_REQ ? '1' : '0',
pdu->seq_rx);
break;
case OSMO_GPRS_LLC_FMT_UI:
OSMO_STRBUF_PRINTF(sb, " PM=%c E=%c IP=%c N(U)=%u",
pdu->flags & OSMO_GPRS_LLC_PDU_F_PROT_MODE ? '1' : '0',
pdu->flags & OSMO_GPRS_LLC_PDU_F_ENC_MODE ? '1' : '0',
pdu->flags & OSMO_GPRS_LLC_PDU_F_MAC_PRES ? '1' : '0',
pdu->seq_tx);
break;
case OSMO_GPRS_LLC_FMT_U:
OSMO_STRBUF_PRINTF(sb, " P/F=%c",
pdu->flags & OSMO_GPRS_LLC_PDU_F_FOLL_FIN ? '1' : '0');
break;
}
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_MAC_PRES)
OSMO_STRBUF_PRINTF(sb, " MAC=%08x", pdu->mac);
OSMO_STRBUF_PRINTF(sb, " FCS=%06x", pdu->fcs);
}
const char *osmo_gprs_llc_pdu_hdr_dump(const struct osmo_gprs_llc_pdu_decoded *pdu)
{
static __thread char buf[256];
osmo_gprs_llc_pdu_hdr_dump_buf(&buf[0], sizeof(buf), pdu);
return buf;
}
/* 6.4.1 Unnumbered (U) frames */
#define GPRS_LLC_U_NULL_CMD 0x00
#define GPRS_LLC_U_DM_RESP 0x01
#define GPRS_LLC_U_DISC_CMD 0x04
#define GPRS_LLC_U_UA_RESP 0x06
#define GPRS_LLC_U_SABM_CMD 0x07
#define GPRS_LLC_U_FRMR_RESP 0x08
#define GPRS_LLC_U_XID 0x0b
int osmo_gprs_llc_pdu_encode(struct msgb *msg, const struct osmo_gprs_llc_pdu_decoded *pdu)
{
uint8_t *addr = msgb_put(msg, 1);
uint8_t *ctrl = NULL;
size_t crc_len;
uint32_t fcs;
/* 6.2.3 Service Access Point Identifier (SAPI) */
addr[0] = pdu->sapi & 0x0f;
/* 6.2.2 Commmand/Response bit (C/R) */
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_CMD_RSP)
addr[0] |= (1 << 6);
switch (pdu->fmt) {
case OSMO_GPRS_LLC_FMT_I:
ctrl = msgb_put(msg, 3);
ctrl[0] = 0x00; /* 0xxxxxxx */
ctrl[1] = ctrl[2] = 0x00;
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_ACK_REQ)
ctrl[0] |= (1 << 6);
ctrl[0] |= (pdu->seq_tx >> 4) & 0x1f;
ctrl[1] |= (pdu->seq_tx & 0x0f) << 4;
ctrl[1] |= (pdu->seq_rx >> 6) & 0x07;
ctrl[2] |= (pdu->seq_rx & 0x3f) << 2;
ctrl[2] |= (pdu->func - OSMO_GPRS_LLC_FUNC_RR) & 0x03;
if (pdu->func == OSMO_GPRS_LLC_FUNC_SACK) {
if (pdu->sack.len == 0)
return -EINVAL;
msgb_put_u8(msg, pdu->sack.len - 1);
memcpy(msgb_put(msg, pdu->sack.len),
&pdu->sack.r[0], pdu->sack.len);
}
break;
case OSMO_GPRS_LLC_FMT_S:
ctrl = msgb_put(msg, 2);
ctrl[0] = 0x80; /* 10xxxxxx */
ctrl[1] = 0x00;
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_ACK_REQ)
ctrl[1] |= 0x20;
ctrl[0] |= (pdu->seq_rx >> 6) & 0x07;
ctrl[1] |= (pdu->seq_rx & 0x3f) << 2;
ctrl[1] |= (pdu->func - OSMO_GPRS_LLC_FUNC_RR) & 0x03;
if (pdu->func == OSMO_GPRS_LLC_FUNC_SACK) {
if (pdu->sack.len == 0)
return -EINVAL;
memcpy(msgb_put(msg, pdu->sack.len),
&pdu->sack.r[0], pdu->sack.len);
}
break;
case OSMO_GPRS_LLC_FMT_UI:
ctrl = msgb_put(msg, 2);
ctrl[0] = 0xc0; /* 110xxxxx */
ctrl[1] = 0x00;
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_MAC_PRES)
ctrl[0] |= (1 << 4);
ctrl[0] |= (pdu->seq_tx >> 6) & 0x07;
ctrl[1] |= (pdu->seq_tx & 0x3f) << 2;
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_ENC_MODE)
ctrl[1] |= (1 << 1);
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_PROT_MODE)
ctrl[1] |= (1 << 0);
break;
case OSMO_GPRS_LLC_FMT_U:
ctrl = msgb_put(msg, 1);
ctrl[0] = 0xe0; /* 111xxxxx */
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_FOLL_FIN)
ctrl[0] |= (1 << 4);
switch (pdu->func) {
case OSMO_GPRS_LLC_FUNC_NULL:
ctrl[0] |= GPRS_LLC_U_NULL_CMD;
break;
case OSMO_GPRS_LLC_FUNC_DM:
ctrl[0] |= GPRS_LLC_U_DM_RESP;
break;
case OSMO_GPRS_LLC_FUNC_DISC:
ctrl[0] |= GPRS_LLC_U_DISC_CMD;
break;
case OSMO_GPRS_LLC_FUNC_UA:
ctrl[0] |= GPRS_LLC_U_UA_RESP;
break;
case OSMO_GPRS_LLC_FUNC_SABM:
ctrl[0] |= GPRS_LLC_U_SABM_CMD;
break;
case OSMO_GPRS_LLC_FUNC_FRMR:
ctrl[0] |= GPRS_LLC_U_FRMR_RESP;
break;
case OSMO_GPRS_LLC_FUNC_XID:
ctrl[0] |= GPRS_LLC_U_XID;
break;
default:
LOGP(DLLC, LOGL_ERROR,
"Unknown UI func=0x%02x\n", pdu->func);
return -EINVAL;
}
break;
}
if (pdu->data_len > 0) {
uint8_t *data = msgb_put(msg, pdu->data_len);
memcpy(data, pdu->data, pdu->data_len);
}
/* 5.5a Message Authentication Code (MAC) field */
if (pdu->flags & OSMO_GPRS_LLC_PDU_F_MAC_PRES) {
/* TODO: calculate MAC (see 3GPP TS 43.020) */
LOGP(DLLC, LOGL_ERROR,
"Message Authentication Code (MAC) is not implemented\n");
return -ENOTSUP;
}
/* 5.5 Frame Check Sequence (FCS) field */
crc_len = msg->tail - addr;
if (~pdu->flags & OSMO_GPRS_LLC_PDU_F_PROT_MODE)
crc_len = OSMO_MIN(crc_len, UI_HDR_LEN + N202);
fcs = osmo_gprs_llc_fcs(addr, crc_len);
msgb_put_u8(msg, fcs & 0xff);
msgb_put_u8(msg, (fcs >> 8) & 0xff);
msgb_put_u8(msg, (fcs >> 16) & 0xff);
return 0;
}
int osmo_gprs_llc_pdu_decode(struct osmo_gprs_llc_pdu_decoded *pdu,
const uint8_t *data, size_t data_len)
{
const uint8_t *addr = &data[0];
const uint8_t *ctrl = &data[1];
#define check_len(len, text) \
do { \
if (data_len < (len)) { \
LOGP(DLLC, LOGL_ERROR, "Failed to parse LLC PDU: %s\n", text); \
return -EINVAL; \
} \
} while (0)
/* 5.5 Frame Check Sequence (FCS) field */
check_len(CRC24_LENGTH, "missing Frame Check Sequence (FCS) field");
pdu->fcs = data[data_len - 3];
pdu->fcs |= data[data_len - 2] << 8;
pdu->fcs |= data[data_len - 1] << 16;
data_len -= CRC24_LENGTH;
/* 6.2.0 Address field format */
check_len(1, "missing Address field");
data_len -= 1;
/* Initial assumption: FCS covers hdr + all inf fields */
pdu->flags |= OSMO_GPRS_LLC_PDU_F_PROT_MODE;
/* 6.2.1 Protocol Discriminator bit (PD): shall be 0 */
if (*addr & 0x80) {
LOGP(DLLC, LOGL_ERROR, "Protocol Discriminator shall be 0\n");
return -EINVAL;
}
/* 6.2.2 Commmand/Response bit (C/R) */
if (*addr & 0x40)
pdu->flags |= OSMO_GPRS_LLC_PDU_F_CMD_RSP;
/* 6.2.3 Service Access Point Identifier (SAPI) */
pdu->sapi = *addr & 0x0f;
/* Check for reserved SAPI */
switch (*addr & 0x0f) {
case 0x00:
case 0x04:
case 0x06:
case 0x0a:
case 0x0c:
case 0x0d:
case 0x0f:
LOGP(DLLC, LOGL_ERROR, "Unknown SAPI=%u\n", pdu->sapi);
return -EINVAL;
}
/* U format has the shortest control field length=1 */
check_len(1, "missing Control field");
/* 6.3.0 Control field formats */
if ((ctrl[0] & 0x80) == 0) {
/* 6.3.1 Information transfer format - I */
pdu->fmt = OSMO_GPRS_LLC_FMT_I;
check_len(3, "I format Control field is too short");
data_len -= 3;
pdu->data = ctrl + 3;
/* pdu->data_len is set below */
if (ctrl[0] & 0x40)
pdu->flags |= OSMO_GPRS_LLC_PDU_F_ACK_REQ;
pdu->seq_tx = (ctrl[0] & 0x1f) << 4;
pdu->seq_tx |= (ctrl[1] >> 4);
pdu->seq_rx = (ctrl[1] & 0x7) << 6;
pdu->seq_rx |= (ctrl[2] >> 2);
switch (ctrl[2] & 0x03) {
case 0:
pdu->func = OSMO_GPRS_LLC_FUNC_RR;
break;
case 1:
pdu->func = OSMO_GPRS_LLC_FUNC_ACK;
break;
case 2:
pdu->func = OSMO_GPRS_LLC_FUNC_RNR;
break;
case 3:
pdu->func = OSMO_GPRS_LLC_FUNC_SACK;
check_len(1, "I func=SACK is too short");
pdu->sack.len = (ctrl[3] & 0x1f) + 1; /* 1 .. 32 */
/* The R(n) bitmask takes len=(K + 1) octets */
check_len(pdu->sack.len, "I func=SACK is too short");
memcpy(&pdu->sack.r[0], ctrl + 4, pdu->sack.len);
pdu->data += 1 + pdu->sack.len;
data_len -= 1 + pdu->sack.len;
break;
}
pdu->data_len = data_len;
} else if ((ctrl[0] & 0xc0) == 0x80) {
/* 6.3.2 Supervisory format - S */
pdu->fmt = OSMO_GPRS_LLC_FMT_S;
check_len(2, "S format Control field is too short");
data_len -= 2;
pdu->data = NULL;
pdu->data_len = 0;
if (ctrl[0] & 0x20)
pdu->flags |= OSMO_GPRS_LLC_PDU_F_ACK_REQ;
pdu->seq_rx = (ctrl[0] & 0x7) << 6;
pdu->seq_rx |= (ctrl[1] >> 2);
switch (ctrl[1] & 0x03) {
case 0:
pdu->func = OSMO_GPRS_LLC_FUNC_RR;
break;
case 1:
pdu->func = OSMO_GPRS_LLC_FUNC_ACK;
break;
case 2:
pdu->func = OSMO_GPRS_LLC_FUNC_RNR;
break;
case 3:
pdu->func = OSMO_GPRS_LLC_FUNC_SACK;
/* The R(n) bitmask takes all remaining octets */
check_len(1, "S func=SACK is too short");
pdu->sack.len = data_len; /* 1 .. 32 */
memcpy(&pdu->sack.r[0], ctrl + 2, pdu->sack.len);
break;
}
} else if ((ctrl[0] & 0xe0) == 0xc0) {
/* 6.3.3 Unconfirmed Information format - UI */
pdu->fmt = OSMO_GPRS_LLC_FMT_UI;
pdu->func = OSMO_GPRS_LLC_FUNC_UI;
check_len(2, "UI format Control field is too short");
data_len -= 2;
pdu->data = ctrl + 2;
pdu->data_len = data_len;
pdu->seq_tx = (ctrl[0] & 0x7) << 6;
pdu->seq_tx |= (ctrl[1] >> 2);
if (ctrl[0] & 0x10) {
check_len(sizeof(pdu->mac), "missing MAC field");
pdu->data_len -= sizeof(pdu->mac);
data_len -= sizeof(pdu->mac);
pdu->mac = osmo_load32le(&pdu->data[data_len]);
pdu->flags |= OSMO_GPRS_LLC_PDU_F_MAC_PRES;
}
if (ctrl[1] & 0x02)
pdu->flags |= OSMO_GPRS_LLC_PDU_F_ENC_MODE;
if (~ctrl[1] & 0x01) /* FCS covers hdr + N202 octets */
pdu->flags &= ~OSMO_GPRS_LLC_PDU_F_PROT_MODE;
} else {
/* 6.3.4 Unnumbered format - U */
pdu->fmt = OSMO_GPRS_LLC_FMT_U;
check_len(1, "U format Control field is too short");
data_len -= 1;
pdu->data = NULL;
pdu->data_len = 0;
if (ctrl[0] & 0x10)
pdu->flags |= OSMO_GPRS_LLC_PDU_F_FOLL_FIN;
switch (ctrl[0] & 0x0f) {
case GPRS_LLC_U_NULL_CMD:
pdu->func = OSMO_GPRS_LLC_FUNC_NULL;
break;
case GPRS_LLC_U_DM_RESP:
pdu->func = OSMO_GPRS_LLC_FUNC_DM;
break;
case GPRS_LLC_U_DISC_CMD:
pdu->func = OSMO_GPRS_LLC_FUNC_DISC;
break;
case GPRS_LLC_U_UA_RESP:
pdu->func = OSMO_GPRS_LLC_FUNC_UA;
break;
case GPRS_LLC_U_SABM_CMD:
pdu->func = OSMO_GPRS_LLC_FUNC_SABM;
break;
case GPRS_LLC_U_FRMR_RESP:
pdu->func = OSMO_GPRS_LLC_FUNC_FRMR;
break;
case GPRS_LLC_U_XID:
pdu->func = OSMO_GPRS_LLC_FUNC_XID;
pdu->data = ctrl + 1;
pdu->data_len = data_len;
break;
default:
LOGP(DLLC, LOGL_ERROR, "Unknown U func=0x%02x\n", ctrl[0] & 0x0f);
return -ENOTSUP;
}
}
#undef check_len
return 0;
}

View File

@ -1,4 +1,5 @@
SUBDIRS = \
llc_pdu_codec \
ts_44_018 \
ts_44_060 \
$(NULL)

View File

@ -0,0 +1,24 @@
AM_CFLAGS = \
-Wall \
$(LIBOSMOCORE_CFLAGS) \
-I$(top_srcdir)/include/ \
$(NULL)
AM_LDFLAGS = \
-no-install \
$(NULL)
check_PROGRAMS = \
pdu_codec_test \
$(NULL)
EXTRA_DIST = \
pdu_codec_test.ok \
pdu_codec_test.err \
$(NULL)
pdu_codec_test_SOURCES = pdu_codec_test.c
pdu_codec_test_LDADD = \
$(LIBOSMOCORE_LIBS) \
$(top_builddir)/src/llc/libosmo-gprs-llc.la \
$(NULL)

View File

@ -0,0 +1,102 @@
/* LLC PDU codec tests
*
* (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Vadim Yanitskiy <vyanitskiy@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/gprs/llc/llc.h>
static void *tall_ctx = NULL;
static void test_pdu_dec_enc(void)
{
static const char *testData[] = {
/* SAPI=1 (GMM), UI func=UI C/R=0 PM=0 N(U)=4 */
"01c010080509afe633",
/* SAPI=1 (GMM), UI func=UI C/R=1 PM=1 N(U)=0 */
"41c001081502de8e9a",
/* SAPI=1 (GMM), U func=NULL C/R=0 P/F=0 */
"01e01ca2b3",
/* SAPI=3 (SNDCP3), U func=XID C/R=1 P/F=1 */
"43fb01001601f41a05df8c7c4e",
/* SAPI=3 (SNDCP3), U func=XID C/R=1 P/F=1 */
"03fb1604d216f984",
};
struct msgb *msg = msgb_alloc(1024, "LLC-PDU");
OSMO_ASSERT(msg != NULL);
for (unsigned int i = 0; i < ARRAY_SIZE(testData); i++) {
struct osmo_gprs_llc_pdu_decoded hdr = { 0 };
uint8_t pdu[256];
size_t pdu_len;
int rc;
printf("%s(): decoding testData[%u] = %s\n", __func__, i, testData[i]);
rc = osmo_hexparse(testData[i], &pdu[0], sizeof(pdu));
pdu_len = strlen(testData[i]) / 2;
OSMO_ASSERT(rc == pdu_len);
rc = osmo_gprs_llc_pdu_decode(&hdr, &pdu[0], pdu_len);
printf(" osmo_gprs_llc_pdu_decode() returns %d\n", rc);
printf(" osmo_gprs_llc_pdu_hdr_dump(): %s\n", osmo_gprs_llc_pdu_hdr_dump(&hdr));
if (hdr.data_len > 0) {
printf(" hdr.data[] (len=%zu): %s\n", hdr.data_len,
osmo_hexdump_nospc(hdr.data, hdr.data_len));
}
printf("%s(): encoding decoded testData[%u]\n", __func__, i);
msgb_reset(msg);
rc = osmo_gprs_llc_pdu_encode(msg, &hdr);
printf(" osmo_gprs_llc_pdu_encode() returns %d\n", rc);
printf(" osmo_gprs_llc_pdu_encode(): %s\n", osmo_hexdump_nospc(msg->data, msg->len));
printf(" memcmp() returns %d\n", memcmp(&pdu, msg->data, pdu_len));
}
msgb_free(msg);
printf("\n");
}
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:");
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);
test_pdu_dec_enc();
talloc_free(tall_ctx);
}

View File

View File

@ -0,0 +1,40 @@
test_pdu_dec_enc(): decoding testData[0] = 01c010080509afe633
osmo_gprs_llc_pdu_decode() returns 0
osmo_gprs_llc_pdu_hdr_dump(): SAPI=1, UI func=UI C/R=0 PM=0 E=0 IP=0 N(U)=4 FCS=33e6af
hdr.data[] (len=3): 080509
test_pdu_dec_enc(): encoding decoded testData[0]
osmo_gprs_llc_pdu_encode() returns 0
osmo_gprs_llc_pdu_encode(): 01c010080509afe633
memcmp() returns 0
test_pdu_dec_enc(): decoding testData[1] = 41c001081502de8e9a
osmo_gprs_llc_pdu_decode() returns 0
osmo_gprs_llc_pdu_hdr_dump(): SAPI=1, UI func=UI C/R=1 PM=1 E=0 IP=0 N(U)=0 FCS=9a8ede
hdr.data[] (len=3): 081502
test_pdu_dec_enc(): encoding decoded testData[1]
osmo_gprs_llc_pdu_encode() returns 0
osmo_gprs_llc_pdu_encode(): 41c001081502de8e9a
memcmp() returns 0
test_pdu_dec_enc(): decoding testData[2] = 01e01ca2b3
osmo_gprs_llc_pdu_decode() returns 0
osmo_gprs_llc_pdu_hdr_dump(): SAPI=1, U func=NULL C/R=0 P/F=0 FCS=b3a21c
test_pdu_dec_enc(): encoding decoded testData[2]
osmo_gprs_llc_pdu_encode() returns 0
osmo_gprs_llc_pdu_encode(): 01e01ca2b3
memcmp() returns 0
test_pdu_dec_enc(): decoding testData[3] = 43fb01001601f41a05df8c7c4e
osmo_gprs_llc_pdu_decode() returns 0
osmo_gprs_llc_pdu_hdr_dump(): SAPI=3, U func=XID C/R=1 P/F=1 FCS=4e7c8c
hdr.data[] (len=8): 01001601f41a05df
test_pdu_dec_enc(): encoding decoded testData[3]
osmo_gprs_llc_pdu_encode() returns 0
osmo_gprs_llc_pdu_encode(): 43fb01001601f41a05df8c7c4e
memcmp() returns 0
test_pdu_dec_enc(): decoding testData[4] = 03fb1604d216f984
osmo_gprs_llc_pdu_decode() returns 0
osmo_gprs_llc_pdu_hdr_dump(): SAPI=3, U func=XID C/R=0 P/F=1 FCS=84f916
hdr.data[] (len=3): 1604d2
test_pdu_dec_enc(): encoding decoded testData[4]
osmo_gprs_llc_pdu_encode() returns 0
osmo_gprs_llc_pdu_encode(): 03fb1604d216f984
memcmp() returns 0

View File

@ -1,6 +1,13 @@
AT_INIT
AT_BANNER([Regression tests])
AT_SETUP([llc/pdu_codec])
AT_KEYWORDS([llc pdu codec])
cat $abs_srcdir/llc_pdu_codec/pdu_codec_test.ok > expout
cat $abs_srcdir/llc_pdu_codec/pdu_codec_test.err > experr
AT_CHECK([$abs_top_builddir/tests/llc_pdu_codec/pdu_codec_test], [0], [expout], [experr])
AT_CLEANUP
AT_SETUP([rlcmac/ts_44_018])
AT_KEYWORDS([rlcmac ts_44_018])
cat $abs_srcdir/ts_44_018/ts_44_018_test.ok > expout