-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Forwarding of unknown messages in C library not supported #1092
Comments
@MaEtUgR You are 100% correct. The other key case here is that if you're forwarding over a network that already has its own packet checking the CRC test is redundant - e.g. IP networks. So you want the ability to not do the message integrity check, the message signing check, or the message supported check. Can you create a PR in ArduPilot/MAVLink for the C library that solves this problem? |
You mean https://github.com/ArduPilot/pymavlink right? To be honest that doesn't sound like peanuts to me because it looks easy to break functionality. I hoped there's a MAVLink expert who would be quicker. But I can try to convince myself to solve it. |
@MaEtUgR Yes, I mean https://github.com/ArduPilot/pymavlink There may be such a MAVLink expert, but from what I've seen, the only changes that happen in any kind of timely fashion are those that people PR themselves. Yes, this may not be easy. On further thinking:
|
But if you can't convince yourself to do this, I'd still post as an issue on https://github.com/ArduPilot/pymavlink |
@peterbarker I was wondering if you could offer advice on this. Essentially the question is "what is the best way to parse a message fully, ignoring any errors, so that you can forward it over another interface. This is needed so we can forward messages where the current library does not "understand" the message (not built to same dialect) and where it does not have the message signature. Ideally you would additionally like to be able to conditionally not-do the CRC check either, for example if routing over an IP network that does its own CRC. The easiest way to do this would be to have new method like mavlink_parse_char() that always returns the final message object even if there are parsing errors. I even think you could reasonably argue that this is how the method should be - though it is a break in behaviour because the current version assumes a bad signature or bad CRC are not successful decoding. I think you can just call MAVLINK_HELPER uint8_t mavlink_parse_char_new(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status)
{
uint8_t msg_received = mavlink_frame_char(chan, c, r_message, r_mavlink_status);
if (msg_received == MAVLINK_FRAMING_BAD_CRC ||
msg_received == MAVLINK_FRAMING_BAD_SIGNATURE) {
if (status->parse_state == MAVLINK_PARSE_STATE_IDLE) {
// we got a bad CRC or a bad signature AND the parser has returned back to idle, indicating that we have got the signature.
//Do we need to copy our final value - appears to happen in mavlink_frame_char_buffer.
// Probably should still copy the error
if (c == MAVLINK_STX)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
rxmsg->len = 0;
mavlink_start_checksum(rxmsg);
}
return 0;
}
}
return msg_received;
} Thoughts? |
MAVLink call: @hamishwillee has ideas for a solution and James needs to be mentioned. |
@auturgy Here is summary of problem statement and possible solutions for @tridge. The MAVLink specification states that:
The current MAVLink C library supports the first case (local processing) but not the second (forwarding). The reason is that:
What is needed is for compatible libraries to be able to:
Possible solution is:
It would be nice to be able to just rewrite |
OK, I had a discussion on this with @tridge. The summary of which is:
A solution is to buffer bytes since the last successful packet collected. In case of an error then callback with the current buffer (which may be forwarded) when the next STX is detected.
|
I think you guys forget about target sysid and compid :) |
@olliw42 I hadn't forgotten about these. If the message target is unknown (ie it can't be read because we don't understand the message) it can be assumed to be broadcast - and so should be forwarded on all interfaces. We could state that in the routing docs, but I think something people would reasonably assume. |
well, I couldn't I think it MUST be added! It's also a matter of exposing a logically consistent protocol. The conclusion of the forwarding of the unknowns then MUST be that essentially every piece of junk which starts with a STX is broadcasted to any other device. I'm not sure - and am not convinced - if that is what one would reasonably expect a protocol to do. I note that essentially any other protocol does this as expected, and one could have learned from the existing. So, it seems we at least agree in that MAVLink is not good at keeping the channels free of junk. :) |
@olliw42 Fair enough - if it is ambiguous or unclear it should be fixed. Done in mavlink/mavlink-devguide#179. Note that anyone can make fixes to the spec and we'll review.
If you don't do it this way then you need to ensure that every routing component is kept up to date with the latest version of the library, and it has to know every message type that you might want to send on the network in advance. That is quite a burden on users and manufacturers of MAVLink bridge components. Further, it is quite possible that other things are running on the same network and you might not want to swallow/clean up their packets either. The ESP8266 wifi bridge for example also forwards any packet it gets whether MAVLink or not. Yes, we can certainly learn from other protocols in many areas (e.g. discoverability and id allocation), but I'm not convinced that this particular case is one of them. |
Closing this in favor of #1166. |
I had this problem together with @simonegu and asked @julianoes about the matter and he mentioned it's totally worth an issue:
Problem
Forwarding messages without parsing the payload seems to be not supported by the mavlink C library.
There are always "dumb" components which are not interested in the payload of the message but only have the responsibility to forward messages to the correct destination comparable to a network router or hub. Examples for such components commonly used with MAVLink are:
These components are often not upgraded for every single change in the MAVLink payload definitions. I'm also speaking here for companies that might want to adjust their custom MAVLink definitions more frequently than the common ones and they are forced to update every single component that's only relaying for every new message.
Cause
You receive a char
c
from your UART driver, you call the parse char to process it and it will return framing ok when its state machine ended up with a CRC checked, known packet that is ready for decoding or resending.But when you're just resending the packet you don't care if the payload definition is known to the relaying component. You want to parse the MAVLink packet to know where it's supposed to go from the header and likely verify the data integrity with CRC to not forward any broken packets.
The part of the parsing that requires knowledge of the message definition is https://github.com/ArduPilot/pymavlink/blob/f92b861b34c06cbb2820709c5712ad4f4f01b350/generator/C/include_v2.0/mavlink_helpers.h#L714-L716
Solution?
The part that requires knowledge about the message definition is for the CRC_EXTRA calculation which is there to ensure that sender and receiver share the details of the message definition. Being able to check this property is useful but why is it not independent of the CRC? Isn't the CRC there to ensure the integrity of the packet and not the shared understanding about the payload definition.
If I read it correctly and the CRC check is bound to the payload definition could we at least add an option to parse a mavlink message worst case without the CRC check or known payload defintion to be able to just forward it?
The text was updated successfully, but these errors were encountered: