Skip to content

Commit 2c6d370

Browse files
author
Pavel Harbanau
committed
ofh: reset the pool before processing new slot
1 parent afefcb9 commit 2c6d370

File tree

6 files changed

+158
-19
lines changed

6 files changed

+158
-19
lines changed

include/srsran/ofh/ethernet/ethernet_frame_pool.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ class frame_buffer_array
109109

110110
public:
111111
// Constructor receives number of buffers stored/read at a time, reserves storage for all eAxCs.
112-
frame_buffer_array(unsigned nof_buffers, unsigned buffer_size) :
113-
increment_quant(nof_buffers),
114-
storage_nof_buffers(ofh::MAX_NOF_SUPPORTED_EAXC * nof_buffers * NUM_OF_ENTRIES),
112+
frame_buffer_array(unsigned nof_buffers_to_return, unsigned buffer_size, unsigned nof_antennas) :
113+
increment_quant(nof_buffers_to_return),
114+
storage_nof_buffers(nof_buffers_to_return * nof_antennas * NUM_OF_ENTRIES),
115115
buffers_array(storage_nof_buffers, frame_buffer{buffer_size}),
116116
write_position(storage_nof_buffers)
117117
{
@@ -162,6 +162,16 @@ class frame_buffer_array
162162
}
163163
}
164164

165+
// Changed state of all 'used' buffers to 'free'.
166+
void reset_buffers()
167+
{
168+
for (auto& buffer : buffers_array) {
169+
if (buffer.status != frame_buffer::frame_buffer_status::marked_to_send) {
170+
buffer.status = frame_buffer::frame_buffer_status::free;
171+
}
172+
}
173+
}
174+
165175
// Returns a vector of pointers to the buffers ready for sending.
166176
span<const frame_buffer*> find_buffers_ready_for_sending()
167177
{
@@ -209,11 +219,11 @@ class eth_frame_pool
209219
pool_entry(units::bytes mtu, unsigned num_of_frames)
210220
{
211221
// DL C-Plane storage.
212-
buffers.emplace_back(NUM_CP_MESSAGES_TO_RETURN, mtu.value());
222+
buffers.emplace_back(NUM_CP_MESSAGES_TO_RETURN, mtu.value(), ofh::MAX_NOF_SUPPORTED_EAXC);
213223
// UL C-Plane storage.
214-
buffers.emplace_back(NUM_CP_MESSAGES_TO_RETURN, mtu.value());
224+
buffers.emplace_back(NUM_CP_MESSAGES_TO_RETURN, mtu.value(), ofh::MAX_NOF_SUPPORTED_EAXC * 2);
215225
// U-Plane storage.
216-
buffers.emplace_back(num_of_frames, mtu.value());
226+
buffers.emplace_back(num_of_frames, mtu.value(), ofh::MAX_NOF_SUPPORTED_EAXC);
217227
}
218228

219229
/// Returns frame buffers for the given OFH type and given direction.
@@ -261,6 +271,12 @@ class eth_frame_pool
261271
entry_buf.clear_buffers();
262272
}
263273

274+
void reset_buffers(const ofh_pool_message_type& context)
275+
{
276+
frame_buffer_array& entry_buf = get_ofh_type_buffers(context.type, context.direction);
277+
entry_buf.reset_buffers();
278+
}
279+
264280
/// Returns a view over a next stored frame buffer for a given OFH type.
265281
span<const frame_buffer*> read_buffers(const ofh_pool_message_type& context)
266282
{
@@ -378,17 +394,17 @@ class eth_frame_pool
378394
pool_entry& cp_entry = get_pool_entry(slot_point, 0);
379395
// Clear buffers with DL Control-Plane messages.
380396
ofh_pool_message_type msg_type{ofh::message_type::control_plane, ofh::data_direction::downlink};
381-
cp_entry.clear_buffers(msg_type);
397+
cp_entry.reset_buffers(msg_type);
382398
// Clear buffers with UL Control-Plane messages.
383399
msg_type.direction = ofh::data_direction::uplink;
384-
cp_entry.clear_buffers(msg_type);
400+
cp_entry.reset_buffers(msg_type);
385401

386402
// Clear buffers with User-Plane messages.
387403
msg_type.type = ofh::message_type::user_plane;
388404
msg_type.direction = ofh::data_direction::downlink;
389405
for (unsigned symbol = 0; symbol != 14; ++symbol) {
390406
pool_entry& up_entry = get_pool_entry(slot_point, symbol);
391-
up_entry.clear_buffers(msg_type);
407+
up_entry.reset_buffers(msg_type);
392408
}
393409
}
394410

