aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-07-26 19:46:23 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2023-07-28 13:48:22 +0200
commit6e1a35bab76ecf6fbd9b41454593aadf3ff556cf (patch)
tree12b19a8bdea9de1fe92ee9ed846b41d6ee4edb14
parent5aa16e1c8d2bf6335aab7300706e699c283cf7b1 (diff)
llc: Submit LL-XID-IND to L3 if N201-U or N201-I changes
-rw-r--r--src/llc/llc.c35
-rw-r--r--src/llc/llc_ll.c13
2 files changed, 31 insertions, 17 deletions
diff --git a/src/llc/llc.c b/src/llc/llc.c
index e5e9538..bcd33b5 100644
--- a/src/llc/llc.c
+++ b/src/llc/llc.c
@@ -554,6 +554,7 @@ static int gprs_llc_lle_process_xid_ind(struct gprs_llc_lle *lle,
unsigned int xid_fields_len;
int rc, i;
struct gprs_llc_xid_field *xid_field_request_l3 = NULL;
+ bool n201_changed = false;
/* Parse and analyze XID-Request */
rc = gprs_llc_xid_decode(xid_fields, ARRAY_SIZE(xid_fields),
@@ -577,11 +578,21 @@ static int gprs_llc_lle_process_xid_ind(struct gprs_llc_lle *lle,
switch (xid_fields[i].type) {
case OSMO_GPRS_LLC_XID_T_N201_U:
LOGLLE(lle, LOGL_INFO, "Peer requested N201-U=%u\n", xid_fields[i].val);
- lle->params.n201_u = xid_fields[i].val;
+ if (lle->params.n201_u != xid_fields[i].val) {
+ lle->params.n201_u = xid_fields[i].val;
+ /* TS 44.064 8.5.3.0 "LL-XID-IND shall be indicated to layer 3 if N201-U or N201-I have been changed." */
+ n201_changed = true;
+ }
break;
case OSMO_GPRS_LLC_XID_T_N201_I:
LOGLLE(lle, LOGL_INFO, "Peer requested N201-I=%u\n", xid_fields[i].val);
- lle->params.n201_i = xid_fields[i].val;
+ if (lle->params.n201_i != xid_fields[i].val) {
+ lle->params.n201_i = xid_fields[i].val;
+ n201_changed = true;
+ }
+ break;
+ case OSMO_GPRS_LLC_XID_T_L3_PAR:
+ xid_field_request_l3 = &xid_fields[i];
break;
default:
continue;
@@ -593,17 +604,19 @@ static int gprs_llc_lle_process_xid_ind(struct gprs_llc_lle *lle,
OSMO_ASSERT(lle->rx_xid);
lle->rx_xid_len = xid_fields_len;
- /* Forward SNDCP-XID fields to Layer 3 (SNDCP) */
- for (i = 0; i < xid_fields_len; i++) {
- if (xid_fields[i].type == OSMO_GPRS_LLC_XID_T_L3_PAR) {
- xid_field_request_l3 = &xid_fields[i];
- gprs_llc_lle_submit_prim_ll_xid_ind(lle, xid_field_request_l3);
- /* delay answer until we get LL-XID.resp from SNDCP: */
- return rc;
- }
+ if (n201_changed || xid_field_request_l3) {
+ /* TS 44.064 8.5.3.0 "LL-XID-IND shall be indicated to layer 3
+ * if N201-U or N201-I have been changed." */
+ /* Forward SNDCP-XID fields to Layer 3 (SNDCP) */
+ rc = gprs_llc_lle_submit_prim_ll_xid_ind(lle, xid_field_request_l3);
}
- rc = gprs_llc_lle_tx_xid_resp(lle, NULL, 0);
+ if (!xid_field_request_l3) {
+ /* TS 44.065 6.8: "If the SNDCP entity receives an LL-XID.indication without
+ * an SNDCP XID block, it shall not respond with the LL-XID.response primitive."
+ * Hence, if no SNDCP XID block, send response now: */
+ rc = gprs_llc_lle_tx_xid_resp(lle, NULL, 0);
+ } /* else: delay answer until we get LL-XID.resp from SNDCP. */
return rc;
}
diff --git a/src/llc/llc_ll.c b/src/llc/llc_ll.c
index 0ba690b..8a3c2ae 100644
--- a/src/llc/llc_ll.c
+++ b/src/llc/llc_ll.c
@@ -172,14 +172,15 @@ int gprs_llc_lle_submit_prim_ll_xid_ind(struct gprs_llc_lle *lle,
const struct gprs_llc_xid_field *xid_field_request_l3)
{
struct osmo_gprs_llc_prim *llc_prim_tx;
- OSMO_ASSERT(xid_field_request_l3);
llc_prim_tx = gprs_llc_prim_alloc_ll_xid_ind(lle->llme->tlli, lle->sapi, NULL, xid_field_request_l3->var.val_len);
OSMO_ASSERT(llc_prim_tx);
- llc_prim_tx->ll.l3_pdu_len = xid_field_request_l3->var.val_len;
- llc_prim_tx->ll.l3_pdu = msgb_put(llc_prim_tx->oph.msg, llc_prim_tx->ll.l3_pdu_len);
- if (llc_prim_tx->ll.l3_pdu_len > 0)
- memcpy(llc_prim_tx->ll.l3_pdu, xid_field_request_l3->var.val,
- llc_prim_tx->ll.l3_pdu_len);
+ if (xid_field_request_l3) {
+ llc_prim_tx->ll.l3_pdu_len = xid_field_request_l3->var.val_len;
+ llc_prim_tx->ll.l3_pdu = msgb_put(llc_prim_tx->oph.msg, llc_prim_tx->ll.l3_pdu_len);
+ if (llc_prim_tx->ll.l3_pdu_len > 0)
+ memcpy(llc_prim_tx->ll.l3_pdu, xid_field_request_l3->var.val,
+ llc_prim_tx->ll.l3_pdu_len);
+ }
llc_prim_tx->ll.xid.n201_i = lle->params.n201_i;
llc_prim_tx->ll.xid.n201_u = lle->params.n201_u;
return gprs_llc_prim_call_up_cb(llc_prim_tx);