Search code examples
serializationomnet++pcapveinsinet

Problem with message serializer in veins_inet simulation


I'm attempting to customize the veins_inet project (I have implemented a custom SUMO map and about 10 nodes. This simulation runs fine without the additions I present here), and in particular send a message containing the speed to each vehicle at set periods (this is completely disjoint to the messages sent during an accident). The .msg file I have is given simply by:

import inet.common.INETDefs;
import inet.common.packet.chunk.Chunk;

//
// General message definition
//
class GeneralMessage extends inet::FieldsChunk
{
    double Speed;
    
}

and the serializer files I have written for this messages are given by:

// GeneralMessageSerializer.h
#ifndef __GENERALMESSAGESERIALIZER_H
#define __GENERALMESSAGESERIALIZER_H

#include "inet/common/packet/ChunkQueue.h"
#include "inet/common/packet/Packet.h"
#include "inet/common/packet/serializer/FieldsChunkSerializer.h"
#include "inet/common/packet/serializer/SequenceChunkSerializer.h"
#include "GeneralMessage_m.h"

namespace inet {

class GeneralMessageSerializer : public FieldsChunkSerializer
{
  public:
    virtual void serialize(MemoryOutputStream& stream, const Ptr<const Chunk>& chunk) const override;
    virtual const Ptr<Chunk> deserialize(MemoryInputStream& stream) const override;
};


}

#endif // __GENERALMESSAGESERIALIZER_H

// GeneralMessageSerializer.cc
#include "GeneralMessageSerializer.h"
#include "GeneralMessage_m.h"
#include "inet/common/packet/chunk/ByteCountChunk.h"
#include "inet/common/packet/chunk/BytesChunk.h"
#include "inet/common/packet/ChunkBuffer.h"
#include "inet/common/packet/Packet.h"
#include "inet/common/packet/ReassemblyBuffer.h"
#include "inet/common/packet/ReorderBuffer.h"
#include "inet/common/packet/serializer/ChunkSerializerRegistry.h"
#include "inet/common/TimeTag_m.h"

namespace inet {

Register_Serializer(GeneralMessage, GeneralMessageSerializer);

#define ASSERT_ERROR(code, message) try { code; ASSERT(false); } catch (std::exception& e) { ASSERT((int)std::string(e.what()).find(message) != -1); };

void GeneralMessageSerializer::serialize(MemoryOutputStream& stream, const Ptr<const Chunk>& chunk) const
{
    const auto& generalMessage = staticPtrCast<const GeneralMessage>(chunk);
//    auto Speed = stream.getSpeed();
    stream.writeUint32Be(generalMessage->getSpeed());
    stream.writeByteRepeatedly(0, B(generalMessage->getChunkLength()).get());
}

const Ptr<Chunk> GeneralMessageSerializer::deserialize(MemoryInputStream& stream) const
{
    auto generalMessage = makeShared<GeneralMessage>();
    generalMessage->setSpeed(stream.readUint32Be());
    stream.readByteRepeatedly(0, B(generalMessage->getChunkLength()).get());
    return generalMessage;

}}

This message is implemented into the veins_inet sample application by the addition of the code block

int i;
    for(i=25;i<150;i++){
        // every node to send out a general message every second
        auto callback = [this]() {
            auto payload = makeShared<GeneralMessage>();
            auto packet = createPacket("general");
            payload->setChunkLength(B(150));
            payload->setSpeed(traciVehicle->getSpeed());
            timestampPayload(payload);
            packet->insertAtBack(payload);
            sendPacket(std::move(packet));
        };
        timerManager.create(veins::TimerSpecification(callback).oneshotAt(SimTime(i, SIMTIME_S)));
    };

in the StartApplication function of the VeinsInetSampleApplication.cc file. As you can see, I'd like this GeneralMessage to be broadcast every second by every node in the simulation starting at 25s. For reference, I then have Pcap recorders on each node to record these messages but so far I haven't managed to get a message to be visible in these recordings as I suspected it wasn't being serialized in the right way.

The error I am receiving while trying to run this is:

Implicit chunk serialization is disabled to prevent unpredictable performance degradation (you may consider changing the Chunk::enableImplicitChunkSerialization flag or passing the PF_ALLOW_SERIALIZATION flag to peek) -- in module (VeinsInetSampleApplication) Scenario.node[0].app[0] (id=110), at t=25s, event #143

