pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/30907 )
Change subject: sndcp: Initial support for async SN-XID.ind and SN-XID.rsp ...................................................................... sndcp: Initial support for async SN-XID.ind and SN-XID.rsp Before this patch, the response was being crafted synchronously through a direct function call. This patch provides initial support to trigger the primitives so that the application using the SNDCP layer can handle the indication and submit a response. The different XID L3 params are still not being passed to the app, that will be done in a subsequent patch. Change-Id: I0a5069fd3dc0d6c3dd28aeae09b51c49dd8be92d --- M include/osmocom/gprs/sndcp/sndcp_prim.h M include/osmocom/gprs/sndcp/sndcp_private.h M src/sndcp/sndcp.c M src/sndcp/sndcp_prim.c M tests/sndcp/sndcp_prim_test.c M tests/sndcp/sndcp_prim_test.err M tests/sndcp/sndcp_prim_test.ok 7 files changed, 95 insertions(+), 16 deletions(-) Approvals: Jenkins Builder: Verified fixeria: Looks good to me, but someone else must approve msuraev: Looks good to me, but someone else must approve pespin: Looks good to me, approved diff --git a/include/osmocom/gprs/sndcp/sndcp_prim.h b/include/osmocom/gprs/sndcp/sndcp_prim.h index 591e75f..b19498f 100644 --- a/include/osmocom/gprs/sndcp/sndcp_prim.h +++ b/include/osmocom/gprs/sndcp/sndcp_prim.h @@ -99,7 +99,8 @@ } xid_req; /* OSMO_GPRS_SNDCP_SN_XID | Ind */ struct { - uint8_t *req_xid; + uint8_t nsapi; + uint8_t *req_xid; /* TODO: theses need to be passed already decoded as in xid_req above */ uint32_t req_xid_len; } xid_ind; /* OSMO_GPRS_SNDCP_SN_XID | Rsp */ diff --git a/include/osmocom/gprs/sndcp/sndcp_private.h b/include/osmocom/gprs/sndcp/sndcp_private.h index ac6c660..206b660 100644 --- a/include/osmocom/gprs/sndcp/sndcp_private.h +++ b/include/osmocom/gprs/sndcp/sndcp_private.h @@ -161,6 +161,10 @@ uint8_t *l3xid_req; unsigned int l3xid_req_len; + /* Copy of the requested XID fields array we have received with the last + * originated XID-Request from peer. NULL if not existing (and l3xid_req_len = 0) */ + struct llist_head *l3_xid_comp_fields_req_from_peer; + /* TODO: taken from lle.params and not yet set ever in code! */ uint16_t n201_u; uint16_t n201_i; @@ -190,6 +194,7 @@ /* sndcp_prim.c: */ struct osmo_gprs_sndcp_prim *gprs_sndcp_prim_alloc_sn_unitdata_ind(uint32_t tlli, uint8_t sapi, uint8_t nsapi, uint8_t *npdu, size_t npdu_len); +struct osmo_gprs_sndcp_prim *gprs_sndcp_prim_alloc_sn_xid_ind(uint32_t tlli, uint8_t sapi, uint8_t nsapi); struct osmo_gprs_sndcp_prim *gprs_sndcp_prim_alloc_snsm_activate_rsp(uint32_t tlli, uint8_t nsapi); int gprs_sndcp_prim_call_up_cb(struct osmo_gprs_sndcp_prim *sndcp_prim); int gprs_sndcp_prim_call_down_cb(struct osmo_gprs_llc_prim *llc_prim); @@ -206,6 +211,7 @@ int gprs_sndcp_snme_handle_llc_ll_xid_cnf(struct gprs_sndcp_mgmt_entity *snme, uint32_t sapi, uint8_t *l3params, unsigned int l3params_len); int gprs_sndcp_sne_handle_sn_unitdata_req(struct gprs_sndcp_entity *sne, uint8_t *npdu, unsigned int npdu_len); int gprs_sndcp_sne_handle_sn_xid_req(struct gprs_sndcp_entity *sne, const struct osmo_gprs_sndcp_prim *sndcp_prim); +int gprs_sndcp_sne_handle_sn_xid_rsp(struct gprs_sndcp_entity *sne, const struct osmo_gprs_sndcp_prim *sndcp_prim); #define LOGSNME(snme, level, fmt, args...) \ LOGSNDCP(level, "SNME(%08x) " fmt, \ diff --git a/src/sndcp/sndcp.c b/src/sndcp/sndcp.c index 4ae1aac..252ba06 100644 --- a/src/sndcp/sndcp.c +++ b/src/sndcp/sndcp.c @@ -721,24 +721,30 @@ } /* 5.1.1.7 SN-XID.response */ -/* FIXME: This is currently called directly from gprs_sndcp_snme_handle_llc_ll_xid_ind(). It should go async over SNDCP user instead */ -static int gprs_sndcp_sne_handle_sn_xid_rsp(struct gprs_sndcp_mgmt_entity *snme, uint8_t sapi, const struct llist_head *comp_fields) +/* FIXME: This is currently uses comp_fields stored from gprs_sndcp_snme_handle_llc_ll_xid_ind(). +* It should use info provided by upper layers in the prim instead */ +int gprs_sndcp_sne_handle_sn_xid_rsp(struct gprs_sndcp_entity *sne, const struct osmo_gprs_sndcp_prim *sndcp_prim) { struct osmo_gprs_llc_prim *llc_prim_tx; struct msgb *msg; int rc; - LOGSNME(snme, LOGL_DEBUG, "SN-XID.rsp comp_fields:\n"); - gprs_sndcp_dump_comp_fields(comp_fields, LOGL_DEBUG); + if (!sne->l3_xid_comp_fields_req_from_peer) { + LOGSNE(sne, LOGL_DEBUG, "SN-XID.rsp origianted comp_fields not found!\n"); + return -EINVAL; + } - llc_prim_tx = osmo_gprs_llc_prim_alloc_ll_xid_resp(snme->tlli, sapi, NULL, 256); + LOGSNE(sne, LOGL_DEBUG, "SN-XID.rsp comp_fields:\n"); + gprs_sndcp_dump_comp_fields(sne->l3_xid_comp_fields_req_from_peer, LOGL_DEBUG); + + llc_prim_tx = osmo_gprs_llc_prim_alloc_ll_xid_resp(sne->snme->tlli, sne->llc_sapi, NULL, 256); OSMO_ASSERT(llc_prim_tx); msg = llc_prim_tx->oph.msg; llc_prim_tx->ll.l3_pdu = msg->tail; /* Compile modified SNDCP-XID bytes */ rc = gprs_sndcp_compile_xid(msg->tail, msgb_tailroom(msg), - comp_fields, 0); + sne->l3_xid_comp_fields_req_from_peer, 0); if (rc < 0) { msgb_free(msg); return -EINVAL; @@ -913,6 +919,24 @@ int version; struct llist_head *comp_fields; struct gprs_sndcp_comp_field *comp_field; + struct gprs_sndcp_entity *sne = NULL; + struct osmo_gprs_sndcp_prim *sndcp_prim_tx; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(snme->sne); i++) { + struct gprs_sndcp_entity *sne_i = snme->sne[i]; + if (!sne_i) + continue; + if (sne_i->llc_sapi != sapi) + continue; + LOGSNE(sne_i, LOGL_DEBUG, "LL-XID.ind: Found SNE SAPI=%u\n", sapi); + sne = sne_i; + break; + } + if (!sne) { + LOGSNME(snme, LOGL_ERROR, "LL-XID.ind: No SNDCP entity found having sent a LL-XID.ind (SAPI=%u)\n", sapi); + return -EINVAL; + } /* Some phones send zero byte length SNDCP frames * and do require a confirmation response. */ @@ -923,7 +947,7 @@ /* Parse SNDCP-CID XID-Field */ - comp_fields = gprs_sndcp_parse_xid(&version, g_ctx, + comp_fields = gprs_sndcp_parse_xid(&version, sne, l3params, l3params_len, NULL); @@ -954,9 +978,12 @@ } } - /* FIXME: push SN-XID.ind up to SGSN/MS here, and below should be part of handling SN-XID.rsp from SGSN/MS. */ - rc = gprs_sndcp_sne_handle_sn_xid_rsp(snme, sapi, comp_fields); - talloc_free(comp_fields); + TALLOC_FREE(sne->l3_xid_comp_fields_req_from_peer); + sne->l3_xid_comp_fields_req_from_peer = comp_fields; + + /* Trigger SN-XID.ind to upper layers: */ + sndcp_prim_tx = gprs_sndcp_prim_alloc_sn_xid_ind(sne->snme->tlli, sne->llc_sapi, sne->nsapi); + rc = gprs_sndcp_prim_call_up_cb(sndcp_prim_tx); return rc; } @@ -965,7 +992,7 @@ */ int gprs_sndcp_snme_handle_llc_ll_xid_cnf(struct gprs_sndcp_mgmt_entity *snme, uint32_t sapi, uint8_t *l3params, unsigned int l3params_len) { - /* Note: This function handles an incoming SNDCP-XID confirmiation. + /* Note: This function handles an incoming SNDCP-XID confirmation. * Since the confirmation fields may lack important parameters we * will reconstruct these missing fields using the original request * we have sent. After that we will create (or delete) the diff --git a/src/sndcp/sndcp_prim.c b/src/sndcp/sndcp_prim.c index 09c37b7..63591d7 100644 --- a/src/sndcp/sndcp_prim.c +++ b/src/sndcp/sndcp_prim.c @@ -206,6 +206,17 @@ return sndcp_prim; } +/* 5.1.1.5 SN-XID.indication */ +struct osmo_gprs_sndcp_prim *gprs_sndcp_prim_alloc_sn_xid_ind(uint32_t tlli, uint8_t sapi, uint8_t nsapi) +{ + struct osmo_gprs_sndcp_prim *sndcp_prim; + sndcp_prim = sndcp_prim_sn_alloc(OSMO_GPRS_SNDCP_SN_XID, PRIM_OP_INDICATION, 0); + sndcp_prim->sn.tlli = tlli; + sndcp_prim->sn.sapi = sapi; + sndcp_prim->sn.xid_ind.nsapi = nsapi; + return sndcp_prim; +} + /* 5.1.1.7 SN-XID.response */ struct osmo_gprs_sndcp_prim *osmo_gprs_sndcp_prim_alloc_sn_xid_rsp(uint32_t tlli, uint8_t sapi, uint8_t nsapi) { @@ -358,6 +369,28 @@ return rc; } +/* 5.1.1.7 SN-XID.response:*/ +static int gprs_sndcp_prim_handle_sndcp_sn_xid_rsp(struct osmo_gprs_sndcp_prim *sndcp_prim) +{ + int rc; + struct gprs_sndcp_entity *sne; + + sne = gprs_sndcp_sne_by_dlci_nsapi(sndcp_prim->sn.tlli, sndcp_prim->sn.sapi, + sndcp_prim->sn.xid_rsp.nsapi); + if (!sne) { + LOGSNDCP(LOGL_ERROR, "Message for non-existing SNDCP Entity " + "(TLLI=%08x, SAPI=%u, NSAPI=%u)\n", + sndcp_prim->sn.tlli, sndcp_prim->sn.sapi, + sndcp_prim->sn.xid_rsp.nsapi); + rc = -EIO; + goto ret_free; + } + rc = gprs_sndcp_sne_handle_sn_xid_rsp(sne, sndcp_prim); +ret_free: + msgb_free(sndcp_prim->oph.msg); + return rc; +} + /* SNDCP higher layers push SNDCP primitive down to SNDCP layer: */ int osmo_gprs_sndcp_prim_upper_down(struct osmo_gprs_sndcp_prim *sndcp_prim) { @@ -379,6 +412,9 @@ case OSMO_PRIM(OSMO_GPRS_SNDCP_SN_XID, PRIM_OP_REQUEST): rc = gprs_sndcp_prim_handle_sndcp_sn_xid_req(sndcp_prim); break; + case OSMO_PRIM(OSMO_GPRS_SNDCP_SN_XID, PRIM_OP_RESPONSE): + rc = gprs_sndcp_prim_handle_sndcp_sn_xid_rsp(sndcp_prim); + break; default: rc = gprs_sndcp_prim_handle_unsupported(sndcp_prim); } diff --git a/tests/sndcp/sndcp_prim_test.c b/tests/sndcp/sndcp_prim_test.c index c2e1231..e8c4a7e 100644 --- a/tests/sndcp/sndcp_prim_test.c +++ b/tests/sndcp/sndcp_prim_test.c @@ -137,7 +137,7 @@ rc = osmo_gprs_sndcp_prim_dispatch_snsm(sndcp_prim); OSMO_ASSERT(rc == 0); - /* SN-XID.Req: */ + /* Submit SN-XID.Req, triggers rx of LL-XID.Req: */ sndcp_prim = osmo_gprs_sndcp_prim_alloc_sn_xid_req(tlli, ll_sapi, nsapi); OSMO_ASSERT(sndcp_prim); sndcp_prim->sn.xid_req.pcomp_rfc1144.active = true; @@ -145,18 +145,24 @@ rc = osmo_gprs_sndcp_prim_upper_down(sndcp_prim); OSMO_ASSERT(rc == 0); - /* SN-XID.Cnf: */ + /* Submit LL-XID.Cnf, triggers rx of LL-XID.cnf */ llc_prim = gprs_llc_prim_alloc_ll_xid_cnf(tlli, ll_sapi, (uint8_t *)sndcp_xid, sizeof(sndcp_xid)); OSMO_ASSERT(llc_prim); rc = osmo_gprs_sndcp_prim_lower_up(llc_prim); OSMO_ASSERT(rc == 0); - /* SN-XID.Ind: */ + /* Submit LL-XID.Ind, triggers rx of SN-XID.Ind: */ llc_prim = gprs_llc_prim_alloc_ll_xid_ind(tlli, ll_sapi, (uint8_t *)sndcp_xid, sizeof(sndcp_xid)); OSMO_ASSERT(llc_prim); rc = osmo_gprs_sndcp_prim_lower_up(llc_prim); OSMO_ASSERT(rc == 0); + /* Submit SN-XID.Rsp, triggers rx of LL-XID.Rsp */ + sndcp_prim = osmo_gprs_sndcp_prim_alloc_sn_xid_rsp(tlli, ll_sapi, nsapi); + OSMO_ASSERT(sndcp_prim); + rc = osmo_gprs_sndcp_prim_upper_down(sndcp_prim); + OSMO_ASSERT(rc == 0); + OSMO_ASSERT(osmo_hexparse(sndcp_data_hex, sndcp_data, sizeof(sndcp_data)) > 0); llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(tlli, ll_sapi, (uint8_t *)sndcp_data, sizeof(sndcp_data)); OSMO_ASSERT(llc_prim); diff --git a/tests/sndcp/sndcp_prim_test.err b/tests/sndcp/sndcp_prim_test.err index 5d12fad..f27486d 100644 --- a/tests/sndcp/sndcp_prim_test.err +++ b/tests/sndcp/sndcp_prim_test.err @@ -75,6 +75,7 @@ DLGLOBAL DEBUG SNME(e1c5d364) Rejecting RFC1144 header compression... DLGLOBAL DEBUG SNME(e1c5d364) Rejecting ROHC header compression... DLGLOBAL INFO Rx from lower layers: LL-XID.indication +DLGLOBAL DEBUG SNE(e1c5d364,SNDCP3,5) LL-XID.ind: Found SNE SAPI=3 DLGLOBAL DEBUG SNME(e1c5d364) LL-XID.cnf requested comp_fields: DLGLOBAL DEBUG SNDCP-XID: DLGLOBAL DEBUG struct gprs_sndcp_comp_field { @@ -132,7 +133,8 @@ DLGLOBAL DEBUG } DLGLOBAL DEBUG SNME(e1c5d364) Rejecting RFC1144 header compression... DLGLOBAL DEBUG SNME(e1c5d364) Rejecting ROHC header compression... -DLGLOBAL DEBUG SNME(e1c5d364) SN-XID.rsp comp_fields: +DLGLOBAL INFO Rx from upper layers: SN-XID.response +DLGLOBAL DEBUG SNE(e1c5d364,SNDCP3,5) SN-XID.rsp comp_fields: DLGLOBAL DEBUG SNDCP-XID: DLGLOBAL DEBUG struct gprs_sndcp_comp_field { DLGLOBAL DEBUG entity=0; diff --git a/tests/sndcp/sndcp_prim_test.ok b/tests/sndcp/sndcp_prim_test.ok index 1789413..4a635fc 100644 --- a/tests/sndcp/sndcp_prim_test.ok +++ b/tests/sndcp/sndcp_prim_test.ok @@ -1,5 +1,6 @@ ==== test_sndcp_prim() [start] ==== test_sndcp_prim_down_cb(): Rx LL-XID.request +test_sndcp_prim_up_cb(): Rx SN-XID.indication test_sndcp_prim_down_cb(): Rx LL-XID.response test_sndcp_prim_up_cb(): Rx SN-UNITDATA.indication TLLI=0xe1c5d364 SAPI=SNDCP3 NSAPI=5 NPDU=[75 22 fa 7c ff d9 56 ba 86 c7 2a f3 d2 1d ce bc 88 3a 8e b6 24 7d de 26 6a 58 de 29 be 96 d2 40 94 7f 9f 4d f5 9c 61 d4 19 e9 9a 58 75 21 21 a9 fd 1f d7 96 90 a7 3f fe 5b 59 f0 e7 c1 52 2c aa a1 39 b6 c5 fd 68 2e fc f4 c0 10 9b 7a 64 9d ae 3a ff a3 0f b0 56 7d 4b 52 33 74 13 67 44 6a ce 62 45 ea cb 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ] test_sndcp_prim_down_cb(): Rx LL-UNITDATA.request TLLI=0xe1c5d364 SAPI=SNDCP3 L3=[65 00 00 00 73 6f 6d 65 2d 6e 70 64 75 2d 64 61 74 61 2d 6c 69 6b 65 2d 61 6e 2d 69 70 2d 70 6b 74 00 ] -- To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/30907 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-gprs Gerrit-Branch: master Gerrit-Change-Id: I0a5069fd3dc0d6c3dd28aeae09b51c49dd8be92d Gerrit-Change-Number: 30907 Gerrit-PatchSet: 4 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanits...@sysmocom.de> Gerrit-Reviewer: msuraev <msur...@sysmocom.de> Gerrit-Reviewer: pespin <pes...@sysmocom.de> Gerrit-CC: daniel <dwillm...@sysmocom.de> Gerrit-CC: laforge <lafo...@osmocom.org> Gerrit-CC: lynxis lazus <lyn...@fe80.eu> Gerrit-MessageType: merged