pespin has uploaded this change for review.

View Change

iuup: Rework API to support RFCI IDs != RFCI index

The initially merged IuUP API and implementation assumed that RFCI with
ID was always in the position of its ID inside the list of RFCIs. This
was the case for messages sent by ip.access nano3g as well as our own
osmocom implementation. However it was noticed that other nodes from
other vendors actually use other order, as allowed by the IuUP message
format.
Hence, we need to break the assumption and provide explicit ID
information in the list.

NOTICE: This commit breaks API and ABI compatibility with older versions
of libosmogsm. This mainly affects its only known user: osmo-mgw.

Related: SYS#5969
Change-Id: Ib21cee2e30bf83dff4e167f79541796007af9845
---
M TODO-RELEASE
M include/osmocom/gsm/iuup.h
M src/gsm/iuup.c
M tests/iuup/iuup_test.c
4 files changed, 76 insertions(+), 48 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/82/28182/1
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 0ae28c0..a02a346 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -11,3 +11,4 @@
libosmogsm add struct member Add codec_list_bss_supported to gsm0808_handover_request_ack (more_items flag ensures ABI compat)
libosmogb ABI BREAKAGE Add reset_ack_notification function pointer to struct bssgp_bvc_fsm_ops
libosmogsm add API Add rach_tx_integer_raw2val() in gsm_utils.h
+libosmogsm API BREAKAGE iuup.h osmo_iuup_rnl_config and osmo_iuup_rnl_status (affects osmo-mgw)
diff --git a/include/osmocom/gsm/iuup.h b/include/osmocom/gsm/iuup.h
index 1ea2b2e..db3d5e0 100644
--- a/include/osmocom/gsm/iuup.h
+++ b/include/osmocom/gsm/iuup.h
@@ -42,6 +42,14 @@
uint32_t t_ms; /* time in ms */
uint32_t n_max; /* max number of repetitions */
};
+struct osmo_iuup_rfci {
+ uint8_t used:1,
+ spare1:1,
+ id:6;
+ uint8_t spare2:4,
+ IPTI:4; /* values range 0-15, 4 bits */;
+ uint16_t subflow_sizes[IUUP_MAX_SUBFLOWS];
+};
struct osmo_iuup_rnl_config {
/* transparent (true) or SMpSDU (false): */
bool transparent;
@@ -56,9 +64,8 @@
uint16_t supported_versions_mask;
uint8_t num_rfci;
uint8_t num_subflows;
- uint16_t subflow_sizes[IUUP_MAX_RFCIS][IUUP_MAX_SUBFLOWS];
bool IPTIs_present;
- uint8_t IPTIs[IUUP_MAX_RFCIS]; /* values range 0-15, 4 bits */
+ struct osmo_iuup_rfci rfci[IUUP_MAX_RFCIS];

/* TODO: Indication of delivery of erroneous SDUs*/
struct osmo_iuup_rnl_config_timer t_init;
@@ -84,9 +91,8 @@
uint8_t data_pdu_type;
uint8_t num_rfci;
uint8_t num_subflows;
- uint16_t subflow_sizes[IUUP_MAX_RFCIS][IUUP_MAX_SUBFLOWS];
bool IPTIs_present;
- uint8_t IPTIs[IUUP_MAX_RFCIS]; /* values range 0-15, 4 bits */
+ struct osmo_iuup_rfci rfci[IUUP_MAX_RFCIS];
} initialization;
struct {
} rate_control;
diff --git a/src/gsm/iuup.c b/src/gsm/iuup.c
index eb595ce..edcea3b 100644
--- a/src/gsm/iuup.c
+++ b/src/gsm/iuup.c
@@ -286,13 +286,10 @@
struct iuup_ctrl_init_rfci_hdr *ihdr_rfci;
struct iuup_ctrl_init_tail *itail;
unsigned int i, j;
- uint8_t num_subflows, num_rfci;
uint16_t payload_crc;
+ uint8_t rfci_cnt;
struct msgb *msg;

- num_subflows = iui->config.num_subflows;
- num_rfci = iui->config.num_rfci;
-
itp = osmo_iuup_tnl_prim_alloc(iui, OSMO_IUUP_TNL_UNITDATA, PRIM_OP_REQUEST, IUUP_MSGB_SIZE);
msg = itp->oph.msg;

@@ -307,42 +304,68 @@

ihdr = (struct iuup_ctrl_init_hdr *)msgb_put(msg, sizeof(*ihdr));
ihdr->chain_ind = 0; /* this frame is the last frame for the procedure. TODO: support several */
- ihdr->num_subflows_per_rfci = num_subflows;
+ ihdr->num_subflows_per_rfci = iui->config.num_subflows;
ihdr->ti = iui->config.IPTIs_present ? 1 : 0;
ihdr->spare = 0;

