Legal notice

Copyright (C) 2015-2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG)

License

This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

Version

This documentation was generated for version 3.5 of vSomeIP.

vSomeIP Overview

The vSomeIP stack implements the http://some-ip.com/[Scalable service-Oriented MiddlewarE over IP (SOME/IP)] protocol. The stack consists out of:

Build Instructions

Dependencies

Compilation

For compilation call:

mkdir build
cd build
cmake ..
make

To specify a installation directory (like --prefix= if you're used to autotools) call cmake like:

cmake -DCMAKE_INSTALL_PREFIX:PATH=$YOUR_PATH ..
make
make install

Compilation with predefined base path

To predefine the base path, the path that is used to create the local sockets, call cmake like:

cmake -DBASE_PATH=<YOUR BASE PATH> ..

The default base path is /tmp.

Compilation with predefined unicast and/or diagnosis address

To predefine the unicast address, call cmake like:

cmake -DUNICAST_ADDRESS=<YOUR IP ADDRESS> ..

To predefine the diagnosis address, call cmake like:

cmake -DDIAGNOSIS_ADDRESS=<YOUR DIAGNOSIS ADDRESS> ..

The diagnosis address is a single byte value.

Compilation with custom default configuration folder

To change the default configuration folder, call cmake like:

cmake -DDEFAULT_CONFIGURATION_FOLDER=<DEFAULT CONFIGURATION FOLDER> ..

The default configuration folder is /etc/vsomeip.

Compilation with custom default configuration file

To change the default configuration file, call cmake like:

cmake -DDEFAULT_CONFIGURATION_FILE=<DEFAULT CONFIGURATION FILE> ..

The default configuration file is /etc/vsomeip.json.

Compilation with changed (maximimum) wait times for local TCP ports

If local communication is done via TCP, we depend on the availability of the network. Therefore, server port creation and therefore port assignment might fail. If the failure is causes by the port already being in use, we use the next available port. For all other failure, we wait for a wait time until we retry with the same port. If the overall wait time of all retries exceeds the maximum wait time, the endpoint creation is aborted. To configure wait time and maximum wait time, call cmake with:

cmake -DLOCAL_TCP_PORT_WAIT_TIME=50 -DLOCAL_TCP_PORT_MAX_WAIT_TIME=2000 ..

The default values are a wait time of 100ms and a maximum wait time of 10000ms. These configurations have no effect if local communication uses UDS (default).

Compilation with signal handling

To compile vsomeip with signal handling (SIGINT/SIGTERM) enabled, call cmake like:

cmake -DENABLE_SIGNAL_HANDLING=1 ..

In the default setting, the application has to take care of shutting down vsomeip in case these signals are received.

Compilation with user defined "READY" message

To compile vsomeip with a user defined message signal the IP routing to be ready to send/receive messages, call cmake like:

cmake -DROUTING_READY_MESSAGE=<YOUR MESSAGE> ..

Compilation with vSomeIP 2 compatibility layer

To compile vsomeip with enabled vSomeIP 2 compatibility layer, call cmake like:

cmake -DENABLE_COMPAT=1 ..

Compilation of examples

For compilation of the examples call:

mkdir build
cd build
cmake ..
make examples

Compilation of tests

To compile the tests, first unzip gtest to location of your desire. Some of the tests require a second node on the same network. There are two cmake variables which are used to automatically adapt the json files to the used network setup:

If one of this variables isn't specified, only the tests using local communication exclusively will be runnable.

Additionally the unit tests require enabled signal handling which can be enabled via the ENABLE_SIGNAL_HANDLING cmake variable.

Example, compilation of tests:

mkdir build
cd build
export GTEST_ROOT=$PATH_TO_GTEST/gtest-1.7.0/
cmake -DENABLE_SIGNAL_HANDLING=1 -DTEST_IP_MASTER=10.0.3.1 -DTEST_IP_SLAVE=10.0.3.125 ..
make check

Additional make targets for the tests:

For development purposes two cmake variables exist which control if the json files and test scripts are copied (default) or symlinked into the build directory. These settings are ignored on Windows.

Example cmake call:

cmake  -DTEST_SYMLINK_CONFIG_FILES=ON -DTEST_SYMLINK_CONFIG_FILES_RELATIVE=ON ..

For compilation of only a subset of tests (for a quick functionality check) the cmake variable TESTS_BAT has to be set:

Example cmake call:

cmake  -DTESTS_BAT=ON ..

Compilation of vsomeip_ctrl

For compilation of the vsomeip_ctrl utility call:

mkdir build
cd build
cmake ..
make vsomeip_ctrl

Generating the documentation

To generate the documentation call cmake as described in Compilation and then call make doc. This will generate:

Starting vsomeip Applications / Used environment variables

On startup the following environment variables are read out:

NOTE: If the file/folder that is configured by VSOMEIP_CONFIGURATION does not exist, the default configuration locations will be used.

NOTE: vsomeip will parse and use the configuration from all files in a configuration folder but will not consider directories within the configuration folder.

In the following example the application my_vsomeip_application is started. The settings are read from the file my_settings.json in the current working directory. The client id for the application can be found under the name my_vsomeip_client in the configuration file.

#!/bin/bash
export VSOMEIP_APPLICATION_NAME=my_vsomeip_client
export VSOMEIP_CONFIGURATION=my_settings.json
./my_vsomeip_application

Configuration File Structure

The configuration files for vsomeip are JSON-Files and are composed out of multiple key value pairs and arrays.

Configuration file element explanation:

...
"suppress_missing_event_logs" :
[
    {
        "service" : "0x0023",
        "instance" : "0x0001",
        "events" : [ "0x8001", "0x8002",
                    {
                        "first" : "0x8010",
                        "last" : "0x801f"
                    },
                    "0x8020" ]
    },
    {
        "service" : "0x0023",
        "instance" : "0x0002",
        "events" : [ "0x8005", "0x8006" ]
    },
    {
        "service" : "0x0023",
        "instance" : "0x0002",
        "events" : [ "0x8105", "0x8106" ]
    },
    {
        // no "events" --> ignore all(!) events of these services
        "service" : "any",
        "instance" : "0x00f2"
    },
    {
        "service" : "0x0102",
        "instance" : "any",
        "events" : [ "0x8005", "0x8006" ]
    }
]

Security

vsomeip has a security implementation based on UNIX credentials. If activated every local connection is authenticated during connect using the standard UNIX credential passing mechanism. During authentication a client transfers its client identifier together with its credentials (UID / GID) to the server which is then matched against the configuration. If received credentials don't match the policy the socket will be immediately closed by the server and an message is logged. If accepted the client identifier is bound to the receiving socket and can therefore be used to do further security checks on incoming messages (vsomeip messages as well as internal commands).

In general clients can be configured to be allowed/denied to request (means communicate with) and offer different service instances. Every incoming vsomeip message (request/response/notification) as well as offer service requests or local subscriptions are then checked against the policy. If an incoming vsomeip message or another operation (e.g. offer/subscribe) violates the configured policies it is skipped and a message is logged.

Furthermore if an application receives informations about other clients/services in the system, it must be received from the authenticated routing manager. This is to avoid malicious applications faking the routing manager and therefore being able to wrongly inform other clients about services running on the system. Therefore, whenever the "security" tag is specified, the routing manager (e.g. routingmanagerd/vsomeipd) must be a configured application with a fixed client identifier. See chapter "Configuration File Structure" on how to configure an application to use a specific client identifier.

Credential passing is only possible via Unix-Domain-Sockets and therefore only available for local communication. However if security is activated method calls from remote clients to local services are checked as well which means remote clients needs to be explicitly allowed. Such a policy looks same in case for local clients except the credentials tag can be skipped.

Security configuration

The available configuration switches for the security feature are:


Security configuration example

...
"security" :
{
    ...
    "policies" :
    [
        {
            ...
            "credentials" :
            {
                "uid" : "44",
                "gid" : "any"
             },
             "allow" :
             [
                 "requests" :
                 [
                     {
                         "service" : "0x6731",
                         "instance" : "0x0001"
                     }
                 ]
             ]
         },
         {
            "credentials" :
            {
                "deny" :
                [
                    {
                        "uid" : [ "1000", { "first" : "1002", "last" : "max" }],
                        "gid" : [ "0", { "first" : "100", "last" : "243" }, "300"]
                    },
                    {
                        "uid" : ["55"],
                        "gid" : ["55"]
                    }
                 ]
             },
             "allow" :
             [
                 "offers" :
                 [
                     {
                        "service" : "0x6728",
                        "instances" : [ "0x0001", { "first" : "0x0003", "last" : "0x0007" }, "0x0009"]
                     },
                     {
                        "service" : "0x6729",
                        "instances" : ["0x88"]
                     },
                     {
                        "service" : "0x6730",
                        "instance" : "any"
                     }
                 ],
                 "requests" :
                 [
                     {
                         "service" : "0x6732",
                         "instances" :
                         [
                             {
                                 "ids" : [ "0x0001", { "first" : "0x0003", "last" : "0x0007" }],
                                 "methods" : [ "0x0001", "0x0003", { "first" : "0x8001", "last" : "0x8006" } ]
                             },
                             {
                                 "ids" : [ "0x0009" ],
                                 "methods" : "any"
                             }
                         ]
                     },
                     {
                        "service" : "0x6733",
                        "instance" : "0x1"
                     },
                     {
                        "service" : "0x6733",
                        "instances" : [ "0x0002", { "first" : "0x0003", "last" : "0x0007" }, "0x0009"]
                     }
                 ]
             ]
         }
     ]
}

The config/ folder contains some addition vsomeip configuration files to run the vsomeip examples with activated security checks. Additionally there's a security test in the test/ subfolder which can be used for further reference. + They give a basic overview how to use the security related configuration tags described in this chapter to run a simple request/response or subscribe/notify example locally or remotely.

Security policy extensions

vsomeip policy extension configuration supports the definition of paths that contain additional security policies to be loaded whenever a client with a yet unknown hostname connects to a local server endpoint. The following configuration parameters are available and can be defined in a file named vsomeip_policy_extensions.json.

Audit Mode

vsomeip's security implementation can be put in a so called 'Audit Mode' where all security violations will be logged but allowed. This mode can be used to build a security configuration.

To activate the 'Audit Mode' the 'security' object has to be included in the json file but the 'check_credentials' switch has to be set to false. For example:

    [...]
    "services" :
    [
        [...]
    ],
    "security" :
    {
        "check_credentials" : "false"
    },
    "routing" : "service-sample",
    [...]

Autoconfiguration

vsomeip supports the automatic configuration of client identifiers and the routing. The first application that starts using vsomeip will automatically become the routing manager if it is not explicitly configured. The client identifiers are generated from the diagnosis address that can be specified by defining DIAGNOSIS_ADDRESS when compiling vsomeip. vsomeip will use the diagnosis address as the high byte and enumerate the connecting applications within the low byte of the client identifier.

Autoconfiguration of client identifiers isn't meant to be used together with vsomeip Security. Every client running locally needs to have at least its own credentials configured when security is activated to ensure the credential checks can pass. Practically that means if a client requests its identifier over the autoconfiguration for which no credentials are configured (at least it isn't known which client identifier is used beforehand) it is impossible for that client to establish a connection to a server endpoint. However if the credentials for all clients are same it's possible to configure them for the overall (or DIAGNOSIS_ADDRESS) client identifier range to mix autoconfiguration together with activated security.

