Skip to content

Commit 7ddf786

Browse files
f1u,du: avoid redundant DSSS on expired ul_notif_timer
1 parent 5d90166 commit 7ddf786

File tree

3 files changed

+114
-36
lines changed

3 files changed

+114
-36
lines changed

lib/f1u/du/f1u_bearer_impl.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void f1u_bearer_impl::handle_sdu(byte_buffer_chain sdu)
5959
// attach the SDU
6060
msg.t_pdu = std::move(sdu);
6161

62-
// attach data delivery status (if anything has changed)
62+
// piggy-back latest data delivery status (ignore if anything has changed)
6363
fill_data_delivery_status(msg);
6464

6565
if (buffering) {
@@ -107,7 +107,7 @@ void f1u_bearer_impl::handle_pdu_impl(nru_dl_message msg)
107107
}
108108
// handle polling of delivery status report
109109
if (msg.dl_user_data.report_polling) {
110-
if (send_data_delivery_status()) {
110+
if (send_data_delivery_status(/* force = */ true)) {
111111
logger.log_debug("Report polling flag is set. Sent data delivery status");
112112
} else {
113113
logger.log_warning("Report polling flag is set. No data to be sent in data delivery status");
@@ -192,9 +192,13 @@ bool f1u_bearer_impl::fill_highest_transmitted_pdcp_sn(nru_dl_data_delivery_stat
192192
// In case the DL DATA DELIVERY STATUS frame is sent before any NR PDCP PDU is transferred to lower layers, the
193193
// information on the highest NR PDCP PDU sequence number successfully delivered in sequence to the UE and the
194194
// highest NR PDCP PDU sequence number transmitted to the lower layers may not be provided.
195-
if (cur_highest_transmitted_pdcp_sn != unset_pdcp_sn) {
196-
logger.log_debug("Adding highest transmitted pdcp_sn={}", cur_highest_transmitted_pdcp_sn);
197-
status.highest_transmitted_pdcp_sn = cur_highest_transmitted_pdcp_sn;
195+
if (cur_highest_transmitted_pdcp_sn == unset_pdcp_sn) {
196+
return false;
197+
}
198+
logger.log_debug("Adding highest transmitted pdcp_sn={}", cur_highest_transmitted_pdcp_sn);
199+
status.highest_transmitted_pdcp_sn = cur_highest_transmitted_pdcp_sn;
200+
if (cur_highest_transmitted_pdcp_sn != notif_highest_transmitted_pdcp_sn) {
201+
notif_highest_transmitted_pdcp_sn = cur_highest_transmitted_pdcp_sn;
198202
return true;
199203
}
200204
return false;
@@ -214,9 +218,13 @@ bool f1u_bearer_impl::fill_highest_delivered_pdcp_sn(nru_dl_data_delivery_status
214218
// In case the DL DATA DELIVERY STATUS frame is sent before any NR PDCP PDU is transferred to lower layers, the
215219
// information on the highest NR PDCP PDU sequence number successfully delivered in sequence to the UE and the
216220
// highest NR PDCP PDU sequence number transmitted to the lower layers may not be provided.
217-
if (cur_highest_delivered_pdcp_sn != unset_pdcp_sn) {
218-
logger.log_debug("Adding highest delivered pdcp_sn={}", cur_highest_delivered_pdcp_sn);
219-
status.highest_delivered_pdcp_sn = cur_highest_delivered_pdcp_sn;
221+
if (cur_highest_delivered_pdcp_sn == unset_pdcp_sn) {
222+
return false;
223+
}
224+
logger.log_debug("Adding highest delivered pdcp_sn={}", cur_highest_delivered_pdcp_sn);
225+
status.highest_delivered_pdcp_sn = cur_highest_delivered_pdcp_sn;
226+
if (cur_highest_delivered_pdcp_sn != notif_highest_delivered_pdcp_sn) {
227+
notif_highest_delivered_pdcp_sn = cur_highest_delivered_pdcp_sn;
220228
return true;
221229
}
222230
return false;
@@ -249,31 +257,31 @@ bool f1u_bearer_impl::fill_highest_delivered_retransmitted_pdcp_sn(nru_dl_data_d
249257
return false;
250258
}
251259

252-
void f1u_bearer_impl::fill_data_delivery_status(nru_ul_message& msg)
260+
bool f1u_bearer_impl::fill_data_delivery_status(nru_ul_message& msg)
253261
{
254-
nru_dl_data_delivery_status status = {};
255-
bool value_added = false;
262+
nru_dl_data_delivery_status status = {};
263+
bool fresh_values = false;
256264

257-
value_added |= fill_desired_buffer_size_of_data_radio_bearer(status);
258-
value_added |= fill_highest_transmitted_pdcp_sn(status);
259-
value_added |= fill_highest_delivered_pdcp_sn(status);
260-
value_added |= fill_highest_retransmitted_pdcp_sn(status);
261-
value_added |= fill_highest_delivered_retransmitted_pdcp_sn(status);
265+
fresh_values |= fill_desired_buffer_size_of_data_radio_bearer(status);
266+
fresh_values |= fill_highest_transmitted_pdcp_sn(status);
267+
fresh_values |= fill_highest_delivered_pdcp_sn(status);
268+
fresh_values |= fill_highest_retransmitted_pdcp_sn(status);
269+
fresh_values |= fill_highest_delivered_retransmitted_pdcp_sn(status);
262270

263-
if (value_added) {
264-
logger.log_debug("Adding data delivery status to NR-U message");
265-
msg.data_delivery_status = std::move(status);
266-
}
271+
logger.log_debug("Adding data delivery status to NR-U message");
272+
msg.data_delivery_status = std::move(status);
267273

268274
// restart UL notification timer
269275
ul_notif_timer.run();
276+
277+
return fresh_values;
270278
}
271279

272-
bool f1u_bearer_impl::send_data_delivery_status()
280+
bool f1u_bearer_impl::send_data_delivery_status(bool force)
273281
{
274-
nru_ul_message msg = {};
275-
fill_data_delivery_status(msg);
276-
if (!msg.data_delivery_status.has_value()) {
282+
nru_ul_message msg = {};
283+
bool fresh_values = fill_data_delivery_status(msg);
284+
if (!fresh_values && !force) {
277285
return false;
278286
}
279287
tx_pdu_notifier.on_new_pdu(std::move(msg));
@@ -282,9 +290,9 @@ bool f1u_bearer_impl::send_data_delivery_status()
282290

283291
void f1u_bearer_impl::on_expired_ul_notif_timer()
284292
{
285-
if (send_data_delivery_status()) {
293+
if (send_data_delivery_status(/* force = */ false)) {
286294
logger.log_debug("UL notification timer expired. Sent data delivery status");
287295
} else {
288-
logger.log_debug("UL notification timer expired. No data to be sent in data delivery status");
296+
logger.log_debug("UL notification timer expired. No fresh data to be sent in data delivery status");
289297
}
290298
}

lib/f1u/du/f1u_bearer_impl.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,49 @@ class f1u_bearer_impl final : public f1u_bearer,
9797
/// Holds the latest information of the available space in the RLC SDU queue that was reported to the upper layers
9898
/// (i.e. torward CU-UP)
9999
uint32_t notif_desired_buffer_size_for_data_radio_bearer;
100+
/// Holds the last highest transmitted PDCP SN that was reported to upper layers (i.e. towards CU-UP)
101+
uint32_t notif_highest_transmitted_pdcp_sn = unset_pdcp_sn;
102+
/// Holds the last highest delivered PDCP SN that was reported to upper layers (i.e. towards CU-UP)
103+
uint32_t notif_highest_delivered_pdcp_sn = unset_pdcp_sn;
100104
/// Holds the last highest retransmitted PDCP SN that was reported to upper layers (i.e. towards CU-UP)
101105
uint32_t notif_highest_retransmitted_pdcp_sn = unset_pdcp_sn;
102106
/// Holds the last highest delivered retransmitted PDCP SN that was reported to upper layers (i.e. towards CU-UP)
103107
uint32_t notif_highest_delivered_retransmitted_pdcp_sn = unset_pdcp_sn;
104108

109+
/// \brief Write desired buffer size of DRB into DSSS.
110+
/// \param status The DSSS to write the desired value into.
111+
/// \return False if the same value was written as last time this function was called; True on fresh value.
105112
bool fill_desired_buffer_size_of_data_radio_bearer(nru_dl_data_delivery_status& status);
113+
114+
/// \brief Write highest transmitted PDCP SN into DSSS.
115+
/// \param status The DSSS to write the desired value into.
116+
/// \return False if the same value was written as last time this function was called; True on fresh value.
106117
bool fill_highest_transmitted_pdcp_sn(nru_dl_data_delivery_status& status);
118+
119+
/// \brief Write highest delivered PDCP SN into DSSS.
120+
/// \param status The DSSS to write the desired value into.
121+
/// \return False if the same value was written as last time this function was called; True on fresh value.
107122
bool fill_highest_delivered_pdcp_sn(nru_dl_data_delivery_status& status);
123+
124+
/// \brief Write highest retransmitted PDCP SN into DSSS.
125+
/// \param status The DSSS to write the desired value into.
126+
/// \return False if the same value was written as last time this function was called; True on fresh value.
108127
bool fill_highest_retransmitted_pdcp_sn(nru_dl_data_delivery_status& status);
128+
129+
/// \brief Write highest delivered retransmitted PDCP SN into DSSS.
130+
/// \param status The DSSS to write the desired value into.
131+
/// \return False if the same value was written as last time this function was called; True on fresh value.
109132
bool fill_highest_delivered_retransmitted_pdcp_sn(nru_dl_data_delivery_status& status);
110-
void fill_data_delivery_status(nru_ul_message& msg);
111-
bool send_data_delivery_status();
133+
134+
/// \brief Write DSSS into NR-U UL message.
135+
/// \param msg NR-U UL message in which the DSSS shall be filled.
136+
/// \return False if DSSS holds the same values as last time this function was called; True on fresh value(s).
137+
bool fill_data_delivery_status(nru_ul_message& msg);
138+
139+
/// \brief Send a DSSS via dedicated NR-U UL message (no piggy-back) either if forced or contains fresh values.
140+
/// \param force Force sending DSSS even if no fresh values are included (i.e. nothing changed since last call).
141+
/// \return True if DSSS was sent, False otherwise.
142+
bool send_data_delivery_status(bool force);
112143

113144
void handle_pdu_impl(nru_dl_message msg);
114145

tests/unittests/f1u/du/f1u_du_bearer_test.cpp

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ class f1u_du_test_base : public f1u_trx_test
104104
std::unique_ptr<f1u_bearer_impl> f1u;
105105

106106
gtpu_teid_t dl_teid_next{1234};
107-
const uint32_t f1u_ul_notif_time_ms = 10;
107+
const uint32_t f1u_ul_notif_time_ms = 10;
108+
const uint32_t f1u_intial_rlc_queue_bytes_limit = 8000;
108109
};
109110

110111
/// Fixture class for F1-U DU tests
@@ -116,9 +117,10 @@ class f1u_du_test : public ::testing::Test, public f1u_du_test_base
116117
// init test's logger
117118
init_logger();
118119
// create tester and testee
119-
f1u_config config = {};
120-
config.t_notify = f1u_ul_notif_time_ms;
121-
config.warn_on_drop = true;
120+
f1u_config config = {};
121+
config.t_notify = f1u_ul_notif_time_ms;
122+
config.rlc_queue_bytes_limit = f1u_intial_rlc_queue_bytes_limit;
123+
config.warn_on_drop = true;
122124
init_f1u(config);
123125
}
124126

@@ -277,14 +279,38 @@ TEST_F(f1u_du_test, tx_pdcp_pdus)
277279

278280
ASSERT_FALSE(tester->tx_msg_list.empty());
279281
EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu1);
280-
EXPECT_FALSE(tester->tx_msg_list.front().data_delivery_status.has_value());
282+
ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value());
283+
{
284+
nru_dl_data_delivery_status& status = tester->tx_msg_list.front().data_delivery_status.value();
285+
EXPECT_FALSE(status.final_frame_ind);
286+
EXPECT_EQ(status.desired_buffer_size_for_drb, f1u_intial_rlc_queue_bytes_limit);
287+
EXPECT_FALSE(status.desired_data_rate);
288+
EXPECT_FALSE(status.lost_nru_sn_ranges.has_value());
289+
EXPECT_FALSE(status.highest_delivered_pdcp_sn.has_value());
290+
EXPECT_FALSE(status.highest_transmitted_pdcp_sn.has_value());
291+
EXPECT_FALSE(status.cause_value.has_value());
292+
EXPECT_FALSE(status.highest_delivered_retransmitted_pdcp_sn.has_value());
293+
EXPECT_FALSE(status.highest_retransmitted_pdcp_sn.has_value());
294+
}
281295
EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value());
282296

283297
tester->tx_msg_list.pop_front();
284298

285299
ASSERT_FALSE(tester->tx_msg_list.empty());
286300
EXPECT_EQ(tester->tx_msg_list.front().t_pdu.value(), tx_pdcp_pdu2);
287-
EXPECT_FALSE(tester->tx_msg_list.front().data_delivery_status.has_value());
301+
ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value());
302+
{
303+
nru_dl_data_delivery_status& status = tester->tx_msg_list.front().data_delivery_status.value();
304+
EXPECT_FALSE(status.final_frame_ind);
305+
EXPECT_EQ(status.desired_buffer_size_for_drb, f1u_intial_rlc_queue_bytes_limit);
306+
EXPECT_FALSE(status.desired_data_rate);
307+
EXPECT_FALSE(status.lost_nru_sn_ranges.has_value());
308+
EXPECT_FALSE(status.highest_delivered_pdcp_sn.has_value());
309+
EXPECT_FALSE(status.highest_transmitted_pdcp_sn.has_value());
310+
EXPECT_FALSE(status.cause_value.has_value());
311+
EXPECT_FALSE(status.highest_delivered_retransmitted_pdcp_sn.has_value());
312+
EXPECT_FALSE(status.highest_retransmitted_pdcp_sn.has_value());
313+
}
288314
EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value());
289315

290316
tester->tx_msg_list.pop_front();
@@ -635,8 +661,21 @@ TEST_F(f1u_du_test, rx_with_poll_triggers_no_ddds_when_nothing_was_notified)
635661
msg1.dl_user_data.report_polling = true;
636662
f1u->handle_pdu(std::move(msg1));
637663

638-
// This should not trigger a DDDS, because no data is available yet
639-
EXPECT_TRUE(tester->tx_msg_list.empty());
664+
// This triggers a DDDS that only includes the initial "desired_buffer_size_for_drb", no other data is available yet
665+
ASSERT_TRUE(tester->tx_msg_list.front().data_delivery_status.has_value());
666+
{
667+
nru_dl_data_delivery_status& status = tester->tx_msg_list.front().data_delivery_status.value();
668+
EXPECT_FALSE(status.final_frame_ind);
669+
EXPECT_EQ(status.desired_buffer_size_for_drb, f1u_intial_rlc_queue_bytes_limit);
670+
EXPECT_FALSE(status.desired_data_rate);
671+
EXPECT_FALSE(status.lost_nru_sn_ranges.has_value());
672+
EXPECT_FALSE(status.highest_delivered_pdcp_sn.has_value());
673+
EXPECT_FALSE(status.highest_transmitted_pdcp_sn.has_value());
674+
EXPECT_FALSE(status.cause_value.has_value());
675+
EXPECT_FALSE(status.highest_delivered_retransmitted_pdcp_sn.has_value());
676+
EXPECT_FALSE(status.highest_retransmitted_pdcp_sn.has_value());
677+
}
678+
EXPECT_FALSE(tester->tx_msg_list.front().assistance_information.has_value());
640679

641680
// Also check that the DL PDU was properly forwarded
642681
ASSERT_FALSE(tester->rx_sdu_list.empty());

0 commit comments

Comments
 (0)