How to directly inject packets to another module in OMNet++ - omnet++

My compound module is multiple layers as show in the attached figure.
Here Layer2 has a cPacketQueue buffer and I want the Layer1 module to directly insert packets into this cPacketQueue of Layer2. Layer1 and Layer2 gates are connected unidirecttionally as show in the figure.
Layer1Gate --> Layer2Gate
UPDATED:
Layer 1 creates Packets with different priorities (0-7) and injects to 8 different cPacketQueues in Layer2 named as priorityBuffers[i], (i is the index).
The Layer2 then sends self messages in intervals of 10ns to poll all these buffers in each iteration and send the packets.
This is all I am doing now. It works fine. But I know 10ns polling is definitely not an efficient way to do this and achieve QoS. So requesting for a better alternative.

I suggest adding a ControlInfo object with priority to every packet from Layer1, send the packet using send() command, then checking ControlInfo of received packet in Layer2, and insert the packet into a specific queue.
Firstly, one should define a class for ControlInfo, for example in common.h:
// common.h
class PriorityControlInfo : public cObject {
public:
int priority;
};
Then in C++ code of Layer1 simple module:
#include "common.h"
// ...
// in the method where packet is created
cPacket * packet = new cPacket();
PriorityControlInfo * info = new PriorityControlInfo();
info->priority = 2; // 2 is desired queue number
packet->setControlInfo(info);
send (packet, "out");
And finally in Layer2:
#include "common.h"
// ...
void Layer2::handleMessage(cMessage *msg) {
cPacket *packet = dynamic_cast<cPacket *>(msg);
if (packet) {
cObject * ci = packet->removeControlInfo();
if (ci) {
PriorityControlInfo * info = check_and_cast<PriorityControlInfo*>(ci);
int queue = info->priority;
EV << "Received packet to " << static_cast<int> (queue) << " queue.\n";
priorityBuffers[queue].insert(packet);
EV << priorityBuffers[queue].info() << endl;
}
}
}
According to using of self messages: I do not understand clearly what is your intention.
Does Layer2 should send a packet immediately after receiving it? If yes why do you use a buffer? In that situation instead of inserting a packet to a buffer, Layer2 should just send it to the Layer3.
Does Layer2 should do something else after receiving a packet and inserting it in a buffer? If yes, just call this action (function) in the above handleMessage().
In the both above variants there is no need to use self messages.

Related

Send an struct array across a FREERTOS queue

