diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index d671a44cc..a90db0cdc 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -83,10 +83,10 @@ public: uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, - char* err_str) = 0; + char* err_str) = 0; virtual int apply_traffic_flow_template(const uint8_t& eps_bearer_id, const uint8_t& lcid, - const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) = 0; + const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) = 0; typedef enum { TEST_LOOP_INACTIVE = 0, @@ -259,7 +259,7 @@ public: virtual void reestablish() = 0; virtual void reestablish(uint32_t lcid) = 0; virtual void reset() = 0; - virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0; + virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, int sn = -1) = 0; virtual void add_bearer(uint32_t lcid, srslte::pdcp_config_t cnfg) = 0; virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0; virtual void config_security(uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0; diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index 9d4422c32..4f075f747 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -36,7 +36,7 @@ public: void reestablish() override; void reestablish(uint32_t lcid) override; void reset() override; - void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu) override; + void write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn = -1) override; void write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu); void add_bearer(uint32_t lcid, pdcp_config_t cnfg) override; void add_bearer_mrb(uint32_t lcid, pdcp_config_t cnfg); diff --git a/lib/include/srslte/upper/pdcp_entity_base.h b/lib/include/srslte/upper/pdcp_entity_base.h index b4b18868e..6bd8954b2 100644 --- a/lib/include/srslte/upper/pdcp_entity_base.h +++ b/lib/include/srslte/upper/pdcp_entity_base.h @@ -107,7 +107,7 @@ public: void config_security(as_security_config_t sec_cfg_); // GW/SDAP/RRC interface - virtual void write_sdu(unique_byte_buffer_t sdu) = 0; + virtual void write_sdu(unique_byte_buffer_t sdu, int sn = -1) = 0; // RLC interface virtual void write_pdu(unique_byte_buffer_t pdu) = 0; diff --git a/lib/include/srslte/upper/pdcp_entity_lte.h b/lib/include/srslte/upper/pdcp_entity_lte.h index a1259426c..660a7554c 100644 --- a/lib/include/srslte/upper/pdcp_entity_lte.h +++ b/lib/include/srslte/upper/pdcp_entity_lte.h @@ -49,7 +49,7 @@ public: void reestablish() override; // GW/RRC interface - void write_sdu(unique_byte_buffer_t sdu) override; + void write_sdu(unique_byte_buffer_t sdu, int sn = -1) override; // RLC interface void write_pdu(unique_byte_buffer_t pdu) override; diff --git a/lib/include/srslte/upper/pdcp_entity_nr.h b/lib/include/srslte/upper/pdcp_entity_nr.h index f973243bd..66e3ddb75 100644 --- a/lib/include/srslte/upper/pdcp_entity_nr.h +++ b/lib/include/srslte/upper/pdcp_entity_nr.h @@ -45,7 +45,7 @@ public: void reestablish() final; // RRC interface - void write_sdu(unique_byte_buffer_t sdu) final; + void write_sdu(unique_byte_buffer_t sdu, int sn = -1) final; // RLC interface void write_pdu(unique_byte_buffer_t pdu) final; diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 3a89f64b8..691f5e8bf 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -76,10 +76,10 @@ bool pdcp::is_lcid_enabled(uint32_t lcid) return valid_lcids_cached.count(lcid) > 0; } -void pdcp::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu) +void pdcp::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, int sn) { if (valid_lcid(lcid)) { - pdcp_array.at(lcid)->write_sdu(std::move(sdu)); + pdcp_array.at(lcid)->write_sdu(std::move(sdu), sn); } else { logger.warning("Writing sdu: lcid=%d. Deallocating sdu", lcid); } diff --git a/lib/src/upper/pdcp_entity_lte.cc b/lib/src/upper/pdcp_entity_lte.cc index aeb28adce..3ce93ebae 100644 --- a/lib/src/upper/pdcp_entity_lte.cc +++ b/lib/src/upper/pdcp_entity_lte.cc @@ -93,7 +93,7 @@ void pdcp_entity_lte::reset() } // GW/RRC interface -void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu) +void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, int upper_sn) { if (rlc->sdu_queue_is_full(lcid)) { logger.info(sdu->msg, sdu->N_bytes, "Dropping %s SDU due to full queue", rrc->get_rb_name(lcid).c_str()); @@ -101,7 +101,14 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu) } // Get COUNT to be used with this packet - uint32_t tx_count = COUNT(st.tx_hfn, st.next_pdcp_tx_sn); + uint32_t used_sn; + if (upper_sn == -1) { + used_sn = st.next_pdcp_tx_sn; // Normal scenario + } else { + used_sn = upper_sn; // SN provided by the upper layers, due to handover. + } + + uint32_t tx_count = COUNT(st.tx_hfn, used_sn); // Normal scenario // If the bearer is mapped to RLC AM, save TX_COUNT and a copy of the PDU. // This will be used for reestablishment, where unack'ed PDUs will be re-transmitted. @@ -109,7 +116,7 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu) // a succesfull transmission or when the discard timer expires. // Status report will also use this queue, to know the First Missing SDU (FMS). if (!rlc->rb_is_um(lcid)) { - store_sdu(st.next_pdcp_tx_sn, sdu); + store_sdu(used_sn, sdu); } // check for pending security config in transmit direction @@ -124,11 +131,11 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu) // Start discard timer if (cfg.discard_timer != pdcp_discard_timer_t::infinity) { timer_handler::unique_timer discard_timer = task_sched.get_unique_timer(); - discard_callback discard_fnc(this, st.next_pdcp_tx_sn); + discard_callback discard_fnc(this, used_sn); discard_timer.set(static_cast(cfg.discard_timer), discard_fnc); discard_timer.run(); discard_timers_map.insert(std::make_pair(tx_count, std::move(discard_timer))); - logger.debug("Discard Timer set for SN %u. Timeout: %ums", tx_count, static_cast(cfg.discard_timer)); + logger.debug("Discard Timer set for SN %u. Timeout: %ums", used_sn, static_cast(cfg.discard_timer)); } // Append MAC (SRBs only) @@ -151,18 +158,20 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu) sdu->N_bytes, "TX %s PDU, SN=%d, integrity=%s, encryption=%s", rrc->get_rb_name(lcid).c_str(), - st.next_pdcp_tx_sn, + used_sn, srslte_direction_text[integrity_direction], srslte_direction_text[encryption_direction]); // Set SDU metadata for RLC AM - sdu->md.pdcp_sn = st.next_pdcp_tx_sn; + sdu->md.pdcp_sn = used_sn; - // Increment NEXT_PDCP_TX_SN and TX_HFN - st.next_pdcp_tx_sn++; - if (st.next_pdcp_tx_sn > maximum_pdcp_sn) { - st.tx_hfn++; - st.next_pdcp_tx_sn = 0; + // Increment NEXT_PDCP_TX_SN and TX_HFN (only update variables if SN was not provided by upper layers) + if (upper_sn == -1) { + st.next_pdcp_tx_sn++; + if (st.next_pdcp_tx_sn > maximum_pdcp_sn) { + st.tx_hfn++; + st.next_pdcp_tx_sn = 0; + } } // Pass PDU to lower layers diff --git a/lib/src/upper/pdcp_entity_nr.cc b/lib/src/upper/pdcp_entity_nr.cc index 5140014ae..b646ff829 100644 --- a/lib/src/upper/pdcp_entity_nr.cc +++ b/lib/src/upper/pdcp_entity_nr.cc @@ -62,7 +62,7 @@ void pdcp_entity_nr::reset() } // SDAP/RRC interface -void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu) +void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu, int sn) { // Log SDU logger.info(sdu->msg, diff --git a/srsenb/src/stack/upper/pdcp.cc b/srsenb/src/stack/upper/pdcp.cc index a0132390d..b633af5fa 100644 --- a/srsenb/src/stack/upper/pdcp.cc +++ b/srsenb/src/stack/upper/pdcp.cc @@ -151,7 +151,7 @@ void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t if (users.count(rnti)) { if (rnti != SRSLTE_MRNTI) { // TODO: Handle PDCP SN coming from GTPU - users[rnti].pdcp->write_sdu(lcid, std::move(sdu)); + users[rnti].pdcp->write_sdu(lcid, std::move(sdu), pdcp_sn); } else { users[rnti].pdcp->write_sdu_mch(lcid, std::move(sdu)); } diff --git a/srsue/test/upper/rrc_meas_test.cc b/srsue/test/upper/rrc_meas_test.cc index 912492e4a..74be7e981 100644 --- a/srsue/test/upper/rrc_meas_test.cc +++ b/srsue/test/upper/rrc_meas_test.cc @@ -194,7 +194,7 @@ class pdcp_test : public srslte::pdcp { public: pdcp_test(const char* logname, srslte::task_sched_handle t) : srslte::pdcp(t, logname) {} - void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) override + void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, int sn = -1) override { ul_dcch_msg_s ul_dcch_msg; asn1::cbit_ref bref(sdu->msg, sdu->N_bytes);