diff --git a/include/osmocom/gprs/llc/llc_prim.h b/include/osmocom/gprs/llc/llc_prim.h index c03f396..adcd22f 100644 --- a/include/osmocom/gprs/llc/llc_prim.h +++ b/include/osmocom/gprs/llc/llc_prim.h @@ -56,6 +56,7 @@ enum osmo_gprs_llc_ll_prim_type { OSMO_GPRS_LLC_LL_DATA, /* Req/Ind/Cnf: TLLI, L3-PDU, Ref, QoS, Radio Prio */ OSMO_GPRS_LLC_LL_UNITDATA, /* Req/Ind: TLLI, L3-PDU, QoS, Radio Prio, Ciph, ... */ OSMO_GPRS_LLC_LL_STATUS, /* Ind: TLLI, Cause */ + OSMO_GPRS_LLC_LL_ASSIGN, /* Ind: TLLI old, TLLI new; Osmocom specific */ }; extern const struct value_string osmo_gprs_llc_ll_prim_type_names[]; @@ -214,6 +215,10 @@ struct osmo_gprs_llc_ll_prim { struct { uint8_t cause; } status_ind; + /* OSMO_GPRS_LLC_LL_ASSIGN | Ind */ + struct { + uint32_t tlli_new; + } assign_ind; }; }; diff --git a/include/osmocom/gprs/llc/llc_private.h b/include/osmocom/gprs/llc/llc_private.h index 78e6e9f..44d32e2 100644 --- a/include/osmocom/gprs/llc/llc_private.h +++ b/include/osmocom/gprs/llc/llc_private.h @@ -297,6 +297,7 @@ struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_xid_ind(uint32_t tlli, enum os 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, uint8_t *l3_par, unsigned int l3_par_len); +struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_assign_ind(uint32_t old_tlli, uint32_t new_tlli); struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_unitdata_ind( uint32_t tlli, enum osmo_gprs_llc_sapi ll_sapi, uint8_t *l3_pdu, size_t l3_pdu_len); @@ -305,7 +306,7 @@ int gprs_llc_lle_submit_prim_ll_xid_ind(struct gprs_llc_lle *lle, int gprs_llc_lle_submit_prim_ll_xid_cnf(struct gprs_llc_lle *lle, const struct gprs_llc_xid_field *xid_field_response_l3, const struct gprs_llc_xid_field *xid_field_request_l3); - +int gprs_llc_llme_submit_prim_ll_assign_ind(uint32_t old_tlli, uint32_t new_tlli); /* llc_llgmm.c */ int gprs_llc_prim_llgmm_upper_down(struct osmo_gprs_llc_prim *llc_prim); diff --git a/src/llc/llc_ll.c b/src/llc/llc_ll.c index a13a7f5..b907299 100644 --- a/src/llc/llc_ll.c +++ b/src/llc/llc_ll.c @@ -40,6 +40,7 @@ const struct value_string osmo_gprs_llc_ll_prim_type_names[] = { { OSMO_GPRS_LLC_LL_DATA, "DATA" }, { OSMO_GPRS_LLC_LL_UNITDATA, "UNITDATA" }, { OSMO_GPRS_LLC_LL_STATUS, "STATUS" }, + { OSMO_GPRS_LLC_LL_ASSIGN, "ASSIGN" }, { 0, NULL } }; @@ -152,6 +153,17 @@ struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_unitdata_ind( return llc_prim; } +/* LL-ASSIGN.ind (MS/SGSN): Osmocom specific, used to inform TLLI update LLC->SNDCP */ +struct osmo_gprs_llc_prim *gprs_llc_prim_alloc_ll_assign_ind(uint32_t old_tlli, uint32_t new_tlli) +{ + struct osmo_gprs_llc_prim *llc_prim; + llc_prim = llc_prim_ll_alloc(OSMO_GPRS_LLC_LL_ASSIGN, PRIM_OP_INDICATION, 0); + llc_prim->ll.tlli = old_tlli; + llc_prim->ll.sapi = OSMO_GPRS_LLC_SAPI_SNDCP3; /* any SNDCP SAPI is good */ + llc_prim->ll.assign_ind.tlli_new = new_tlli; + return llc_prim; +} + /******************************** * Handling to upper layers: ********************************/ @@ -192,6 +204,16 @@ int gprs_llc_lle_submit_prim_ll_xid_cnf(struct gprs_llc_lle *lle, return gprs_llc_prim_call_up_cb(llc_prim_tx); } + +int gprs_llc_llme_submit_prim_ll_assign_ind(uint32_t old_tlli, uint32_t new_tlli) +{ + struct osmo_gprs_llc_prim *llc_prim_tx; + llc_prim_tx = gprs_llc_prim_alloc_ll_assign_ind(old_tlli, new_tlli); + OSMO_ASSERT(llc_prim_tx); + + return gprs_llc_prim_call_up_cb(llc_prim_tx); +} + /******************************** * Handling from upper layers: ********************************/ diff --git a/src/llc/llc_llgmm.c b/src/llc/llc_llgmm.c index d85a30e..f33d6de 100644 --- a/src/llc/llc_llgmm.c +++ b/src/llc/llc_llgmm.c @@ -207,6 +207,9 @@ static int llc_prim_handle_llgmm_assign_req(struct osmo_gprs_llc_prim *llc_prim) llme->old_tlli = old_tlli; llme->tlli = new_tlli; llme->state = OSMO_GPRS_LLC_LLMS_ASSIGNED; + /* Inform SNDCP about the TLLI change so it can update it too: */ + if (old_tlli != new_tlli) + gprs_llc_llme_submit_prim_ll_assign_ind(old_tlli, new_tlli); } else if (old_tlli != TLLI_UNASSIGNED && new_tlli == TLLI_UNASSIGNED) { /* TLLI Unassignment 8.3.3) */ llme->tlli = llme->old_tlli = 0; diff --git a/tests/llc/llc_prim_test.c b/tests/llc/llc_prim_test.c index bcba783..b9e2e0e 100644 --- a/tests/llc/llc_prim_test.c +++ b/tests/llc/llc_prim_test.c @@ -48,9 +48,17 @@ int test_llc_prim_up_cb(struct osmo_gprs_llc_prim *llc_prim, void *user_data) printf("%s(): Rx %s TLLI=0x%08x\n", __func__, pdu_name, llc_prim->llgmm.tlli); break; case OSMO_GPRS_LLC_SAP_LL: - printf("%s(): Rx %s TLLI=0x%08x SAPI=%s l3=[%s]\n", __func__, pdu_name, - llc_prim->ll.tlli, osmo_gprs_llc_sapi_name(llc_prim->ll.sapi), - osmo_hexdump(llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len)); + switch (OSMO_PRIM_HDR(&llc_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_LLC_LL_ASSIGN, PRIM_OP_INDICATION): + printf("%s(): Rx %s TLLI=0x%08x NEW_TLLI=x%08x\n", __func__, pdu_name, + llc_prim->ll.tlli, llc_prim->ll.assign_ind.tlli_new); + break; + default: + printf("%s(): Rx %s TLLI=0x%08x SAPI=%s l3=[%s]\n", __func__, pdu_name, + llc_prim->ll.tlli, osmo_gprs_llc_sapi_name(llc_prim->ll.sapi), + osmo_hexdump(llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len)); + break; + } break; default: printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);