Closed berkowski closed 8 years ago
This is working as expected. The Micro-Modem treats the frames as the smallest atomic units, so the Goby MMDriver currently does as well. More concretely, you could get frames 1&2 but not 3 within a packet. All packetization must be handled at the application layer.
It wouldn't be hard to implement a configuration option for MMDriver to treat multiframe messages (say N frames of B bytes) as single frame messages (of size N*B) that are rejected if any of the frames are bad.
I wouldn't want this to be the only option, though. Especially with high rates it's not uncommon to get <N frames through (but not all of them bad).
Ah, ok. That makes sense though it seems to make things a bit awkward in practice.
The MACManager entries know about rates, and obviously the modem drivers do as well, but the QueueManager entries do not. How am I at the application level supposed to handle splitting a message up into frame-size chunks for pushing with QueueManager::push_message if I do not know what rates the MACManager entries have been configured for?
There's no one solution here, since you could be working with mixed rates (e.g. rate 1 and 3 alternating, where the former has 64 bytes frames and the latter has 256 byte frames). What I do is to target (i.e. at configuration time) the lowest MTU that I'll be using (in the above example, 64 bytes), and then queue will concatenate smaller packets to fill the 256 byte frame.
If you want to introspect on the frame sizes at runtime, you can attach a callback slot to the ModemDriverBase::signal_data_request signal:
At this point ModemTransmission will include max_num_frames() and max_frame_bytes(), where
max_num_frames() == 3 and max_frame_bytes() == 64 for rate 1 and max_num_frames() == 2 and max_frame_bytes() == 256 for rate 3
If you attach your application level callback slot before the QueueManager slot (e.g. using goby::acomms::bind), I would assume that you could push some messages during that callback that will then get added to the Queue priority contest and sent out.
Let me know if that doesn't make sense.
And if you have ideas on how to better handle this, let me know. Also keep in mind that if you want to have complete control over the data buffering and packetization, you may be best off not using Queue at all (and attaching your applications signals directly to those in ModemDriverBase).
I ended up going with the later there and wrote my own simple queue class that can interact with both the MMDriver and the MACManager. So far it's survived some testing on the dev box. I don't have a better way of handling it that wouldn't require some extensive changes to the existing QueueManager, and I don't really think that's the way to go for a whole host of reasons.
I thought about something similar to your suggestion of splitting based on the smallest frame size, but I didn't want to give up on ensuring that at some level a protobuf object doesn't get split across discrete modem packets. I'd lose that control by frame-chunking a protobuf message at the queueing stage with how QueueManager currently works.
Let me also take the time to thank you again for the continued help, explanations, and fixes!
I seem unable to split messages across frames for when using the MicroModem driver with a QueueManager/MACManager. This specific case uses a MAC slot w/ rate 1, which is a 192B packet split into 3 64B frames. The encoded message is 71 bytes and it gets refused because it is too big.
Here is the snippet where we see the message get pushed into the queue:
And here is the portion where goby tries to send it:
The rejection notice is from
goby/src/acomms/queue/queue.cpp
:I would expect messages to get rejected if they're too big to fit in a transmission packet, but you should be able to span frames without issues. Or am I misunderstanding something here?