I am starting with ESP32 and FREERTOS, and I am having problems sending an Struct array across a queue. I have already sent another kind of variables but never an array of Structs and I am getting an exception.
The sender and the receiver are in different source files and I am starting to thing that maybe is the problem (or at least part of the problem).
My simplified code looks like this:
common.h
struct dailyWeather {
// Day of the week starting in Monday (1)
int dayOfWeek;
// Min and Max daily temperature
float minTemperature;
float maxTemperature;
int weather;
};
file1.h
#pragma once
#ifndef _FILE1_
#define _FILE1_
// Queue
extern QueueHandle_t weatherQueue;
#endif
file1.cpp
#include "common.h"
#include "file1.h"
// Queue
QueueHandle_t weatherQueue = xQueueCreate( 2, sizeof(dailyWeather *) ); // also tried "dailyWeather" without pointer and "Struct dailyWeather"
void task1(void *pvParameters) {
for (;;) {
dailyWeather weatherDATA[8] = {};
// Code to fill the array of structs with data
if (xQueueSend( weatherQueue, &weatherDATA, ( TickType_t ) 0 ) == pdTRUE) {
// The message was sent sucessfully
}
}
}
file2.cpp
#include "common.h"
#include "file1.h"
void task2(void *pvParameters) {
for (;;) {
dailyWeather *weatherDATA_P; // Also tried without pointer and as an array of Structs
if( xQueueReceive(weatherQueue, &( weatherDATA_P ), ( TickType_t ) 0 ) ) {
Serial.println("Received");
dailyWeather weatherDATA = *weatherDATA_P;
Serial.println(weatherDATA.dayOfWeek);
}
}
}
When I run this code on my ESP32 it works until I try to print the data with Serial.println. The "Received" message is printed, but it crash in the next Serial.println with this error.
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
I am locked with this problem and I am not able to find a way to fix it, so any help will be very apreciated.
EDIT:
I am thinking that maybe a solution will be just to add an order item to the struct, make the queue bigger (in number) and send all the Structs separately to the queue. Then use that order in reader to order it again.
Anyway, will be nice to learn what I am doing wrong with the above code.
freeRTOS queues operate by using the buffer and data size you specify during initialization, when you call xQueueCreate(), to make copies of the data you want to send-receive.
When you call xQueueSend(), which is equivalent to xQueueSendToBack(), it makes a copy into that buffer.
If another task is awaiting for the queue in a call to xQueueReceive(), at the moment it becomes ready to run, xQueueReceive() will make a copy of the item in front of the queue's buffer into the destination buffer you specify in your call to xQueueReceive().
If the data you want to send is of pointer/array type, dailyWeather * in your case, then you need to make sure the memory pointed to by the pointer does not get out of scope before being read by the task that receives the pointer by calling xQueueReceive(). Local variables are created in the calling task's stack and will certainly get out of scope, and very likely overwritten, after the function returns.
IMO, best solution if you really need to pass pointers is to allocate the structures array in the function that generates the data and deallocate it in the task that consumes the data.
For many scenarios it is highly desirable not to abuse of dynamic memory handling, so in several communications stacks you will find the use of buffer pools, which at the end are also queues that are initialized during application startup. Operation is approximately as follows:
Initialization:
Initialize the buffer pool queues (simple queues of pointers).
Fill the buffer pools with dynamically allocated buffers of appropriated sizes.
Initialize the queues for inter- task communications.
Task that provides the data:
Get (Receive) a buffer pointer from one buffer pool.
Fill the buffer with data.
Send the buffer pointer to the communications queue.
Task that receives the data:
Get (Receive) the data buffer pointer from the communications queue.
Use the data.
Return (Send) the buffer pointer to the buffer pool.
In case your structures are small, so you have a more or less constrained copy-then-copy overhead, it makes more sense to create the queue so you work directly with structure instances and structure copies instead of structure buffer pointers.
Firstly it's not a good idea to create the queue in the global scope like you do. A global queue handle is OK. But run xQueueCreate() in the same function that creates task1 and task2 (queue must be created before the tasks), something like this:
QueueHandle_t weatherQueue = NULL;
void main() {
weatherQueue = xQueueCreate(32, sizeof(struct dailyWeather));
if (!weatherQueue) {
// Handle error
}
if (xTaskCreate(task1, ...) != pdPASS) {
// Handle error
}
if (xTaskCreate(task2, ...) != pdPASS) {
// Handle error
}
}
Secondly, the code in task1() does the following in a loop:
Create a new array of 8 dailyWeather structs in stack (in the scope of a single loop iteration)
Copy a pointer to first item in weatherDATA[] to the queue (task2 will receive it a bit later, when it's time to switch tasks)
Release the array of 8 dailyWeather (because we're exiting loop scope)
A bit later task2() executes and tries to read the pointer to first item in weatherDATA[]. However this memory has probably been released already. You can't dereference it.
So you're passing pointers to invalid memory over the queue.
It's much, much easier to work with a queue if you just pass the data you want to send instead of a pointer. Your structure is small and consists of elementary data types, so it's a good idea to pass it over the queue in its entirety, one at a time (you can pass an entire array if you want, but this way is simpler).
Something like this:
void task1(void *pvParameters) {
for (;;) {
dailyWeather weatherDATA[8] = {};
// Code to fill the array of structs with data
for (int i = 0; i < 8; i++) {
// Copy the structs to queue, one at a time
if (xQueueSend( weatherQueue, &(weatherDATA[i]), ( TickType_t ) 0 ) == pdTRUE) {
// The message was sent successfully
}
}
}
}
On the receiver side:
void task2(void *pvParameters) {
for (;;) {
dailyWeather weatherDATA;
if( xQueueReceive(weatherQueue, &( weatherDATA ), ( TickType_t ) 0 ) ) {
Serial.println("Received");
Serial.println(weatherDATA.dayOfWeek);
}
}
}
I cannot recommend the official FreeRTOS book enough, it's a great resource for beginners.
Thanks for all for the answers.
Finally I have added a variable to track the item position and I have passed all the data through the queue to the destination task. Then I put all those structs back into another array.
common.h
#include <stdint.h>
struct dailyWeather {
// Day of the week starting in Monday (1)
uint8_t dayOfWeek;
// Min and Max daily temperature
float minTemperature;
float maxTemperature;
uint8_t weather;
uint8_t itemOrder;
};
file1.h
// Queue
extern QueueHandle_t weatherQueue;
file1.cpp
#include "common.h"
#include "file1.h"
// Queue
QueueHandle_t weatherQueue = xQueueCreate( 2 * 8, sizeof(struct dailyWeather) );
void task1(void *pvParameters) {
for (;;) {
dailyWeather weatherDATA[8];
// Code to fill the array of structs with data
for (uint8_t i = 0; i < 8; i++) {
weatherDATA[i].itemOrder = i;
if (xQueueSend( weatherQueue, &weatherDATA[i], ( TickType_t ) 0 ) == pdTRUE) {
// The message was sent sucessfully
}
}
}
}
file2.cpp
#include "common.h"
#include "file1.h"
void task2(void *pvParameters) {
dailyWeather weatherDATA_D[8];
for (;;) {
dailyWeather weatherDATA;
if( xQueueReceive(weatherQueue, &( weatherDATA ), ( TickType_t ) 0 ) ) {
Serial.println("Received");
weatherDATA_D[weatherDATA.itemOrder] = weatherDATA;
}
}
}
Best regards.

How to find out the number of received packets from each sender

In OMNET++ with INET framework, I want to find out how many packets are received from each sending node.I found the below code. Can anyone tell me what is function of "it->second++" command in below code?
std::map<L3Address, uint64_t> recPkt;
auto it = recPkt.find(senderAddr);
if (it == recPkt.end())
recPkt[senderAddr] = 1;
else
it->second++;
Also, can anyone suggest how to display the number of received packets per node.
it is an iterator to an element of std::map. Iterator is something like a pointer. it points to a pair: <L3Address, uint64_t>. Probably the address of sender is the first element of this pair, and the second one is the number of received packets.
The first element of this pair may be obtained using it->first while the second via it->second.
Operation recPkt.find(senderAddr) checks whether recPkt contains an entry with the address senderAddr:
if not, it points to recPkt.end(), then a new entry is created and 1 is set as value (because first packet has been just received),
if entry for senderAddr already exists, the second value of this element (counter) is incremented using it->second++
To show current value of received packets to internal log window one may use:
for (auto it : recPkt) {
EV << "From address " << it.first << " received " << it.second << " packets." << std::endl;
}
However, the better way is to write these values to statistics. The best place for it is a finish() method of your module:
void YourModule::finish() {
// ..
for (auto it : recPkt) {
std::string name = "Received packet from ";
name += it.first.str(); // address
recordScalar(name, it.second);
}
}
Reference: C++ Reference, std::map
EDIT
One more thing. The declaration of recPkt i.e. line:
std::map<L3Address, uint64_t> recPkt;
must be in your class. recPkt cannot be declared just before use.

OMNET++: How to obtain wireless signal power?

I am using the newly released INET 4.0 framework for OMNET++ and I would like to obtain the received signal strength value in a wireless host (of type AdhocHost). How may I do that?
In INET 4.0.0 the packet received by a module contains several tags. Between others there is SignalPowerInd tag. According to SignalTag.msg:
This indication specifies the average analog signal power that was detected during receiving the packet.
It may be present on a packet from the phyiscal layer to the application.
This tag is present in packet processing by a wireless MAC layer, for example:
And packet received by application layer contains SignalPowerInd too:
One can obtain the value of `SignalPowerInd` from received radio packet in any layer using standard API. For example, to obtain it in `UdpBasicApp` one should add in `UdpBasicApp.cc`:
#include "inet/physicallayer/common/packetlevel/SignalTag_m.h"
// ...
void UdpBasicApp::socketDataArrived(UdpSocket *socket, Packet *packet) {
if (packet->findTag<SignalPowerInd>() != nullptr) {
auto signalPowerInd = packet->getTag<SignalPowerInd>();
auto rxPower = signalPowerInd->getPower().get();
EV_INFO << "RX power= " << rxPower << "W" << endl;
}
// process incoming packet
processPacket(packet);
}

Howto make zeromq PUB/SUB drop old messages instead of new (for realtime feeds)?

Say I have a PUB server that zmq_send()'s realtime messages to SUB client. If client is busy and can not zmq_recv() messages quick enough, then messages will be buffered in client (and/or server).
If the buffer grows too large (high water mark) then NEW messages will be dropped. For realtime messages this is the opposite of what one wants. OLD messages should be dropped to make place for NEW ones.
Is there some way to do this?
Ideally I would like the SUB client's receive queue to be either empty or contain the most recent message only. When a new message is received it would replace the old one. ( I guess the problem here would be that the client would block on zmq_recv() when the queue is empty, wasting time doing so. )
So how are realtime feeds usually implemented in ZeroMQ?
I'll answer my own question here. The setting ZMQ_CONFLATE "Keep only last message" seemed promising but it doesn't work with subscription filters. It only ever keeps one message in the queue. If you have more than one filter, both old and new messages of the other filters type gets thrown away.
Likewise the recommendation of the zeromq guide to simply to kill slow subscribers, but that doesn't seem like realistic solution. Having subscribers with different read speeds, subscribed to the same fast publisher, should be a normal use case. Some of these subscribers might live on slow computers others on fast ones, etc. ZeroMQ should be able to handle that somehow.
http://zguide.zeromq.org/page:all#Slow-Subscriber-Detection-Suicidal-Snail-Pattern
I ended up doing manual dropping of old queued up messages on the client side. It seems to work fine. I get subscribed messages to the client that are less than 3ms old (through tcp localhost) that way. This works even in cases where I have five thousand, 10 second old messages, in the queue in front of those few real-time message at the back. This is good enough for me.
I cant help but think this is something that should be provided by the library. It could probably do a better job of it.
Anyways here is the client side, old message dropping, code:
bool Empty(zmq::socket_t& socket) {
bool ret = true;
zmq::pollitem_t poll_item = { socket, 0, ZMQ_POLLIN, 0 };
zmq::poll(&poll_item, 1, 0); //0 = no wait
if (poll_item.revents & ZMQ_POLLIN) {
ret = false;
}
return ret;
}
std::vector<std::string> GetRealtimeSubscribedMessageVec(zmq::socket_t& socket_sub, int timeout_ms)
{
std::vector<std::string> ret;
struct MessageTmp {
int id_ = 0;
std::string data_;
boost::posix_time::ptime timestamp_;
};
std::map<int, MessageTmp> msg_map;
int read_msg_count = 0;
int time_in_loop = 0;
auto start_of_loop = boost::posix_time::microsec_clock::universal_time();
do {
read_msg_count++;
//msg format sent by publisher is: filter, timestamp, data
MessageTmp msg;
msg.id_ = boost::lexical_cast<int>(s_recv(socket_sub));
msg.timestamp_ = boost::posix_time::time_from_string(s_recv(socket_sub));
msg.data_ = s_recv(socket_sub);
msg_map[msg.id_] = msg;
auto now = boost::posix_time::microsec_clock::universal_time();
time_in_loop = (now - start_of_loop).total_milliseconds();
if (time_in_loop > timeout_ms) {
std::cerr << "Timeout reached. Publisher is probably sending messages quicker than we can drop them." << std::endl;
break;
}
} while ((Empty(socket_sub) == false));
if (read_msg_count > 1) {
std::cout << "num of old queued up messages dropped: " << (read_msg_count - 1) << std::endl;
}
for (const auto &pair: msg_map) {
const auto& msg_tmp = pair.second;
auto now = boost::posix_time::microsec_clock::universal_time();
auto message_age_ms = (now - msg_tmp.timestamp_).total_milliseconds();
if (message_age_ms > timeout_ms) {
std::cerr << "[SUB] Newest message too old. f:" << msg_tmp.id_ << ", age: " << message_age_ms << "ms, s:" << msg_tmp.data_.size() << std::endl;
}
else {
std::cout << "[SUB] f:" << msg_tmp.id_ << ", age: " << message_age_ms << "ms, s:" << msg_tmp.data_.size() << std::endl;
ret.push_back(msg_tmp.data_);
}
}
return ret;
}

Core MIDI: when I send a MIDIPacketList using MIDISend() only the first packet is being sent

I am trying to send a MIDIPacketList containing two packets that describe controller position change message relating to a x-y style controller.
The function i'm trying to implement takes the an x and y position, and then creates the packets and sends them to the selected target device as follows:
- (void)matrixCtrlSetPosX:(int)posX PosY:()posY {
MIDIPacketList packetList;
packetList.numPackets = 2;
packetList.packet[0].length = 3;
packetList.packet[0].data[0] = 0xB0; // status: controller change
packetList.packet[0].data[1] = 0x32; // controller number 50
packetList.packet[0].data[2] = (Byte)posX; // value (x position)
packetList.packet[0].timeStamp = 0;
packetList.packet[1].length = 3;
packetList.packet[1].data[0] = 0xB0; // status: controller change
packetList.packet[1].data[1] = 0x33; // controller number 51
packetList.packet[1].data[2] = (Byte)posY; // value (y position)
packetList.packet[1].timeStamp = 0;
CheckError(MIDISend(_outputPort, _destinationEndpoint, &packetList), "Couldn't send MIDI packet list");
}
The problem I am having is that the program only appears to be sending out the first packet.
I have tried splitting the output into two separate MIDIPacketLists and two making two calls to MIDISend(), which does work, but I am sure that there must be something trivial I am missing out in building the midi packet list so that the two messages can be sent in one call to MIDISend(). I just cannot seem to figure out what the problem is here! Anyone here had experience doing this, or am I going about this the wrong way entirely?
Just declaring the MIDIPacketList doesn't allocate memory or set up the structure. There's a process to adding packets to the list. Here's a quick and dirty example:
- (void)matrixCtrlSetPosX:(int)posX PosY:(int)posY {
MIDITimeStamp timestamp = 0;
const ByteCount MESSAGELENGTH = 6;
Byte buffer[1024]; // storage space for MIDI Packets
MIDIPacketList *packetlist = (MIDIPacketList*)buffer;
MIDIPacket *currentpacket = MIDIPacketListInit(packetlist);
Byte msgs[MESSAGELENGTH] = {0xB0, 0x32, (Byte)posX, 0xB0, 0x33, (Byte)posY};
currentpacket = MIDIPacketListAdd(packetlist, sizeof(buffer),
currentpacket, timestamp, MESSAGELENGTH, msgs);
CheckError(MIDISend(_outputPort, _destinationEndpoint, packetlist), "Couldn't send MIDI packet list");
}
I adapted this code from testout.c found here

Resources