routingmanagerd

The routingmanagerd is a minimal vsomeip application intended to offer routing manager functionality on a node where one system wide configuration file is present. It can be found in the examples folder.

Example: Starting the daemon on a system where the system wide configuration is stored under /etc/vsomeip.json:

VSOMEIP_CONFIGURATION=/etc/vsomeip.json ./routingmanagerd

When using the daemon it should be ensured that:

vsomeip Hello World

In this paragraph a Hello World program consisting out of a client and a service is developed. The client sends a message containing a string to the service. The service appends the received string to the string Hello and sends it back to the client. Upon receiving a response from the service the client prints the payload of the response ("Hello World"). This example is intended to be run on the same host.

All files listed here are contained in the examples\hello_world subdirectory.

Build instructions

The example can build with its own CMakeFile, please compile the vsomeip stack before hand as described in Compilation. Then compile the example starting from the repository root directory as followed:

cd examples/hello_world
mkdir build
cd build
cmake ..
make

Starting and expected output

Starting and expected output of service

$ VSOMEIP_CONFIGURATION=../helloworld-local.json \
  VSOMEIP_APPLICATION_NAME=hello_world_service \
  ./hello_world_service
2015-04-01 11:31:13.248437 [info] Using configuration file: ../helloworld-local.json
2015-04-01 11:31:13.248766 [debug] Routing endpoint at /tmp/vsomeip-0
2015-04-01 11:31:13.248913 [info] Service Discovery disabled. Using static routing information.
2015-04-01 11:31:13.248979 [debug] Application(hello_world_service, 4444) is initialized.
2015-04-01 11:31:22.705010 [debug] Application/Client 5555 got registered!