In case it is also useful, here is the readout from the last handful of events before the error hit in the console:

** Event #133 t=25 Scenario.node[8].ipv4.ip (Ipv4, id=658) on general (inet::Packet, id=1536)

INFO:Received (inet::Packet)general from network. DETAIL:Received datagram `' with dest=224.0.0.1 INFO:Delivering (inet::Packet)general (178 B) [[inet::Ipv4Header, length = 20 B | inet::UdpHeader, port:9001->9001, payloadLength:150 B, length = 8 B | GeneralMessage, length = 150 B]] locally. WARN:Received datagram 'general' without source address filled in INFO:Passing up to protocol udp(57) ** Event #134 t=25 Scenario.node[8].wlan[0].mac (Ieee80211Mac, id=622) on general (inet::Packet, id=1528)

INFO:Frame (inet::Packet)general (208 B) [[inet::ieee80211::Ieee80211DataHeader, length = 24 B | inet::Ieee80211EtherTypeHeader, length = 2 B | inet::Ipv4Header, length = 20 B | inet::UdpHeader, port:9001->9001, payloadLength:150 B, length = 8 B | GeneralMessage, length = 150 B | inet::ieee80211::Ieee80211MacTrailer, length = 4 B]] received from higher layer, receiver = 01-00-5E-00-00-01 INFO (Dcf)Scenario.node[8].wlan[0].mac.dcf:Processing upper frame: general INFO (PendingQueue)Scenario.node[8].wlan[0].mac.dcf.channelAccess.pendingQueue:Pushing packet general into the queue. DETAIL (Dcf)Scenario.node[8].wlan[0].mac.dcf:Requesting channel DETAIL (Contention)Scenario.node[8].wlan[0].mac.dcf.channelAccess.contention:Starting contention: cw = 15, slots = 15, slotTime = 0.000013, ifs = 0.000058, eifs = 0.000178 INFO (Contention)Scenario.node[8].wlan[0].mac.dcf.channelAccess.contention:Scheduling contention end: backoffslots = 15, slotTime = 0.000013, lastBusyTime = 20.000152936058, lastIdle = -4611676.018427387903, waitInterval = 0. ** Event #135 t=25 Scenario.node[0].udp (Udp, id=107) on general (inet::Packet, id=1529)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=0 ** Event #136 t=25 Scenario.node[1].udp (Udp, id=170) on general (inet::Packet, id=1530)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=1 ** Event #137 t=25 Scenario.node[2].udp (Udp, id=233) on general (inet::Packet, id=1531)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=2 ** Event #138 t=25 Scenario.node[3].udp (Udp, id=296) on general (inet::Packet, id=1532)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=3 ** Event #139 t=25 Scenario.node[4].udp (Udp, id=359) on general (inet::Packet, id=1533)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=4 ** Event #140 t=25 Scenario.node[5].udp (Udp, id=422) on general (inet::Packet, id=1534)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=5 ** Event #141 t=25 Scenario.node[7].udp (Udp, id=548) on general (inet::Packet, id=1535)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=7 ** Event #142 t=25 Scenario.node[8].udp (Udp, id=611) on general (inet::Packet, id=1536)

INFO:Packet general received from network, dest port 9001 INFO:Sending payload up to socket sockId=8 ** Event #143 t=25 Scenario.node[0].app[0] (VeinsInetSampleApplication, id=110) on general (inet::Packet, id=1529)


Solution

  • You have changed the type of the message you send in VeinsInetSampleApplication but you have not changed the type of expected received message. So in VeinsInetSampleApplication.cc there is something like that:

    void VeinsInetSampleApplication::processPacket(std::shared_ptr<inet::Packet> pk)
    {
      auto payload = pk->peekAtFront<VeinsInetSampleMessage>();  // <-- causes an error
      EV_INFO << "Received packet: " << payload << endl;
      ...
    

    Therefore during receiving a packet is treated as VeinsInetSampleMessage, not GeneralMessage - it leads to an exception. I suggest changing that line into:

    auto payload = pk->peekAtFront<GeneralMessage>();
    

    And of course the remaining part of processPacket() must be changed accordingly (e.g. GeneralMessage doesn't contain roadId so one mustn't read it).