lib/ofh/transmitter/ofh_downlink_handler_broadcast_impl.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,21 @@ downlink_handler_broadcast_impl::downlink_handler_broadcast_impl(
2929
*dependencies.logger,
3030
calculate_nof_symbols_before_ota(config.cp, config.scs, config.dl_processing_time, config.tx_timing_params),
3131
get_nsymb_per_slot(config.cp),
32-
to_numerology_value(config.scs))
32+
to_numerology_value(config.scs)),
33+
frame_pool_ptr(dependencies.frame_pool_ptr),
34+
frame_pool(*frame_pool_ptr)
3335
{
3436
srsran_assert(data_flow_cplane, "Invalid Control-Plane data flow");
3537
srsran_assert(data_flow_uplane, "Invalid User-Plane data flow");
38+
srsran_assert(frame_pool_ptr, "Invalid frame pool");
3639
}
3740

3841
void downlink_handler_broadcast_impl::handle_dl_data(const resource_grid_context& context,
3942
const resource_grid_reader& grid)
4043
{
44+
// Clear any stale buffers associated with the context slot.
45+
frame_pool.clear_slot(context.slot);
46+
4147
if (window_checker.is_late(context.slot)) {
4248
logger.warning(
4349
"Dropped late downlink resource grid in slot '{}' and sector#{}. No OFH data will be transmitted for this slot",

lib/ofh/transmitter/ofh_downlink_handler_broadcast_impl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "ofh_tx_window_checker.h"
1616
#include "srsran/adt/span.h"
1717
#include "srsran/adt/static_vector.h"
18+
#include "srsran/ofh/ethernet/ethernet_frame_pool.h"
1819
#include "srsran/ofh/ofh_constants.h"
1920
#include "srsran/ofh/transmitter/ofh_downlink_handler.h"
2021
#include "srsran/ofh/transmitter/ofh_transmitter_configuration.h"
@@ -47,6 +48,8 @@ struct downlink_handler_broadcast_impl_dependencies {
4748
std::unique_ptr<data_flow_cplane_scheduling_commands> data_flow_cplane;
4849
/// Data flow for User-Plane.
4950
std::unique_ptr<data_flow_uplane_downlink_data> data_flow_uplane;
51+
/// Ethernet frame pool.
52+
std::shared_ptr<ether::eth_frame_pool> frame_pool_ptr;
5053
};
5154

5255
/// \brief Open Fronthaul downlink broadcast handler implementation.
@@ -72,6 +75,8 @@ class downlink_handler_broadcast_impl : public downlink_handler
7275
std::unique_ptr<data_flow_cplane_scheduling_commands> data_flow_cplane;
7376
std::unique_ptr<data_flow_uplane_downlink_data> data_flow_uplane;
7477
tx_window_checker window_checker;
78+
std::shared_ptr<ether::eth_frame_pool> frame_pool_ptr;
79+
ether::eth_frame_pool& frame_pool;
7580
};
7681

7782
} // namespace ofh

lib/ofh/transmitter/ofh_transmitter_factories.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ create_downlink_manager(const transmitter_config& tx_con
121121
dl_dependencies.logger = &logger;
122122
dl_dependencies.data_flow_cplane = std::move(data_flow_cplane);
123123
dl_dependencies.data_flow_uplane = std::move(data_flow_uplane);
124+
dl_dependencies.frame_pool_ptr = frame_pool;
124125

125126
return std::make_unique<downlink_manager_broadcast_impl>(dl_config, std::move(dl_dependencies));
126127
}

tests/integrationtests/ofh/ofh_integration_test.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,11 +1104,9 @@ static ru_ofh_dependencies generate_ru_dependencies(srslog::basic_logger&
11041104
sector_deps.eth_gateway = std::move(gateway);
11051105

11061106
// Configure Ethernet receiver.
1107-
if (!test_params.use_loopback_receiver) {
1108-
auto dummy_receiver = std::make_unique<dummy_eth_receiver>(logger, *workers.ru_rx_exec);
1109-
eth_receiver = dummy_receiver.get();
1110-
sector_deps.eth_receiver = std::move(dummy_receiver);
1111-
}
1107+
auto dummy_receiver = std::make_unique<dummy_eth_receiver>(logger, *workers.ru_rx_exec);
1108+
eth_receiver = dummy_receiver.get();
1109+
sector_deps.eth_receiver = std::move(dummy_receiver);
11121110

11131111
return dependencies;
11141112
}
@@ -1138,20 +1136,26 @@ int main(int argc, char** argv)
11381136
test_gateway* tx_gateway;
11391137
test_ether_receiver* eth_receiver;
11401138

1139+
ru_ofh_configuration ru_cfg = generate_ru_config();
1140+
ru_ofh_dependencies ru_deps =
1141+
generate_ru_dependencies(logger, workers, &timing_notifier, &rx_symbol_notifier, tx_gateway, eth_receiver);
1142+
11411143
if (test_params.use_loopback_receiver) {
1144+
ru_deps.sector_dependencies[0].eth_receiver.reset();
11421145
eth_receiver_ptr = std::make_unique<lo_eth_receiver>(logger);
11431146
eth_receiver = eth_receiver_ptr.get();
11441147
}
1145-
1146-
ru_ofh_configuration ru_cfg = generate_ru_config();
1147-
ru_ofh_dependencies ru_deps =
1148-
generate_ru_dependencies(logger, workers, &timing_notifier, &rx_symbol_notifier, tx_gateway, eth_receiver);
11491148
std::unique_ptr<radio_unit> ru_object = create_ofh_ru(ru_cfg, std::move(ru_deps));
11501149

11511150
// Get RU downlink plane handler.
11521151
auto& ru_dl_handler = ru_object->get_downlink_plane_handler();
11531152
auto& ru_ul_handler = ru_object->get_uplink_plane_handler();
11541153

1154+
if (test_params.use_loopback_receiver) {
1155+
eth_receiver_ptr = std::make_unique<lo_eth_receiver>(logger);
1156+
eth_receiver = eth_receiver_ptr.get();
1157+
}
1158+
11551159
// Create RU emulator instance.
11561160
ru_compression_params ul_compression_params{to_compression_type(test_params.data_compr_method),
11571161
test_params.data_bitwidth};

tests/unittests/ofh/ethernet/ethernet_frame_pool_test.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,113 @@ TEST_P(EthFramePoolFixture, read_interval_should_return_correct_data)
412412
pool.clear_sent_frame_buffers(interval);
413413
}
414414