Starting and expected output of client

$ VSOMEIP_CONFIGURATION=../helloworld-local.json \
  VSOMEIP_APPLICATION_NAME=hello_world_client \
  ./hello_world_client
2015-04-01 11:31:22.704166 [info] Using configuration file: ../helloworld-local.json
2015-04-01 11:31:22.704417 [debug] Connecting to [0] at /tmp/vsomeip-0
2015-04-01 11:31:22.704630 [debug] Listening at /tmp/vsomeip-5555
2015-04-01 11:31:22.704680 [debug] Application(hello_world_client, 5555) is initialized.
Sending: World
Received: Hello World

CMakeFile

examples/hello_world/CMakeLists.txt

Configuration File For Client and Service

examples/hello_world/helloworld-local.json

Service

examples/hello_world/hello_world_service_main.cpp

The service example results in the following program execution:

Main

  1. main()

    First the application is initialized. After the initialization is finished the application is started.

Initialization

  1. init()

    The initialization contains the registration of a message handler and an event handler.

    The message handler declares a callback (on_message_cbk) for messages that are sent to the specific service (specifying the service id, the service instance id and the service method id).

    The event handler declares a callback (on_event_cbk) for events that occur. One event can be the successful registration of the application at the runtime.

Start

  1. start()

    The application will be started. This function only returns when the application will be stopped.

