diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 9dda9b9ace..0bbd294c53 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -88,7 +88,6 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, entity->stats.rxpdu_dd_pkts++; entity->stats.rxpdu_dd_bytes += size; - return; } @@ -120,7 +119,7 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, entity->stats.rxpdu_dd_pkts++; entity->stats.rxpdu_dd_bytes += size; - + return; } } @@ -130,7 +129,6 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, entity->stats.rxpdu_dd_pkts++; entity->stats.rxpdu_dd_bytes += size; - return; } @@ -158,7 +156,6 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, entity->stats.txsdu_pkts++; entity->stats.txsdu_bytes += cur->size; - nr_pdcp_free_sdu(cur); count++; } @@ -224,7 +221,7 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, memcpy(buf + header_size, buffer, size); - if (entity->has_integrity){ + if (entity->has_integrity) { uint8_t integrity[4] = {0}; entity->integrity(entity->integrity_context, integrity, @@ -232,13 +229,12 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, entity->rb_id, count, entity->is_gnb ? 1 : 0); memcpy((unsigned char *)buf + header_size + size, integrity, 4); + } else if (integrity_size == 4) { + // set MAC-I to 0 for SRBs with integrity not active + memset(buf + header_size + size, 0, 4); } - // set MAC-I to 0 for SRBs with integrity not active - else if (integrity_size == 4) - memset(buf + header_size + size, 0, 4); - - if (entity->has_ciphering && (entity->is_gnb || entity->security_mode_completed)){ + if (entity->has_ciphering && (entity->is_gnb || entity->security_mode_completed)) { entity->cipher(entity->security_context, (unsigned char *)buf + header_size, size + integrity_size, entity->rb_id, count, entity->is_gnb ? 1 : 0); @@ -339,6 +335,8 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) cur->buffer, cur->size); entity->rx_list = cur->next; entity->rx_size -= cur->size; + entity->stats.txsdu_pkts++; + entity->stats.txsdu_bytes += cur->size; nr_pdcp_free_sdu(cur); } @@ -350,6 +348,8 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) cur->buffer, cur->size); entity->rx_list = cur->next; entity->rx_size -= cur->size; + entity->stats.txsdu_pkts++; + entity->stats.txsdu_bytes += cur->size; nr_pdcp_free_sdu(cur); count++; } @@ -362,7 +362,7 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) } } -void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now) +static void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now) { entity->t_current = now; @@ -384,7 +384,7 @@ static void deliver_all_sdus(nr_pdcp_entity_t *entity) } } -void nr_pdcp_entity_suspend(nr_pdcp_entity_t *entity) +static void nr_pdcp_entity_suspend(nr_pdcp_entity_t *entity) { entity->tx_next = 0; if (entity->t_reordering_start != 0) { @@ -395,19 +395,71 @@ void nr_pdcp_entity_suspend(nr_pdcp_entity_t *entity) entity->rx_deliv = 0; } -void nr_pdcp_entity_release(nr_pdcp_entity_t *entity) -{ - deliver_all_sdus(entity); -} - -void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity) +static void free_rx_list(nr_pdcp_entity_t *entity) { nr_pdcp_sdu_t *cur = entity->rx_list; while (cur != NULL) { nr_pdcp_sdu_t *next = cur->next; + entity->stats.rxpdu_dd_pkts++; + entity->stats.rxpdu_dd_bytes += cur->size; nr_pdcp_free_sdu(cur); cur = next; } + entity->rx_list = NULL; + entity->rx_size = 0; +} + +static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity) +{ + /* transmitting entity procedures */ + /* todo: deal with ciphering/integrity algos and keys */ + + /* receiving entity procedures */ + /* todo: deal with ciphering/integrity algos and keys */ +} + +static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity) +{ + /* transmitting entity procedures */ + entity->tx_next = 0; + /* todo: deal with ciphering/integrity algos and keys */ + + /* receiving entity procedures */ + /* deliver all SDUs if t_reordering is running */ + if (entity->t_reordering_start != 0) + deliver_all_sdus(entity); + /* stop t_reordering */ + entity->t_reordering_start = 0; + /* set rx_next and rx_deliv to the initial value */ + entity->rx_next = 0; + entity->rx_deliv = 0; + /* todo: deal with ciphering/integrity algos and keys */ +} + +static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity) +{ + /* transmitting entity procedures */ + entity->tx_next = 0; + /* todo: deal with ciphering/integrity algos and keys */ + + /* receiving entity procedures */ + free_rx_list(entity); + /* stop t_reordering */ + entity->t_reordering_start = 0; + /* set rx_next and rx_deliv to the initial value */ + entity->rx_next = 0; + entity->rx_deliv = 0; + /* todo: deal with ciphering/integrity algos and keys */ +} + +static void nr_pdcp_entity_release(nr_pdcp_entity_t *entity) +{ + deliver_all_sdus(entity); +} + +static void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity) +{ + free_rx_list(entity); if (entity->free_security != NULL) entity->free_security(entity->security_context); if (entity->free_integrity != NULL) @@ -461,6 +513,18 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( ret->delete_entity = nr_pdcp_entity_delete; ret->release_entity = nr_pdcp_entity_release; ret->suspend_entity = nr_pdcp_entity_suspend; + + switch (type) { + case NR_PDCP_DRB_AM: + ret->reestablish_entity = nr_pdcp_entity_reestablish_drb_am; + break; + case NR_PDCP_DRB_UM: + ret->reestablish_entity = nr_pdcp_entity_reestablish_drb_um; + break; + case NR_PDCP_SRB: + ret->reestablish_entity = nr_pdcp_entity_reestablish_srb; + break; + } ret->get_stats = nr_pdcp_entity_get_stats; ret->deliver_sdu = deliver_sdu; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 078c32b6c0..1657f3c4bb 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -78,6 +78,7 @@ typedef struct nr_pdcp_entity_t { void (*delete_entity)(struct nr_pdcp_entity_t *entity); void (*release_entity)(struct nr_pdcp_entity_t *entity); void (*suspend_entity)(struct nr_pdcp_entity_t *entity); + void (*reestablish_entity)(struct nr_pdcp_entity_t *entity); void (*get_stats)(struct nr_pdcp_entity_t *entity, nr_pdcp_statistics_t *out); /* set_security: pass -1 to integrity_algorithm / ciphering_algorithm @@ -123,7 +124,7 @@ typedef struct nr_pdcp_entity_t { uint64_t t_current; /* timers (stores the ms of activation, 0 means not active) */ - int t_reordering_start; + uint64_t t_reordering_start; /* security */ int has_ciphering; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index eb1367c724..db57aa63f0 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -64,6 +64,25 @@ uint8_t proto_agent_flag = 0; static ngran_node_t node_type; +nr_pdcp_entity_t *nr_pdcp_get_rb(nr_pdcp_ue_t *ue, int rb_id, bool srb_flag) +{ + nr_pdcp_entity_t *rb; + + if (srb_flag) { + if (rb_id < 1 || rb_id > 2) + rb = NULL; + else + rb = ue->srb[rb_id - 1]; + } else { + if (rb_id < 1 || rb_id > MAX_DRBS_PER_UE) + rb = NULL; + else + rb = ue->drb[rb_id - 1]; + } + + return rb; +} + /****************************************************************************/ /* rlc_data_req queue - begin */ /****************************************************************************/ @@ -263,24 +282,12 @@ static void do_pdcp_data_ind( nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rntiMaybeUEid); - - if (srb_flagP == 1) { - if (rb_id < 1 || rb_id > 2) - rb = NULL; - else - rb = ue->srb[rb_id - 1]; - } else { - if (rb_id < 1 || rb_id > MAX_DRBS_PER_UE) - rb = NULL; - else - rb = ue->drb[rb_id - 1]; - } + rb = nr_pdcp_get_rb(ue, rb_id, srb_flagP); if (rb != NULL) { rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size); } else { - LOG_E(PDCP, "%s:%d:%s: no RB found (rb_id %ld, srb_flag %d)\n", - __FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP); + LOG_E(PDCP, "pdcp_data_ind: no RB found (rb_id %ld, srb_flag %d)\n", rb_id, srb_flagP); } nr_pdcp_manager_unlock(nr_pdcp_ue_manager); @@ -776,14 +783,8 @@ void add_srb(int is_gnb, nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rntiMaybeUEid); - if (ue->srb[srb_id-1] != NULL) { - LOG_E(PDCP, - "%s:%d:%s: warning SRB %d already exist for UE ID/RNTI %ld, do nothing\n", - __FILE__, - __LINE__, - __FUNCTION__, - srb_id, - rntiMaybeUEid); + if (nr_pdcp_get_rb(ue, srb_id, true) != NULL) { + LOG_E(PDCP, "warning SRB %d already exist for UE ID/RNTI %ld, do nothing\n", srb_id, rntiMaybeUEid); } else { pdcp_srb = new_nr_pdcp_entity(NR_PDCP_SRB, is_gnb, srb_id, 0, false, false, // sdap parameters @@ -878,8 +879,8 @@ void add_drb(int is_gnb, nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rntiMaybeUEid); - if (ue->drb[drb_id-1] != NULL) { - LOG_W(PDCP, "%s:%d:%s: warning DRB %d already exist for UE ID/RNTI %ld, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rntiMaybeUEid); + if (nr_pdcp_get_rb(ue, drb_id, false) != NULL) { + LOG_W(PDCP, "warning DRB %d already exist for UE ID/RNTI %ld, do nothing\n", drb_id, rntiMaybeUEid); } else { pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id, pdusession_id, has_sdap_rx, has_sdap_tx, deliver_sdu_drb, ue, @@ -997,25 +998,20 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, /* TODO: proper handling of DRBs, for the moment only SRBs are handled */ - if (rb_id >= 1 && rb_id <= 2) { - rb = ue->srb[rb_id - 1]; + rb = nr_pdcp_get_rb(ue, rb_id, true); - if (rb == NULL) { - LOG_E(PDCP, "%s:%d:%s: no SRB found (ue_id %ld, rb_id %ld)\n", __FILE__, __LINE__, __FUNCTION__, ue_id, rb_id); - nr_pdcp_manager_unlock(nr_pdcp_ue_manager); - return; - } - - integrity_algorithm = (security_modeP>>4) & 0xf; - ciphering_algorithm = security_modeP & 0x0f; - rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP, - ciphering_algorithm, (char *)kRRCenc_pP); - rb->security_mode_completed = false; - } else { - LOG_E(PDCP, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); - exit(1); + if (rb == NULL) { + LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %ld)\n", ue_id, rb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return; } + integrity_algorithm = (security_modeP>>4) & 0xf; + ciphering_algorithm = security_modeP & 0x0f; + rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP, + ciphering_algorithm, (char *)kRRCenc_pP); + rb->security_mode_completed = false; + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } @@ -1034,14 +1030,10 @@ bool nr_pdcp_data_req_srb(ue_id_t ue_id, nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - - if (rb_id < 1 || rb_id > 2) - rb = NULL; - else - rb = ue->srb[rb_id - 1]; + rb = nr_pdcp_get_rb(ue, rb_id, true); if (rb == NULL) { - LOG_E(PDCP, "%s:%d:%s: no SRB found (ue_id %ld, rb_id %ld)\n", __FILE__, __LINE__, __FUNCTION__, ue_id, rb_id); + LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %ld)\n", ue_id, rb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); return 0; } @@ -1062,9 +1054,10 @@ void nr_pdcp_suspend_srb(ue_id_t ue_id, int srb_id) { nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - nr_pdcp_entity_t *srb = ue->srb[srb_id - 1]; + nr_pdcp_entity_t *srb = nr_pdcp_get_rb(ue, srb_id, true); if (srb == NULL) { - LOG_E(PDCP, "Trying to susbend SRB with ID %d but it is not established\n", srb_id); + LOG_E(PDCP, "Trying to suspend SRB with ID %d but it is not established\n", srb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); return; } srb->suspend_entity(srb); @@ -1075,9 +1068,10 @@ void nr_pdcp_suspend_drb(ue_id_t ue_id, int drb_id) { nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - nr_pdcp_entity_t *drb = ue->drb[drb_id - 1]; + nr_pdcp_entity_t *drb = nr_pdcp_get_rb(ue, drb_id, false); if (drb == NULL) { - LOG_E(PDCP, "Trying to susbend DRB with ID %d but it is not established\n", drb_id); + LOG_E(PDCP, "Trying to suspend DRB with ID %d but it is not established\n", drb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); return; } drb->suspend_entity(drb); @@ -1088,7 +1082,12 @@ void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering) { nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - nr_pdcp_entity_t *srb = ue->srb[srb_id - 1]; + nr_pdcp_entity_t *srb = nr_pdcp_get_rb(ue, srb_id, true); + if (srb == NULL) { + LOG_E(PDCP, "Trying to reconfigure SRB with ID %d but it is not established\n", srb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return; + } int decoded_t_reordering = decode_t_reordering(t_Reordering); srb->t_reordering = decoded_t_reordering; nr_pdcp_manager_unlock(nr_pdcp_ue_manager); @@ -1102,7 +1101,12 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering) */ nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - nr_pdcp_entity_t *drb = ue->drb[drb_id - 1]; + nr_pdcp_entity_t *drb = nr_pdcp_get_rb(ue, drb_id, false); + if (drb == NULL) { + LOG_E(PDCP, "Trying to reconfigure DRB with ID %d but it is not established\n", drb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return; + } int decoded_t_reordering = decode_t_reordering(t_Reordering); drb->t_reordering = decoded_t_reordering; nr_pdcp_manager_unlock(nr_pdcp_ue_manager); @@ -1136,36 +1140,21 @@ void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void nr_pdcp_reestablishment(ue_id_t ue_id) +void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag) { - // TODO implement this on a per RB basis following TS 38.323 Sec 5.1.2 + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + nr_pdcp_manager_lock(nr_pdcp_ue_manager); - nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - if (ue == NULL) { - LOG_E(PDCP, "Cannot find PDCP entity for UE %lx\n", ue_id); - nr_pdcp_manager_unlock(nr_pdcp_ue_manager); - return; + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); + rb = nr_pdcp_get_rb(ue, rb_id, srb_flag); + + if (rb != NULL) { + rb->reestablish_entity(rb); + } else { + LOG_W(PDCP, "UE %4.4lx cannot re-establish RB %d (is_srb %d), RB not found\n", ue_id, rb_id, srb_flag); } - for (int i = 0; i < 3; i++) { - nr_pdcp_entity_t *srb = ue->srb[i]; - if (srb != NULL) { - srb->tx_next = 0; - srb->rx_next = 0; - srb->rx_deliv = 0; - srb->rx_reord = 0; - } - } - - for (int i = 0; i < MAX_DRBS_PER_UE; i++) { - nr_pdcp_entity_t *drb = ue->drb[i]; - if (drb != NULL) { - // drb->tx_next = 0; // Should continue from the previous value - drb->rx_next = 0; - //drb->rx_deliv = 0; // should continue from the previous value - drb->rx_reord = 0; - } - } nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } @@ -1200,14 +1189,10 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - - if (rb_id < 1 || rb_id > MAX_DRBS_PER_UE) - rb = NULL; - else - rb = ue->drb[rb_id - 1]; + rb = nr_pdcp_get_rb(ue, rb_id, false); if (rb == NULL) { - LOG_E(PDCP, "%s:%d:%s: no DRB found (ue_id %ld, rb_id %ld)\n", __FILE__, __LINE__, __FUNCTION__, ue_id, rb_id); + LOG_E(PDCP, "no DRB found (ue_id %lx, rb_id %ld)\n", ue_id, rb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); return 0; } @@ -1309,18 +1294,7 @@ bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_stat nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - - if (srb_flag == 1) { - if (rb_id < 1 || rb_id > 2) - rb = NULL; - else - rb = ue->srb[rb_id - 1]; - } else { - if (rb_id < 1 || rb_id > 5) - rb = NULL; - else - rb = ue->drb[rb_id - 1]; - } + rb = nr_pdcp_get_rb(ue, rb_id, srb_flag); if (rb != NULL) { rb->get_stats(rb, out); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 85e2c4b46b..05e18c23c2 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -64,7 +64,7 @@ void add_drb(int is_gnb, void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid); bool nr_pdcp_remove_UE(ue_id_t ue_id); -void nr_pdcp_reestablishment(ue_id_t ue_id); +void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag); void nr_pdcp_suspend_srb(ue_id_t ue_id, int srb_id); void nr_pdcp_suspend_drb(ue_id_t ue_id, int drb_id); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 40972d55c6..dea1494f17 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1046,11 +1046,16 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context for (int srb_id = 1; srb_id < maxSRBs; srb_id++) { if (ue_p->Srb[srb_id].Active) { nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); + // TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag + nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true); } } // TODO: should send E1 UE Bearer Modification with PDCP Reestablishment flag - nr_pdcp_reestablishment(ue_p->rrc_ue_id); + for (int drb_id = 1; drb_id <= MAX_DRBS_PER_UE; drb_id++) { + if (ue_p->established_drbs[drb_id - 1].status != DRB_INACTIVE) + nr_pdcp_reestablishment(ue_p->rrc_ue_id, drb_id, false); + } f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data);