0

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)

1 Answers1

0

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).

Jerzy D.
  • 6,707
  • 2
  • 16
  • 22
  • Thank you, that worked great! Another random question since you seem to be a great font of knowledge in this area - Do you know how to (hopefully easily) change the transfer protocol for messages? By default in the Sample Application it is UDP, however I think this is too simple as the actual message in GeneralMessage is not recorded in the Pcap file I later analyse. I.e., I'd like the speed of the vehicle to be visible in that Pcap recording. I can see from the Pcap showcase that perhaps I may need to use ARP. Is this possible? –  Dec 28 '22 at 12:56
  • 1
    `VeinsInetApplicationBase` uses multicast IPv4 address (i.e. 224.0.0.1) as a destination address, so the transport type must be UDP. Therefore, you cannot use TCP instead of UDP. – Jerzy D. Dec 30 '22 at 08:30
  • Again, thank you. Is it possible to change this in some way to manipulate the protocol type? I can see multiple protocol types in the Pcap Showcase example with Inet, but the code seems quite minimal and difficult to extract information from –  Dec 31 '22 at 10:55