Callbacks

  1. on_state_cbk()

    This function is called by the application when an state change occurred. If the application was successfully registered at the runtime then the specific service is offered.

  2. on_message_cbk()

    This function is called when a message/request from a client for the specified service was received.

    First a response based upon the request is created. Afterwards the string 'Hello' will be concatenated with the payload of the client's request. After that the payload of the response is created. The payload data is set with the previously concatenated string. Finally the response is sent back to the client and the application is stopped.

Stop

  1. stop()

    This function stops offering the service, unregister the message and the event handler and shuts down the application.

Client

examples/hello_world/hello_world_client_main.cpp

The client example results in the following program execution:

Main

  1. main()

    First the application is initialized. After the initialization is finished the application is started.

Initialization

  1. init()

    The initialization contains the registration of a message handler, an event handler and an availability handler.

    The event handler declares again a callback (on_state_cbk) for state changes that occur.

    The message handler declares a callback (on_message_cbk) for messages that are received from any service, any service instance and any method.

    The availability handler declares a callback (on_availability_cbk) which is called when the specific service is available (specifying the service id and the service instance id).

Start

  1. start()

    The application will be started. This function only returns when the application will be stopped.

Callbacks

  1. on_state_cbk()

    This function is called by the application when an state change occurred. If the application was successfully registered at the runtime then the specific service is requested.

  2. on_availability_cbk()

    This function is called when the requested service is available or no longer available.

    First there is a check if the change of the availability is related to the 'hello world service' and the availability changed to true. If the check is successful a service request is created and the appropriate service information are set (service id, service instance id, service method id). After that the payload of the request is created. The data of the payload is 'World' and will be set afterwards. Finally the request is sent to the service.

  3. on_message_cbk()

    This function is called when a message/response was received. If the response is from the requested service, of type 'RESPONSE' and the return code is 'OK' then the payload of the response is printed. Finally the application is stopped.

