Keep vanetza-idf in obu-firmware, so a plain clone builds the firmware
obu-firmware builds against the vanetza-idf C-ITS library, which until now came from the colleague's microbu-esp32c5 tree beside the repository and was not tracked here, so a clone of this repository could not build the firmware it ships. The library alone is now part of obu-firmware, as obu-firmware/external/vanetza-idf: their external/vanetza-idf at commit cf4b99f, unchanged (9775 files; see its PROVENANCE.md). CMake takes it from there by default; -DVANETZA_IDF_DIR still points the build elsewhere. The rest of the colleague's tree (their own VAM firmware, PKI tooling, station-link Python tools, the V2X2MAP bridge) stays out of this repository and gitignored; nothing is pushed to their repository. NOTES.md, docs/06, TODO.md and the pcap verifier's usage line point at the new location.
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
#include <vanetza/common/runtime.hpp>
|
||||
#include <vanetza/geonet/address.hpp>
|
||||
#include <vanetza/geonet/cbf_counter.hpp>
|
||||
#include <vanetza/geonet/cbf_packet_buffer.hpp>
|
||||
#include <vanetza/geonet/pdu.hpp>
|
||||
#include <vanetza/units/time.hpp>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace geonet
|
||||
{
|
||||
|
||||
CbfPacket::CbfPacket(PendingPacket<GbcPdu>&& packet, const MacAddress& sender) :
|
||||
m_packet(std::move(packet)), m_sender(sender)
|
||||
{
|
||||
}
|
||||
|
||||
CbfPacket::CbfPacket(PendingPacket<GbcPdu, const MacAddress&>&& packet, const MacAddress& sender) :
|
||||
m_packet(PendingPacket<GbcPdu>(std::move(packet), cBroadcastMacAddress)), m_sender(sender)
|
||||
{
|
||||
}
|
||||
|
||||
const MacAddress& CbfPacket::sender() const
|
||||
{
|
||||
return m_sender;
|
||||
}
|
||||
|
||||
const Address& CbfPacket::source() const
|
||||
{
|
||||
return m_packet.pdu().extended().source_position.gn_addr;
|
||||
}
|
||||
|
||||
SequenceNumber CbfPacket::sequence_number() const
|
||||
{
|
||||
return m_packet.pdu().extended().sequence_number;
|
||||
}
|
||||
|
||||
Clock::duration CbfPacket::reduce_lifetime(Clock::duration d)
|
||||
{
|
||||
return m_packet.reduce_lifetime(d);
|
||||
}
|
||||
|
||||
std::size_t CbfPacket::length() const
|
||||
{
|
||||
return m_packet.length();
|
||||
}
|
||||
|
||||
|
||||
CbfPacketBuffer::CbfPacketBuffer(Runtime& rt, TimerCallback cb, std::unique_ptr<CbfCounter> cnt, std::size_t bytes) :
|
||||
m_runtime(rt), m_counter(std::move(cnt)),
|
||||
m_capacity_bytes(bytes), m_stored_bytes(0),
|
||||
m_timer_callback(cb)
|
||||
{
|
||||
}
|
||||
|
||||
CbfPacketBuffer::~CbfPacketBuffer()
|
||||
{
|
||||
m_runtime.cancel(this);
|
||||
}
|
||||
|
||||
bool CbfPacketBuffer::remove(const Identifier& id)
|
||||
{
|
||||
bool packet_dropped = false;
|
||||
|
||||
auto& id_map = m_timers.right;
|
||||
auto found = id_map.find(id);
|
||||
if (found != id_map.end()) {
|
||||
auto& packet = found->info;
|
||||
m_stored_bytes -= packet->length();
|
||||
m_counter->remove(id);
|
||||
m_packets.erase(packet);
|
||||
remove_timer(m_timers.project_left(found));
|
||||
packet_dropped = true;
|
||||
}
|
||||
|
||||
assert(m_packets.size() == m_timers.size());
|
||||
return packet_dropped;
|
||||
}
|
||||
|
||||
void CbfPacketBuffer::remove_timer(typename timer_bimap::left_map::iterator timer_it)
|
||||
{
|
||||
auto& timer_map = m_timers.left;
|
||||
auto successor = timer_map.erase(timer_it);
|
||||
if (successor == timer_map.begin() && !timer_map.empty()) {
|
||||
// erased timer was scheduled one, reschedule timer trigger
|
||||
schedule_timer();
|
||||
}
|
||||
}
|
||||
|
||||
void CbfPacketBuffer::add(CbfPacket&& packet, Clock::duration timeout)
|
||||
{
|
||||
if(timeout <= Clock::duration::zero()) return;
|
||||
m_stored_bytes += packet.length();
|
||||
const auto first_timer = m_timers.left.begin();
|
||||
|
||||
// do head drop if necessary
|
||||
while (m_stored_bytes > m_capacity_bytes && !m_packets.empty()) {
|
||||
m_stored_bytes -= m_packets.front().length();
|
||||
const auto id = identifier(m_packets.front());
|
||||
m_timers.right.erase(id);
|
||||
m_counter->remove(id);
|
||||
m_packets.pop_front();
|
||||
}
|
||||
|
||||
Timer timer = { m_runtime, timeout };
|
||||
const Identifier id = identifier(packet);
|
||||
m_packets.emplace_back(std::move(packet));
|
||||
using timer_value = timer_bimap::value_type;
|
||||
auto insertion = m_timers.insert(timer_value { timer, id, std::prev(m_packets.end()) });
|
||||
if (!insertion.second) {
|
||||
m_stored_bytes -= m_packets.back().length();
|
||||
m_packets.pop_back();
|
||||
} else {
|
||||
m_counter->add(id);
|
||||
}
|
||||
|
||||
// first expirying timer has changed (head drop or added packet)
|
||||
if (m_timers.left.begin() != first_timer) {
|
||||
schedule_timer();
|
||||
}
|
||||
assert(m_packets.size() == m_timers.size());
|
||||
}
|
||||
|
||||
void CbfPacketBuffer::update(const Identifier& id, Clock::duration timeout)
|
||||
{
|
||||
auto& id_map = m_timers.right;
|
||||
auto found = id_map.find(id);
|
||||
if (found != id_map.end()) {
|
||||
const Timer& timer = found->second;
|
||||
CbfPacket& cbf_packet = *found->info;
|
||||
reduce_lifetime(timer, cbf_packet);
|
||||
id_map.replace_data(found, Timer { m_runtime, timeout});
|
||||
m_counter->increment(id);
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<CbfPacket> CbfPacketBuffer::fetch(const Identifier& id)
|
||||
{
|
||||
boost::optional<CbfPacket> packet;
|
||||
|
||||
auto& id_map = m_timers.right;
|
||||
auto found = id_map.find(id);
|
||||
if (found != id_map.end()) {
|
||||
const Timer& timer = found->second;
|
||||
CbfPacket& cbf_packet = *found->info;
|
||||
bool valid_packet = reduce_lifetime(timer, cbf_packet);
|
||||
m_stored_bytes -= cbf_packet.length();
|
||||
if (valid_packet) {
|
||||
packet.emplace(std::move(cbf_packet));
|
||||
}
|
||||
m_counter->remove(id);
|
||||
m_packets.erase(found->info);
|
||||
remove_timer(m_timers.project_left(found));
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
const CbfPacket* CbfPacketBuffer::find(const Identifier& id) const
|
||||
{
|
||||
const auto& id_map = m_timers.right;
|
||||
auto found = id_map.find(id);
|
||||
return found != id_map.end() ? &(*found->info) : nullptr;
|
||||
}
|
||||
|
||||
std::size_t CbfPacketBuffer::counter(const Identifier& id) const
|
||||
{
|
||||
return m_counter->counter(id);
|
||||
}
|
||||
|
||||
void CbfPacketBuffer::flush()
|
||||
{
|
||||
// fetch all expired timers
|
||||
const Timer now { m_runtime, std::chrono::seconds(0) };
|
||||
auto end = m_timers.left.upper_bound(now);
|
||||
for (auto it = m_timers.left.begin(); it != end;) {
|
||||
// reduce LT by queuing time
|
||||
const Timer& timer = it->first;
|
||||
CbfPacket& packet = *it->info;
|
||||
bool valid_packet = reduce_lifetime(timer, packet);
|
||||
m_stored_bytes -= packet.length();
|
||||
if (valid_packet) {
|
||||
m_timer_callback(std::move(packet).packet());
|
||||
}
|
||||
|
||||
m_counter->remove(it->second);
|
||||
m_packets.erase(it->info);
|
||||
it = m_timers.left.erase(it);
|
||||
}
|
||||
|
||||
// schedule timer if not empty
|
||||
if (!m_timers.empty()) {
|
||||
schedule_timer();
|
||||
}
|
||||
}
|
||||
|
||||
bool CbfPacketBuffer::reduce_lifetime(const Timer& timer, CbfPacket& packet) const
|
||||
{
|
||||
const auto queuing_time = m_runtime.now() - timer.start;
|
||||
return packet.reduce_lifetime(queuing_time) > Clock::duration::zero();
|
||||
}
|
||||
|
||||
void CbfPacketBuffer::schedule_timer()
|
||||
{
|
||||
assert(!m_timers.empty());
|
||||
m_runtime.cancel(this);
|
||||
Runtime::Callback cb = [this](Clock::time_point) { flush(); };
|
||||
m_runtime.schedule(m_timers.left.begin()->first.expiry, cb, this);
|
||||
}
|
||||
|
||||
|
||||
CbfPacketBuffer::Timer::Timer(const Runtime& rt, Clock::duration timeout) :
|
||||
expiry(rt.now() + timeout), start(rt.now())
|
||||
{
|
||||
}
|
||||
|
||||
bool CbfPacketBuffer::Timer::operator<(const Timer& other) const
|
||||
{
|
||||
return this->expiry < other.expiry;
|
||||
}
|
||||
|
||||
} // namespace geonet
|
||||
} // namespace vanetza
|
||||
|
||||
Reference in New Issue
Block a user