riebl / vanetza

Open-source implementation of the ETSI C-ITS protocol stack
Other
202 stars 158 forks source link

Correct usage of DCC #147

Closed khevessy closed 2 years ago

khevessy commented 2 years ago

Hi, a have a little problem when implementing DCC. I think I am doing something wrong and I thought you could help me. I have implemented simple CA service that is sending CAM messages. If I use DccPassthrough from original socktap example, all is working correctly. However, when I try to use my own DCC class with DccInformationSharing, BurstyTransmitRateControl, FlowControl and SmoothingChannelProbeProcessor, something weird happens. I am trying to send messages with period of 1 second, but it is not possible, nothing is sent, and then after ten seconds, there is a burst of sent messages where (all or almost) all of the previously queued messages are transmitted, and then again nothing is sent for 10 seconds. I think that burst transmit rate control is holding the transfer for some reason, but I do not know why as the channel is not loaded. Measured CBR is 0. FlowControl's trigger() function is being called. I think I am omitting some callback somewhere, but I cannot seem to find it. I do not know what else to add, Here is code of my Dcc class:

#include <random>
#include <vanetza/common/unit_interval.hpp>
#include "dcc.hpp"

Dcc::Dcc(vanetza::Runtime& runtime, vanetza::geonet::Router* pRouter, vanetza::access::Interface& accessInterface)
        : m_Runtime(runtime),
          m_Router(pRouter),
          m_FiniteStateMachine(CBR_MAPPING),
          m_ChannelProbeProcessor(),
          m_AccessInterface(accessInterface)
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<double> dis(0.0, 1.0);
    vanetza::UnitInterval interval(dis(gen));
    m_Network.reset(new vanetza::geonet::DccInformationSharing(m_Runtime,
                                                               m_Router->get_location_table(),
                                                               vanetza::dcc::ChannelLoad(CBR_TARGET_VALUE),
                                                               interval));  // Random initial interval
    m_Network->on_global_cbr_update  = [this](const vanetza::geonet::CbrAggregator& cbr)
        {
            globalCbrUpdate(cbr.get_global_cbr());  // Periodical callback, called when global CBR is counted from the location table
        };

    // Initialize the transmit rate control
    m_TransmitRateControl.reset(new vanetza::dcc::BurstyTransmitRateControl(m_FiniteStateMachine, m_Runtime));

    m_FlowControl.reset(new vanetza::dcc::FlowControl(m_Runtime, *m_TransmitRateControl, m_AccessInterface));

    m_ChannelProbeProcessor.on_indication = std::bind(&Dcc::localCbrUpdate, this, std::placeholders::_1);
}

void Dcc::globalCbrUpdate(vanetza::dcc::ChannelLoad cbr)
{
    m_FiniteStateMachine.update(cbr);
}

void Dcc::localCbrUpdate(vanetza::dcc::ChannelLoad cbr)
{
    if (m_Network)
        m_Network->update_local_cbr(cbr);
}

void Dcc::CbrMeasurement(vanetza::dcc::ChannelLoad cbr)
{
    m_ChannelProbeProcessor.indicate(cbr);
}

Here is an example run for better illustration: image

Thanks for your possible help, Karel

kenog commented 2 years ago

Hi Karel,

what DCC profile did you assign your CAMs? Did you also try another rate control algorithm (e.g. LimericRateControl)? What was the outcome? You wrote that FlowControl's trigger() is called. When? After 10s or directly after generating the message?

Best regards Keno

khevessy commented 2 years ago

Hi Keno,

thanks for your response.

1) I assigned priority DP2 to CAM messages. When I tried other priorities, it did not change anything (including DP0). 3) FlowControl's trigger() is called every 10 seconds.

2) Per your suggestion I tried LimericRateControl and it works, but it sends the packets basically one second too late: image

FlowControl::trigger() is not called in this case, but LimericTransmitRateControl::notify() is called (from FlowControl::request()). I think that something is missing in my code, but I do not know what.

Regards, Karel

riebl commented 2 years ago

My first guess is that your finite state machine is not behaving as expected. Can you please verify that your outgoing messages are actually not DP0 and that the transmission interval derived from your FSM is as expected? For example, you could set some breakpoints in BurstyTransmitRateControl::interval for this purpose. You may also want to call FlowControl::reschedule when your state machine changes.

khevessy commented 2 years ago

Outgoing messages are really DP2 and transmission interval from interval = m_fsm.transmission_interval(); is 50000 (as I checked from debugger), which I believe is correct? What do you exactly mean by "when state machine changes", in other words, when exactly should be FlowControl::reschedule called? Is it when CBR measurement is taken?

Another thing, as @kenog asked me above, how often should FlowControl::trigger() be called? For me it seems it is called every ten seconds when the messages are actually transmit, is this correct?

Thanks for your help.

Regards, Karel

khevessy commented 2 years ago

I am sorry! You were correct, my outgoing messages were actually DP0. What confused me was that I looked only into BurstyTransmitRateControl::interval() and did not look to BurstyTransmitRateControl::notify() as I should have. I neglected to fill the traffic_class in the new message... now, when this is fixed, BurstyTransmitRateControl is behaving the same as LimericRateControl, all packets are delayed by one second:

image

Do you have any idea what could I be doing wrong this time? I tried setting maximum_lifetime to 50 ms which did not help. Or is this the correct behavior?

riebl commented 2 years ago

Honestly, I am confused by your log: Do the "real sending" and "CA Service sending" lines tagged with #n belong together? Why is the timestamp of the CA service then after its "real sending" sibling? Where do you read the delay of one second?

khevessy commented 2 years ago

You are correct, my debug print in CA Service was one line too late, which was really confusing. Sorry. It is working without any problem now. Closing this issue.