Stop

  1. stop()

This function unregister the event and the message handler and shuts down the application.

Trace Connector

Overview/Prerequisites

The Trace Connector is used to forward the internal messages that are sent over the Unix Domain Sockets to DLT. + Thus, it requires that DLT is installed and the DLT module can be found in the context of CMake.

Configuration

Static Configuration

The Trace Connector can be configured statically over the tracing point of the Configuration File Structure

Example 1 (Minimal Configuration)

{
    ...

    "tracing" :
    {
        "enable" : "true"
    },

    ...

This is the minimal configuration of the Trace Connector. This just enables the tracing and all of the sent internal messages will be traced/forwarded to DLT.

Example 2 (Using Filters)

{
    ...

    "tracing" :
    {
        "enable" : "true",
        "channels" :
        [
            {
                "name" : "My channel",
                "id" : "MC"
            }
        ],
        "filters" : [
            {
                "channel" : "MC",
                "matches" : [ { "service" : "0x1234", "instance" : "any", "method" : "0x80e8" } ],
                "type" : "positive"
            }
        ]
    },

    ...

As it is a positive filter, the example filter ensures that only messages representing method '0x80e8' from instances of service '0x1234' will be forwarded to the DLT. If it was specified as a negative filter, all messages except messages representing method '0x80e8' from instances of service '0x1234' would be forwarded to the DLT.

The general filter rules are:

Dynamic Configuration

The Trace Connector can also be configured dynamically over its interfaces. You need to include '<vsomeip/trace.hpp>' to access its public interface.

Example:

    // get trace connector
    std::shared_ptr<vsomeip::trace::connector> its_connector
    = vsomeip::trace::connector::get();

    // add channel
    std::shared_ptr<vsomeip::trace::channel> its_channel
    = its_connector->create_channel("MC", "My channel");

    // add filter rule
    vsomeip::trace::match_t its_match
        = std::make_tuple(0x1234, 0xffff, 0x80e8);
    vsomeip::trace::filter_id_t its_filter_id
    = its_channel->add_filter(its_match, true);

    // init trace connector
    its_connector->init();

    // enable trace connector
    its_connector->set_enabled(true);

    // remove the filter
    its_channel->remove_filter(its_filter_id);

vsomeip nPDU feature

This is the add-on documentation for the nPDU feature, aka. Zugverfahren.

The nPDU feature can be used to reduce network load as it enables the vsomeip stack to combine multiple vsomeip messages in one single ethernet frame.

Some general important things regarding the nPDU feature first:

Configuration

There are two parameters specific for the nPDU feature:

For more information please see the corresponding requirement documents.

The nPDU feature specific settings are configured in the json file in the "services" section on service level in a special debounce-times section:

[...]
"services":
[
    {
        "service":"0x1000",
        "instance":"0x0001",
        "unreliable":"30509",
        "debounce-times":
        {
            // nPDU feature configuration for this
            // service here
        }
    }
],
[...]

Additionally nPDU default timings can be configured globally.

The global default timings can be overwritten via the npdu-default-timings json object. For example the following configuration snippet shows how to set all default timings to zero:

{
    "unicast":"192.168.1.9",
    [...]
    "npdu-default-timings" : {
        "debounce-time-request" : "0",
        "debounce-time-response" : "0",
        "max-retention-time-request" : "0",
        "max-retention-time-response" : "0"
    },
    "routing":"[...]",
    "service-discovery": { [...] }
}

Example 1: One service with one method offered over UDP

Service side

{
    "unicast":"192.168.1.9",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x0001",
            "unreliable":"30509",
            "debounce-times":
            {
                "responses": {
                    "0x1001" : {
                        "debounce-time":"10",
                        "maximum-retention-time":"100"
                    }
                }
            }
        }
    ],
    "routing":"[...]",
    "service-discovery": { [...] }
}

Client side

