diff --git a/include/osmocom/gprs/llc/llc_prim.h b/include/osmocom/gprs/llc/llc_prim.h index 66b8a2a..a2b53cb 100644 --- a/include/osmocom/gprs/llc/llc_prim.h +++ b/include/osmocom/gprs/llc/llc_prim.h @@ -284,6 +284,8 @@ struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_llgm_assign_req(uint32_t tll struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_llgm_reset_req(uint32_t tlli); /* Alloc primitive for LL SAP: */ +struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_ll_establish_req(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, + uint8_t *l3_par, unsigned int l3_par_len); struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_ll_xid_req(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, uint8_t *l3_par, unsigned int l3_par_len); struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_ll_xid_resp(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, diff --git a/include/osmocom/gprs/llc/llc_private.h b/include/osmocom/gprs/llc/llc_private.h index 3f7ee15..994acd8 100644 --- a/include/osmocom/gprs/llc/llc_private.h +++ b/include/osmocom/gprs/llc/llc_private.h @@ -287,6 +287,8 @@ struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_grr_unitdata_req( /* llc_ll.c */ int gprs_llc_prim_ll_upper_down(struct osmo_gprs_llc_prim *llc_prim); +struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_establish_cnf(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, + uint8_t *l3_par, unsigned int l3_par_len); struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_xid_ind(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, uint8_t *l3_par, unsigned int l3_par_len); struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_xid_cnf(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, @@ -312,6 +314,7 @@ struct gprs_llc_lle *gprs_llc_lle_for_rx_by_tlli_sapi(const uint32_t tlli, int gprs_llc_lle_rx_unitdata_ind(struct gprs_llc_lle *lle, uint8_t *ll_pdu, size_t ll_pdu_len, struct gprs_llc_pdu_decoded *pdu_dec); void gprs_llc_llme_free(struct gprs_llc_llme *llme); +int gprs_llc_lle_tx_sabm(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int l3par_len); int gprs_llc_lle_tx_xid(const struct gprs_llc_lle *lle, uint8_t *xid_payload, unsigned int xid_payload_len, bool is_cmd); int gprs_llc_lle_tx_xid_req(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int l3par_len); int gprs_llc_lle_tx_xid_resp(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int l3par_len); diff --git a/src/llc/llc.c b/src/llc/llc.c index e9e8e3b..3831f8a 100644 --- a/src/llc/llc.c +++ b/src/llc/llc.c @@ -432,6 +432,13 @@ static int gprs_llc_lle_generate_xid(struct gprs_llc_lle *lle, uint8_t *bytes, i return rc; } +/* LL-ESTABLISH negotiation (See also: TS 101 351, Section 7.2.2.2) */ +int gprs_llc_lle_tx_sabm(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int l3par_len) +{ + LOGLLE(lle, LOGL_ERROR, "Tx SABM: ABM mode not supported yet!\n"); + return -ENOTSUP; +} + /* Set of LL-XID negotiation (See also: TS 101 351, Section 7.2.2.4) */ int gprs_llc_lle_tx_xid_req(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int l3par_len) { diff --git a/src/llc/llc_ll.c b/src/llc/llc_ll.c index 72ef889..43a0951 100644 --- a/src/llc/llc_ll.c +++ b/src/llc/llc_ll.c @@ -54,6 +54,30 @@ static inline struct osmo_gprs_llc_prim *llc_prim_ll_alloc(enum osmo_gprs_llc_ll return gprs_llc_prim_alloc(OSMO_GPRS_LLC_SAP_LL, type, operation, l3_len); } +/* 7.2.2.2 LL-ESTABLISH.req (MS/SGSN) */ +struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_ll_establish_req(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, uint8_t *l3_par, unsigned int l3_par_len) +{ + struct osmo_gprs_llc_prim *llc_prim; + llc_prim = llc_prim_ll_alloc(OSMO_GPRS_LLC_LL_ESTABLISH, PRIM_OP_REQUEST, l3_par_len); + llc_prim->ll.tlli = tlli; + llc_prim->ll.sapi = ll_sapi; + llc_prim->ll.l3_pdu = l3_par; + llc_prim->ll.l3_pdu_len = l3_par_len; + return llc_prim; +} + +/* 7.2.2.2 LL-ESTABLISH.cnf (MS/SGSN) */ +struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_establish_cnf(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, uint8_t *l3_par, unsigned int l3_par_len) +{ + struct osmo_gprs_llc_prim *llc_prim; + llc_prim = llc_prim_ll_alloc(OSMO_GPRS_LLC_LL_ESTABLISH, PRIM_OP_CONFIRM, l3_par_len); + llc_prim->ll.tlli = tlli; + llc_prim->ll.sapi = ll_sapi; + llc_prim->ll.l3_pdu = l3_par; + llc_prim->ll.l3_pdu_len = l3_par_len; + return llc_prim; +} + /* 7.2.2.4 LL-XID.req (MS/SGSN) */ struct osmo_gprs_llc_prim *osmo_gprs_llc_prim_alloc_ll_xid_req(uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, uint8_t *l3_par, unsigned int l3_par_len) { @@ -172,6 +196,28 @@ int gprs_llc_lle_submit_prim_ll_xid_cnf(struct gprs_llc_lle *lle, * Handling from upper layers: ********************************/ +/* 7.2.2.2 LL-ESTABLISH.req (MS/SGSN):*/ +static int llc_prim_handle_ll_establish_req(struct osmo_gprs_llc_prim *llc_prim) +{ + int rc = 0; + struct gprs_llc_lle *lle; + + lle = gprs_llc_find_lle_by_tlli_sapi(llc_prim->ll.tlli, llc_prim->ll.sapi); + if (!lle) { + LOGLLC(LOGL_NOTICE, "Rx %s: Unknown TLLI 0x%08x SAPI 0x%02x\n", + osmo_gprs_llc_prim_name(llc_prim), llc_prim->ll.tlli, + llc_prim->ll.sapi); + rc = -ENOKEY; + goto ret_free; + } + + rc = gprs_llc_lle_tx_sabm(lle, llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len); + +ret_free: + msgb_free(llc_prim->oph.msg); + return rc; +} + /* 7.2.2.4 LL-XID.req (MS/SGSN):*/ static int llc_prim_handle_ll_xid_req(struct osmo_gprs_llc_prim *llc_prim) { @@ -243,6 +289,11 @@ int gprs_llc_prim_ll_upper_down(struct osmo_gprs_llc_prim *llc_prim) { int rc; switch (OSMO_PRIM_HDR(&llc_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_LLC_LL_ESTABLISH, PRIM_OP_REQUEST): + OSMO_ASSERT(g_llc_ctx->location == OSMO_GPRS_LLC_LOCATION_MS || + g_llc_ctx->location == OSMO_GPRS_LLC_LOCATION_SGSN); + rc = llc_prim_handle_ll_establish_req(llc_prim); + break; case OSMO_PRIM(OSMO_GPRS_LLC_LL_XID, PRIM_OP_REQUEST): OSMO_ASSERT(g_llc_ctx->location == OSMO_GPRS_LLC_LOCATION_MS || g_llc_ctx->location == OSMO_GPRS_LLC_LOCATION_SGSN); diff --git a/tests/llc/llc_prim_test.c b/tests/llc/llc_prim_test.c index 83a7556..54dabb6 100644 --- a/tests/llc/llc_prim_test.c +++ b/tests/llc/llc_prim_test.c @@ -231,6 +231,11 @@ static void test_llc_prim_sgsn(void) OSMO_ASSERT(rc == 0); char xid_l3_pars[] = "xid-l3-dummy-buffer"; + llc_prim = osmo_gprs_llc_prim_alloc_ll_establish_req(tlli, OSMO_GPRS_LLC_SAPI_SNDCP3, (uint8_t *)xid_l3_pars, sizeof(xid_l3_pars)); + OSMO_ASSERT(llc_prim); + rc = osmo_gprs_llc_prim_upper_down(llc_prim); + OSMO_ASSERT(rc == -ENOTSUP); /* ABM mode not supported yet. */ + llc_prim = osmo_gprs_llc_prim_alloc_ll_xid_req(tlli, OSMO_GPRS_LLC_SAPI_SNDCP3, (uint8_t *)xid_l3_pars, sizeof(xid_l3_pars)); OSMO_ASSERT(llc_prim); rc = osmo_gprs_llc_prim_upper_down(llc_prim); diff --git a/tests/llc/llc_prim_test.err b/tests/llc/llc_prim_test.err index 667b423..444f3da 100644 --- a/tests/llc/llc_prim_test.err +++ b/tests/llc/llc_prim_test.err @@ -13,6 +13,8 @@ DLGLOBAL NOTICE LLME(ffffffff/e1c5d364){UNASSIGNED} LLGM Assign pre (e1c5d364 => DLGLOBAL NOTICE LLME(e1c5d364/e1c5d364){ASSIGNED} LLGM Assign post (e1c5d364 => e1c5d364) DLGLOBAL INFO Rx from upper layers: LLGMM-RESET.request DLGLOBAL INFO LLME(e1c5d364/e1c5d364){ASSIGNED} LLGMM-RESET.request +DLGLOBAL INFO Rx from upper layers: LL-ESTABLISH.request +DLGLOBAL ERROR LLE(e1c5d364/e1c5d364,SNDCP3){UNASSIGNED} Tx SABM: ABM mode not supported yet! DLGLOBAL INFO Rx from upper layers: LL-XID.request DLGLOBAL NOTICE LLE(e1c5d364/e1c5d364,SNDCP3){UNASSIGNED} Sending XID type L3-Params (30 bytes) request to MS... DLGLOBAL INFO Rx from upper layers: LL-UNITDATA.request