The RSOMEIP takeover plan #5
Replies: 5 comments
-
Thanks for the contribution, @vvcarvalho! You make a lot of interesting points, and I'm keen to discuss them with you once I've had a better look. |
Beta Was this translation helpful? Give feedback.
-
I've had a look now, and I'll try to address these points in the same order that you did. Some of them I omitted because I 100% agree, and don't feel the need to repeat them, but please let me know if I missed something. I'll also preface this by saying that while I agree with the potential for rsomeip to become an effective substitute for vsomeip, this is not my main objective with this project. My goal is simply to implement the SOME/IP protocol (including SOME/IP-SD, SOME/IP-TP, SOME/IP-E2E, etc.) in Rust, and the vsomeip/C++ compatibility is just for extra credit. This is not to say that I don't want these things for rsomeip, it's just that they are not my main priority.
I'll also add maintainability to this list. I think this will be important for ensuring the longevity of the project.
This is my mindset going into to this project. I always assume that the other application is not rsomeip, and the only way to communicate is by correctly implementing the SOME/IP spec. As long as both applications achieve this, compatibility is assured.
I'm not sure how feasible it is to incorporate vsomeip in to the testing architecture, but at least some examples could be made that mirror vsomeips, and which could be used interchangeably for demonstration proposes.
I don't know enough about Rust/C++ interoperability to say if this is possible with the architecture that I have in mind for rsomeip, or how costly it would be to develop and maintain. This is a point I feel will require much more discussion. When it comes to the interoperability between rsomeip and the CommonAPI/vsomeip stack, I would prefer to keep as much of it to the SOME/IP protocol as possible, followed by some implementation of the vsomeip protocol, and only then some sort of Rust/C++ bridge. But, as long as there is enough interest, there should be a way of making this possible.
Yes to the extensibility through a well defined API. For the C/C++ interop, see my previous point.
This would be great for the maintainability of the project. If you know of a way to more concretely link these requirements to specific parts of the code, please let me know.
I'm already working on a way to generate code coverage reports on PRs here on Github, and also to generate lints, format code, etc. Currently, I don't have a clearly defined testing strategy, so this is something that could definitely be improved. Also, you mention including benchmarks in the testing strategy, but from what I read on the subject, this is not something that makes sense with Github's CI. This would be great to have, but I don't know if it's possible.
Don't know enough about Ferrocene either, but since SOME/IP was designed with infotainment systems in mind, I don't know how useful it would be in safety critical environments.
I don't know of any DLT lib in Rust, so I think we would need to implement one ourselves.
I feel that this is something Rust is particularly good at, and is one of the selling points for using it over C++.
I think this will be very important in terms of usability of rsomeip. That's it. Let me know if you want me to clarify anything, or if there is something else you which to discuss, and thanks again for the contribution! Also, this is just me being a little pedantic, but I prefer using |
Beta Was this translation helpful? Give feedback.
-
Responses
It's my understanding that
I like the idea of using it in some examples. But my point was more to extract live data from, say, a vsomeip client or server and see how well it plays out with an Regarding the C++ and Rust bridge. It isn't that much of hassle honestly. If it is thought at from the start I mean :)
No better way than to track in a table and link it to the code 😆
True. The thing with Ferrocene is we could make a CI job with it as a target to support the correctness of the library in such environments were anyone use it for such purposes and in such environments.
Yes. But the DLT library is small as well. I could take care of it. SegueHope that clarifies some of my points. Now, I wanted to run onto you what you had in mind for the architecture? |
Beta Was this translation helpful? Give feedback.
-
Architecture
The rsomeip architecture is a work in progress. I have a general idea of what I want it to look like, but it's something that I'm figuring out as I go along. So take what I'm about to write with a grain of salt, since this can all change in the future. The overall structure of rsomeip is divided into several layers, where each one represents a step in manipulating data from its raw network representation to the service-oriented idioms that the user sees, and vice-versa. The goal is to minimize coupling and improve extensibility through well defined layers and interfaces. I have three layers in mind: the Socket layer, the Endpoint layer, and the Service layer. Socket LayerThis layer implements the underlying network protocol used by SOME/IP. It's responsible sending and receiving raw data, and forwarding it to the Endpoints layer above. In the Endpoint LayerThis layer implements most of the SOME/IP protocol itself, converting between raw data and SOME/IP primitives, and forwarding these to the correct place in the Service layer above. I'm currently working on this layer in the Service LayerThis layers abstract the SOME/IP primitives into service oriented idioms, like servers, clients and proxies. It will use code generation to make these as concrete as possible. This is the next logical step after implementing the Endpoint layer. RuntimeThe runtime is what brings all of the layers together. It manages the creation, configuration, and lifetime of each component in the layer, and allows extending each layer with plugins. ExamplePerhaps, it's easier to give a pseudo-code example of how this would look like from a user perspective, especially of the last couple of layers. // Use `rsomeip::service` and `rsomeip::method` to generate
// service definitions.
#[rsomeip::service(id=0xaaaa, major=0, minor=1)]
trait HelloWorld {
#[rsomeip::method(id=0x0001)]
fn greet(name: String) -> String
}
struct HelloWorldStub;
// The service interface needs to be implemented by the user,
// but the client is auto-generated.
impl HelloWorldService for HelloWorldStub {
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
}
#[tokio::main]
async fn server() {
// The runtime can be configured with the Builder pattern.
let runtime =
rsomeip::Runtime::build()
.with_sd(true)
.with_vsomeip(true)
.with(MyAwesomePlugin::new())
.get();
// The runtime will take care of serving the service to the clients.
runtime.offer(0xaaaa, "127.0.0.1:8080:tcp").unwrap();
runtime.serve(HelloWorldStub::new(), 0x1111);
tokio::thread::sleep(Duration::from_secs(60)).await;
}
#[tokio::main]
async fn client() {
// The runtime can also be configured from a file.
let runtime = rsomeip::Runtime::configure("rsomeip.toml").get();
// The runtime will setup the proxy to interact with the server.
let proxy = runtime
.proxy(0xaaaa, 0x1111)
.and_then(HelloWorldProxy::try_from)
.unwrap();
proxy.available().await;
// The HelloWorldProxy is auto-generated. It converts method calls of the
// service interface into SOME/IP requests.
let greeting = proxy.greet("rsomeip").await.unwrap();
assert_eq!(&greeting, "Hello, rsomeip!");
} DLT
Regarding dlt, I'm planning on using the tracing library to generate logs. If you could make a dlt implementation that is compatible with it, that would be great! |
Beta Was this translation helpful? Give feedback.
-
Wall of textI've got a generic approach in mind that we could mix with your layered approach. Generally, I think the grand issue with implementing SOME/IP is separating the socket layer from the endpoint and service layer. From a user of the library POV, I believe that it is beneficial to understand what is the typical usage of the library: static configuration of the network topology in terms of the services in a local system and means of communication to other systems that implement the protocol through service discovery. With that perspective, I believe that the endpoint and service layer could be "joined" into a per-service pipeline object. Example:
Given that, for each service, we can have a bunch of configurable values that alter the execution, why not make it such that these things are baked into a single object instead of littered through the codebase? The benefits of reproduction are immense, and each step could have a simple, testable failure mode that either is propagated to the network or logs the error. Each pipeline object has fixed steps, such as serialization, and hooks and entrypoints. Rust has HOF, let's use it. Furthermore, one aspect to introduce concurrency is obviously to pick a central data structure, henceforth called container, that encapsulates per-service information into a single object. So as to not introduce unnecessary locks, I propose such data structure provide per-service/endpoint granularity of locks. And that ownership of those items use Rust's ownership semantics so as to avoid copying. In this model, worker thread A receives a process message for service Also, the async runtime interaction should probably only take care of few things: send and receive operations and timers. Make it as simple as possible. Then, processing of the messages are done with worker threads, that communicate via the async runtime through queue(s) of priority by work stealing. The benefit is that we can have these worker threads follow different, configurable algorithms, if necessary. We can have configurable send strategies per socket, like batch size, intervals and whatnot. To illustrate: the SOME/IP router receives a message, it checks for the SOME/IP header to determine which endpoint it belongs. The pipeline object associated with that endpoint is acquired and then each function pointer used in that is processed. Akin to (pseudocode):
The pipeline then is a series of fallible functions that, if done to completion, produce a response that is queued to the socket layer. The socket layer can be an abstraction upon the async runtime (if we use traits), and the processing from start to finish is encapsulated into an pipeline object. Regarding Thanks for reading the info dump :) but to summarize, I think following this approach allows us to have configurable pipelines, worker and async runtime while having modularity as one of the core -ilities of the lib. |
Beta Was this translation helpful? Give feedback.
-
To ensure RSOMEIP can effectively compete with or potentially replace vsomeip, we must focus on several core areas. I'm going to info dump what is on my mind here and we can talk what points are achievable and lay the ground work on the others.
The implementation should prioritize compatibility, configurability, extensibility, and performance. Below are the key attributes and improvements needed:
Points
Binary Compatibility
We should ensure message compatibility at the network layer and not assume the receiving implementation is a rsomeip. This addresses interoperability between RSOMEIP and vsomeip implementations. To do this, we can, for example, run the network tests in vsomeip and create a PCAP and simply inject those messages into our im
Interface Compatibility
Create a C++ bridge that upholds the same interface as vsomeip (mostly application and runtime interfaces). This way, Common API layers can utilize RSOMEIP as the underlying implementation. There is rust-cxx bridge that autogenerates a lot of things for us which could help.
Asynchronous I/O loop and network protocols
I think the choice for
tokio
is pretty good. With it, we have support for unix domain sockets, tcp and udp. I'm not sure which is better for an implementation: the tokio runtime ormio
but either choice is solid. I think going lower-level will only result in a net benefit if the performance of the runtime does not fit our requirements.Plugin and Extensibility
application_impl.hpp
interface. Plus, we have the ability to support runtime-loadable modules for a lot of the functionality. Service discovery, someip-tp, etc.SOME/IP Requirements Mapping
Points for Improvement
Socket Endpoint Reliability
Testability
Performance
Standards compliance
Architecture
Implementing these features and improvements in RSOMEIP, with a strong focus on quality attributes related to software engineering, will establish a solid foundation for RSOMEIP to be a competitive alternative to vsomeip.
Beta Was this translation helpful? Give feedback.
All reactions