415+
// Pool should have enough space to store C-Plane and U-Plane packets for all antennas.
416+
TEST_P(EthFramePoolFixture, pool_should_have_enough_space)
417+
{
418+
slot_point slot(to_numerology_value(scs), 0);
419+
for (unsigned slot_count = 0; slot_count < TEST_NUM_SLOTS; ++slot_count) {
420+
for (unsigned symbol = 0; symbol < nof_symbols; ++symbol) {
421+
ofh::slot_symbol_point symbol_point(slot, symbol, nof_symbols);
422+
ether::frame_pool_context ctx{{ofh_type, ofh::data_direction::downlink}, symbol_point};
423+
unsigned nof_requested_buffers = ofh::MAX_NOF_SUPPORTED_EAXC;
424+
// DL C-Plane and U-Plane
425+
for (unsigned i = 0; i != nof_requested_buffers; ++i) {
426+
span<frame_buffer> frame_buffers = pool.get_frame_buffers(ctx);
427+
ASSERT_TRUE(!frame_buffers.empty()) << "Non-empty span of buffers expected";
428+
for (auto& buffer : frame_buffers) {
429+
buffer.set_size(64);
430+
}
431+
pool.push_frame_buffers(ctx, frame_buffers);
432+
}
433+
pool.read_frame_buffers(ctx);
434+
pool.clear_sent_frame_buffers(ctx);
435+
436+
if (ofh_type == ofh::message_type::user_plane) {
437+
continue;
438+
}
439+
// UL C-Plane
440+
// We may need to write Type 1 and Type 3 C-Plane messages in the same slot and symbol.
441+
nof_requested_buffers *= 2;
442+
ctx = {{ofh_type, ofh::data_direction::uplink}, symbol_point};
443+
for (unsigned i = 0; i != nof_requested_buffers; ++i) {
444+
span<frame_buffer> frame_buffers = pool.get_frame_buffers(ctx);
445+
ASSERT_TRUE(!frame_buffers.empty()) << "Non-empty span of buffers expected";
446+
for (auto& buffer : frame_buffers) {
447+
buffer.set_size(64);
448+
}
449+
pool.push_frame_buffers(ctx, frame_buffers);
450+
}
451+
pool.read_frame_buffers(ctx);
452+
pool.clear_sent_frame_buffers(ctx);
453+
}
454+
++slot;
455+
}
456+
}
457+
458+
TEST_P(EthFramePoolFixture, clearing_full_pool_should_allow_adding_more_data)
459+
{
460+
slot_point slot(to_numerology_value(scs), 0);
461+
for (unsigned slot_count = 0; slot_count < TEST_NUM_SLOTS; ++slot_count) {
462+
for (unsigned symbol = 0; symbol < nof_symbols; ++symbol) {
463+
ofh::slot_symbol_point symbol_point(slot, symbol, nof_symbols);
464+
465+
if (ofh_type == ofh::message_type::control_plane && symbol != 0) {
466+
continue;
467+
}
468+
469+
// DL C-Plane and U-Plane
470+
bool pool_has_space = true;
471+
ether::frame_pool_context ctx{{ofh_type, ofh::data_direction::downlink}, symbol_point};
472+
unsigned nof_requested_buffers = ofh::MAX_NOF_SUPPORTED_EAXC;
473+
while (pool_has_space) {
474+
span<frame_buffer> frame_buffers = pool.get_frame_buffers(ctx);
475+
pool_has_space = !frame_buffers.empty();
476+
for (auto& buffer : frame_buffers) {
477+
buffer.set_size(64);
478+
}
479+
pool.push_frame_buffers(ctx, frame_buffers);
480+
}
481+
// Clear full slot in the pool and try to get buffers again.
482+
pool.clear_slot(slot);
483+
for (unsigned i = 0; i != nof_requested_buffers; ++i) {
484+
span<frame_buffer> frame_buffers = pool.get_frame_buffers(ctx);
485+
ASSERT_TRUE(!frame_buffers.empty()) << "Non-empty span of buffers expected";
486+
pool.push_frame_buffers(ctx, frame_buffers);
487+
}
488+
pool.read_frame_buffers(ctx);
489+
pool.clear_sent_frame_buffers(ctx);
490+
491+
if (ofh_type == ofh::message_type::user_plane) {
492+
continue;
493+
}
494+
495+
// UL C-Plane
496+
// We may need to write Type 1 and Type 3 C-Plane messages in the same slot and symbol.
497+
nof_requested_buffers *= 2;
498+
ctx = {{ofh_type, ofh::data_direction::uplink}, symbol_point};
499+
pool_has_space = true;
500+
while (pool_has_space) {
501+
span<frame_buffer> frame_buffers = pool.get_frame_buffers(ctx);
502+
pool_has_space = !frame_buffers.empty();
503+
for (auto& buffer : frame_buffers) {
504+
buffer.set_size(64);
505+
}
506+
pool.push_frame_buffers(ctx, frame_buffers);
507+
}
508+
// Clear full slot in the pool and try to get buffers again.
509+
pool.clear_slot(slot);
510+
for (unsigned i = 0; i != nof_requested_buffers; ++i) {
511+
span<frame_buffer> frame_buffers = pool.get_frame_buffers(ctx);
512+
ASSERT_TRUE(!frame_buffers.empty()) << "Non-empty span of buffers expected";
513+
pool.push_frame_buffers(ctx, frame_buffers);
514+
}
515+
pool.read_frame_buffers(ctx);
516+
pool.clear_sent_frame_buffers(ctx);
517+
}
518+
++slot;
519+
}
520+
}
521+
415522
INSTANTIATE_TEST_SUITE_P(EthFramePoolTestSuite,
416523
EthFramePoolFixture,
417524
::testing::Combine(::testing::Values(mtu::MTU_9000, mtu::MTU_5000, mtu::MTU_1500),

0 commit comments

Comments
 (0)