/* RFCI + subflow size part: */
- for (i = 0; i < num_rfci; i++) {
- bool last = (i+1 == num_rfci);
- uint8_t len_size = 1;
- for (j = 0; j < num_subflows; j++) {
- if (iui->config.subflow_sizes[i][j] > UINT8_MAX)
+ rfci_cnt = 0;
+ for (i = 0; i < ARRAY_SIZE(iui->config.rfci); i++) {
+ bool last;
+ uint8_t len_size;
+ struct osmo_iuup_rfci *rfci = &iui->config.rfci[i];
+ if (!rfci->used)
+ continue;
+ rfci_cnt++;
+ last = (rfci_cnt == iui->config.num_rfci);
+
+ len_size = 1;
+ for (j = 0; j < iui->config.num_subflows; j++) {
+ if (rfci->subflow_sizes[j] > UINT8_MAX)
len_size = 2;
}
- ihdr_rfci = (struct iuup_ctrl_init_rfci_hdr *)msgb_put(msg, sizeof(*ihdr_rfci) + len_size * num_subflows);
- ihdr_rfci->rfci = i;
+
+ ihdr_rfci = (struct iuup_ctrl_init_rfci_hdr *)msgb_put(msg, sizeof(*ihdr_rfci) + len_size * iui->config.num_subflows);
+ ihdr_rfci->rfci = rfci->id;
ihdr_rfci->li = len_size - 1;
ihdr_rfci->lri = last;
if (len_size == 2) {
uint16_t *buf = (uint16_t *)&ihdr_rfci->subflow_length[0];
- for (j = 0; j < num_subflows; j++)
- osmo_store16be(iui->config.subflow_sizes[i][j], buf++);
+ for (j = 0; j < iui->config.num_subflows; j++)
+ osmo_store16be(rfci->subflow_sizes[j], buf++);
} else {
- for (j = 0; j < num_subflows; j++)
- ihdr_rfci->subflow_length[j] = iui->config.subflow_sizes[i][j];
+ for (j = 0; j < iui->config.num_subflows; j++)
+ ihdr_rfci->subflow_length[j] = rfci->subflow_sizes[j];
}
+ /* early loop termination: */
+ if (last)
+ break;
+ }
+ /* Sanity check: */
+ if (rfci_cnt != iui->config.num_rfci) {
+ LOGP(DLIUUP, LOGL_ERROR, "rfci_cnt %u != num_rfci %u\n",
+ rfci_cnt, iui->config.num_rfci);
+ msgb_free(msg);
+ return NULL;
}

if (iui->config.IPTIs_present) {
- uint8_t num_bytes = (num_rfci + 1) / 2;
+ uint8_t num_bytes = (iui->config.num_rfci + 1) / 2;
uint8_t *buf = msgb_put(msg, num_bytes);
- for (i = 0; i < num_bytes - 1; i++)
- buf[i] = iui->config.IPTIs[i*2] << 4 |
- (iui->config.IPTIs[i*2 + 1] & 0x0f);
- buf[i] = iui->config.IPTIs[i*2] << 4;
- if (!(num_rfci & 0x01)) /* is even: */
- buf[i] |= (iui->config.IPTIs[i*2 + 1] & 0x0f);
-
+ rfci_cnt = 0;
+ for (i = 0; i < ARRAY_SIZE(iui->config.rfci); i++) {
+ struct osmo_iuup_rfci *rfci = &iui->config.rfci[i];
+ if (!rfci->used)
+ continue;
+ if (!(rfci_cnt & 0x01)) /* is even: */
+ buf[rfci_cnt / 2] = (((uint8_t)rfci->IPTI) << 4);
+ else
+ buf[rfci_cnt / 2] |= (rfci->IPTI & 0x0F);
+ rfci_cnt++;
+ /* early loop termination: */
+ if (rfci_cnt == iui->config.num_rfci)
+ break;
+ }
}

itail = (struct iuup_ctrl_init_tail *)msgb_put(msg, sizeof(*itail));
@@ -368,12 +391,8 @@
irp->u.status.u.initialization.data_pdu_type = iui->config.data_pdu_type;
irp->u.status.u.initialization.num_subflows = iui->config.num_subflows;
irp->u.status.u.initialization.num_rfci = iui->config.num_rfci;
- memcpy(irp->u.status.u.initialization.subflow_sizes, iui->config.subflow_sizes,
- IUUP_MAX_RFCIS * IUUP_MAX_SUBFLOWS * sizeof(iui->config.subflow_sizes[0][0]));
irp->u.status.u.initialization.IPTIs_present = iui->config.IPTIs_present;
- if (iui->config.IPTIs_present)
- memcpy(irp->u.status.u.initialization.IPTIs, iui->config.IPTIs,
- IUUP_MAX_RFCIS * sizeof(iui->config.IPTIs[0]));
+ memcpy(irp->u.status.u.initialization.rfci, iui->config.rfci, sizeof(iui->config.rfci));
return irp;
}

@@ -530,24 +549,27 @@
ihdr_rfci = (struct iuup_ctrl_init_rfci_hdr *)ihdr->rfci_data;

do {
+ struct osmo_iuup_rfci *rfci = &iui->config.rfci[num_rfci];
uint8_t l_size_bytes = ihdr_rfci->li + 1;
is_last = ihdr_rfci->lri;
- if (ihdr_rfci->rfci != num_rfci) {
- LOGPFSML(iui->fi, LOGL_NOTICE, "Initialization: Unexpected RFCI %u at position %u received\n",
- ihdr_rfci->rfci, num_rfci);
+ if (num_rfci >= IUUP_MAX_RFCIS) {
+ LOGPFSML(iui->fi, LOGL_NOTICE, "Initialization: Too many RFCIs received (%u)\n",
+ num_rfci);
err_cause = IUUP_ERR_CAUSE_UNEXPECTED_RFCI;
goto send_nack;
}
+ rfci->used = 1;
+ rfci->id = ihdr_rfci->rfci;
if (l_size_bytes == 2) {
uint16_t *subflow_size = (uint16_t *)ihdr_rfci->subflow_length;
for (i = 0; i < ihdr->num_subflows_per_rfci; i++) {
- iui->config.subflow_sizes[ihdr_rfci->rfci][i] = osmo_load16be(subflow_size);
+ rfci->subflow_sizes[i] = osmo_load16be(subflow_size);
subflow_size++;
}
} else {
uint8_t *subflow_size = ihdr_rfci->subflow_length;
for (i = 0; i < ihdr->num_subflows_per_rfci; i++) {
- iui->config.subflow_sizes[ihdr_rfci->rfci][i] = *subflow_size;
+ rfci->subflow_sizes[i] = *subflow_size;
subflow_size++;
}
}
@@ -561,19 +583,18 @@
uint8_t num_bytes = (num_rfci + 1) / 2;
iui->config.IPTIs_present = true;
for (i = 0; i < num_bytes - 1; i++) {
- iui->config.IPTIs[i*2] = *buf >> 4;
- iui->config.IPTIs[i*2 + 1] = *buf & 0x0f;
+ iui->config.rfci[i*2].IPTI = *buf >> 4;
+ iui->config.rfci[i*2 + 1].IPTI = *buf & 0x0f;
buf++;
}
- iui->config.IPTIs[i*2] = *buf >> 4;
+ iui->config.rfci[i*2].IPTI = *buf >> 4;
if (!(num_rfci & 0x01)) /* is even: */
- iui->config.IPTIs[i*2 + 1] = *buf & 0x0f;
+ iui->config.rfci[i*2 + 1].IPTI = *buf & 0x0f;
buf++;
itail = (struct iuup_ctrl_init_tail *)buf;
} else {
itail = (struct iuup_ctrl_init_tail *)ihdr_rfci;
}
-
if (itail->data_pdu_type > 1) {
LOGPFSML(iui->fi, LOGL_NOTICE, "Initialization: Unexpected Data PDU Type %u received\n", itail->data_pdu_type);
err_cause = IUUP_ERR_CAUSE_UNEXPECTED_VALUE;
diff --git a/tests/iuup/iuup_test.c b/tests/iuup/iuup_test.c
index a58481d..6e3d8ca 100644
--- a/tests/iuup/iuup_test.c
+++ b/tests/iuup/iuup_test.c
@@ -19,14 +19,14 @@
.supported_versions_mask = 0x0001,
.num_rfci = 3,
.num_subflows = 3,
- .subflow_sizes = {
- {81, 103, 60},
- {39, 0, 0},
- {0, 0, 0},
+ .IPTIs_present = true,
+ .rfci = {
+ {.used = 1, .id = 0, .IPTI = 1, .subflow_sizes = {81, 103, 60} },
+ {.used = 1, .id = 1, .IPTI = 7, .subflow_sizes = {39, 0, 0} },
+ {.used = 1, .id = 2, .IPTI = 1, .subflow_sizes = {0, 0, 0} },
},
/* .delivery_err_sdu = All set to 0 (YES) by default, */
.IPTIs_present = true,
- .IPTIs = {1, 7, 1},
.t_init = { .t_ms = IUUP_TIMER_INIT_T_DEFAULT, .n_max = IUUP_TIMER_INIT_N_DEFAULT },
.t_ta = { .t_ms = IUUP_TIMER_TA_T_DEFAULT, .n_max = IUUP_TIMER_TA_N_DEFAULT },
.t_rc = { .t_ms = IUUP_TIMER_RC_T_DEFAULT, .n_max = IUUP_TIMER_RC_N_DEFAULT },

To view, visit change 28182. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Ib21cee2e30bf83dff4e167f79541796007af9845
Gerrit-Change-Number: 28182
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-MessageType: newchange