{
    "unicast":"192.168.1.77",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x0001",
            "unicast":"192.168.1.9", // required to mark service as external
            "unreliable":"30509",
            "debounce-times":
            {
                "requests": {
                    "0x1001" : {
                        "debounce-time":"20",
                        "maximum-retention-time":"200"
                    }
                }
            }
        }
    ],
    "routing":"[...]",
    "service-discovery": { [...] }
}

Example 2: One service with two methods offered over UDP

Service side

{
    "unicast":"192.168.1.9",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x0001",
            "unreliable":"30509",
            "debounce-times":
            {
                "responses": {
                    "0x1001" : {
                        "debounce-time":"10",
                        "maximum-retention-time":"100"
                    },
                    "0x1002" : {
                        "debounce-time":"20",
                        "maximum-retention-time":"200"
                    }
                }
            }
        }
    ],
    "routing":"[...]",
    "service-discovery": { [...] }
}

Client side

{
    "unicast":"192.168.1.77",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x0001",
            "unicast":"192.168.1.9", // required to mark service as external
            "unreliable":"30509",
            "debounce-times":
            {
                "requests": {
                    "0x1001" : {
                        "debounce-time":"20",
                        "maximum-retention-time":"200"
                    },
                    "0x1002" : {
                        "debounce-time":"40",
                        "maximum-retention-time":"400"
                    }
                }
            }
        }
    ],
    "routing":"[...]",
    "service-discovery": { [...] }
}

Example 3: One service with one method offered over UDP and TCP

Service side

{
    "unicast":"192.168.1.9",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x0001",
            "unreliable":"30509",
            "reliable":
            {
                "port":"30510",
                "enable-magic-cookies":"false"
            },
            "debounce-times":
            {
                "responses": {
                    "0x1001" : {
                        "debounce-time":"10",
                        "maximum-retention-time":"100",
                    }
                }
            }
        }
    ],
    "routing":"[...]",
    "service-discovery": { [...] }
}

Client side

{
    "unicast":"192.168.1.77",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x0001",
            "unicast":"192.168.1.9", // required to mark service as external
            "unreliable":"30509",
            "reliable":
            {
                "port":"30510",
                "enable-magic-cookies":"false"
            },
            "debounce-times":
            {
                "requests": {
                    "0x1001" : {
                        "debounce-time":"20",
                        "maximum-retention-time":"200",
                    }
                }
            }
        }
    ],
    "routing":"[...]",
    "service-discovery": { [...] }
}

SOME/IP TP

With SOME/IP Transport Protocol (TP) it is possible to transport messages which exceed the UDP payload size limit of 1400 byte. If enabled the message is segmented and send in multiple UDP datagrams.

Example configuration:

Configuration service side:

{
    "unicast":"192.168.0.1",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x1",
            "unreliable":"40000",
            "someip-tp": {
                "service-to-client": [
                    "0x1", "0x2", "0x8001"
                ]
            }
        }
    ],
    "max-payload-size-unreliable" : "5000",
    "routing":"[...]",
    "service-discovery": { [...] }
}

Configuration client side:

{
    "unicast":"192.168.0.100",
    "logging": { [...] },
    "applications": [ [...] ],
    "services":
    [
        {
            "service":"0x1000",
            "instance":"0x1",
            "unicast":"192.168.0.1", // required to mark service as external
            "unreliable":"40000", // required to mark service as external
            "someip-tp": {
                "client-to-service": [
                    "0x1", "0x2"
                ]
            }
        }
    ],
    "routing":"[...]",
    "service-discovery": { [...] }
}

Tools

vsomeip_ctrl

vsomeip_ctrl is a small utility which can be used to send SOME/IP messages from the commandline. If a response arrives within 5 seconds the response will be printed.

Example: Calling method with method id 0x80e8 on service with service id 0x1234, instance id 0x5678:

./vsomeip_ctrl --instance 5678 --message 123480e800000015134300030100000000000009efbbbf576f726c6400

Example: Sending a message to service with service id 0x1234, instance id 0x5678 and method id 0x0bb8 via TCP

./vsomeip_ctrl --tcp --instance 5678 --message 12340bb8000000081344000101010000