精华内容
下载资源
问答
  • 2_SOMEIP 报文_消息头
    2021-03-10 19:37:50

    协议规范

    SOME/IP在网络上提供面向服务的通信。一个服务可以由0个或多个事件、方法和字段组成。

    事件提供周期性发送的数据,或者是服务器数据发生改变时发送给订阅者的数据。

    方法为订阅者提供了在程序端执行远程过程调用的可能性。

    字段是下列三个中的一个或多个的组合:

    • 一个notifier,它将数据从提供者发送到订阅者
    • 一个getter,订阅者可以调用它来显式地查询提供者的值
    • 一个setter,当订阅方想要更改提供者的值时,可以调用它

    字段的notifier和事件(event)的主要区别在于,事件只在变化时发送,字段的notifier在订阅后直接发送数据。

    协议格式(序列化)

    序列化描述数据在协议数据单元(pdu)中表示的方式,作为UDP或TCP消息的有效负载,在基于ip的汽车车载网络上传输。

    限制

    不支持对SOME/IP消息的乱序段进行重新排序。

    消息头

    [PRS_SOMEIP_00030] Header 布局包括:

    • Message ID (Service ID/Method ID) [32 Bits]
    • Length [32 Bits] 长度包含:Request ID 及以后的字段的字节数
    • Request ID (Client ID/Session ID) [32 Bits]
    • Protocol Version [8Bits]
    • Interface Version [8 Bits]
    • Message Type [8 Bits]
    • Return Code [8 Bits]

    消息头接下来就是Payload 数据了。

    在应用端到端(E2E)通信保护的情况下,端到端报头(E2E header)被放置在返回代码Return Code之后,这取决于端到端报头所选择的偏移值。缺省偏移值是64位,将端到端报头置于返回代码和有效负载之间。

    [PRS_SOMEIP_00031] 出于互操作性的原因,头部布局对于SOME/IP的所有实现应该是相同的。字段按传输顺序排列,即左上角的字段先传输。

    Message ID (32bit)

    [PRS_SOMEIP_00034] Messagge ID应该是一个32位的标识符,用于识别:

    • 对某个应用的一个方法的远程过程调用(RPC)
    • 特定的Event

    NOTE:Message ID的分配由用户/系统设计人员决定。然而,消息ID对于整个系统(即车辆)是唯一的。

    Method ID [15 Bit]

    Method ID 如下表所示:

    字段字段字段
    service ID (16bit)0 (1bit)Method ID (15bit)

    Event ID [15bit]

    Event ID 如下表所示:

    字段字段字段
    service ID (16bit)1 (1bit)Event ID (15bit)

    Eventgroup是服务中字段事件和通知事件的逻辑分组,以便允许订阅。
    [PRS_SOMEIP_00365]空的事件组不能被使用。
    [PRS_SOMEIP_00366]事件和字段通知至少映射到一个Eventgroup

    Length [32 Bit]

    [PRS_SOMEIP_00042]Length字段应该包含从Request ID/Session ID开始直到SOME/IP消息结束的字节长度

    Request ID [32 Bit]

    请求ID允许提供者和订阅者区分同一方法、事件、getter或setter的多个并行使用。

    [PRS_SOMEIP_00043] 请求ID对于提供者和订阅者组合是唯一的。

    [PRS_SOMEIP_00704] 在生成响应消息时,提供者应将请求ID从请求复制到响应消息。 Note:这允许订阅者将响应映射到已发出的请求,即使有多个未完成的请求。

    [PRS_SOMEIP_00044] 在响应到达或预计不会再到达之前(超时),不能重用请求ID。

    [PRS_SOMEIP_00046]请求ID的结构:

    字段字段
    Client ID (16bit)Session ID(16bit)

    NOTE:这意味着ECU的实现者可以根据其实现的要求定义client ID,而提供者不需要知道这个布局或定义,因为他只在响应中复制完整的请求ID.

    [PRS_SOMEIP_00702] 客户端ID是ECU中调用客户端的唯一标识符。客户端ID允许ECU将多个客户端对同一方法的调用区分开来。

    [PRS_SOMEIP_00703] 会话ID是唯一的标识符,用于区分来自相同发送方的顺序消息或请求。

    [PRS_SOMEIP_00532] 客户端ID还应支持通过具有可配置的前缀或固定值在整个车辆中是唯一的(例如,客户端ID的最重要字节是诊断地址或应用程序(SW-C)配置的客户端ID)。

    例如:

    字段字段字段
    client ID prefix(8bit)client ID(8bit)Session ID(16bit)

    [PRS_SOMEIP_00932] 如果会话处理不活跃,会话ID应该设置为0x00。

    [PRS_SOMEIP_00933] 当会话处理处于活动状态时,会话ID应设置为[0x1, 0xFFFF]范围内的值。

    [PRS_SOMEIP_00934] 如果会话处理是活动的,会话ID应根据各自的用例增加(关于专用用例的详细信息包含在单独的规格项中)。

    [PRS_SOMEIP_00533] 请求/响应方法应该使用会话处理机制处理会话ID。会话ID应该在每次调用后递增。

    [PRS_SOMEIP_00521] 当会话ID达到0xFFFF时,它应该绕到0x01重新开始。

    [PRS_SOMEIP_00739] 对于请求/响应方法,如果响应的会话ID与请求的会话ID不匹配,订阅者必须忽略响应。

    [PRS_SOMEIP_00935] 对于通知消息,接收者应该忽略会话ID,当会话处理不活跃时。

    [PRS_SOMEIP_00936] 对于通知消息,接收方应处理会话ID根据各自的用例(关于专用用例的详细信息包含在单独的规格项中)。

    Protocol Version [8 Bit]

    协议版本用来识别使用的SOME/IP报头格式(不包括有效载荷格式)。

    [PRS_SOMEIP_00050] 对于SOME/IP报头中所有不兼容的更改,协议版本应该增加。如果基于旧协议版本的接收方不丢弃消息并不正确地处理它,则更改是不兼容的。

    NOTE:协议版本本身是SOME/IP报头的一部分,因此协议版本在报头中的位置不能改变。

    NOTE:仅影响有效负载格式的变更不应增加协议版本。

    Interface Version [8 Bit]

    [PRS_SOMEIP_00053] 接口版本应该是一个包含服务接口(service interface)的主版本Major version的8位字段。

    Message Type [8 Bit]

    [PRS_SOMEIP_00055] 消息类型字段用于区分不同类型的消息,应包含下表所示的值:

    NumberValueDescription
    0x00REQUESTA request expecting a response (even void)
    0x01REQUEST_NO_RETURNA fire&forget request
    0x02NOTIFICATIONA request of a notification/event callback expecting no response
    0x80RESPONSEThe response message
    0x81ERRORThe response containing an error
    0x20TP_REQUESTA TP request expecting a response (even void)
    0x21TP_REQUEST_NO_RETURNA TP fire&forget request
    0x22TP_NOTIFICATIONA TP request of a notification/event callback expecting no response
    0xa0TP_RESPONSEThe TP response message
    0xa1TP_ERRORThe TP response containing an error

    [PRS_SOMEIP_00701] 当没有错误发生时,常规请求(消息类型0x00)应由响应(消息类型0x80)响应。如果发生错误,将响应错误消息(消息类型0x81)。

    也可以发送没有响应消息的请求message type 0x01; 为了更新值,存在一个回调接口(消息类型0x02)

    [PRS_SOMEIP_00367] 消息类型的第三高位(=0x20)应该被称为TP-Flag,并且应该设置为1来表示当前的SOME/IP消息是一个消息段(Segment)。消息类型的其他位按本节中指定的方式设置。

    Return Code [8 Bit]

    [PRS_SOMEIP_00058] 返回代码用于指示请求是否成功处理。为了简化Header布局,每个消息都传输字段返回代码。特定消息类型允许的返回代码如下表所示:

    Message TypeAllowed Return Codes
    REQUESTN/A set to 0x00 (E_OK)
    REQUEST_NO_RETURNN/A set to 0x00 (E_OK)
    NOTIFICATIONN/A set to 0x00 (E_OK)
    RESPONSESee Return Codes in [PRS_SOMEIP_00191]
    ERRORSee Return Codes in [PRS_SOMEIP_00191]. Shall not be 0x00 (E_OK)

    Payload [variable size]

    载荷字段携带参数,参数的序列化将在后续章节说明。

    SOME/IP有效载荷字段的大小取决于所使用的传输协议。UDP SOME/IP负载应该在0到1400字节之间。限制在1400字节是以便允许协议栈的未来更改(例如改成IPv6或增加安全手段)由于TCP支持有效负载分段,因此自动支持更大的负载。

    有效负载可以由事件的数据元素或方法的参数组成。

    Endianess

    [PRS_SOMEIP_00368] 报头应该按照网络字节顺序进行编码(big endian)。

    [PRS_SOMEIP_00369] 载荷内参数的字节顺序应由配置来定义。

    更多相关内容
  • eth-ws-someip 汽车以太网SOME / IP和SOME / IP-SD Wireshark LUA解剖器(Autosar CP和AP,Foundation 1.5.0) 安装 为了使用此LUA插件,需要将它们添加到Wireshark的“个人插件”文件夹中。 如果您不想直接将解剖...
  • CommonAPI C ++ SOME / IP... == CommonAPI SOME / IP C ++用户指南该用户指南可以作为AsciiDoc文档在CommonAPI-SomeIP-Tools项目的文档目录中找到。 可以在找到pdf版本。 更多的信息 Linux的构建说明 CommonAPI Core运
  • someip - transaction 实例

    2020-11-11 15:33:29
    附件是SOMEIP服务端和客户端进行完整通讯的一系列以太网报文的完整记录。Server广播服务,C订阅服务。S/C建立通讯的完整过程。有助于理解someip的工作过程和原理。
  • 包括基础协议规范PRS协议和基于CP实现的SWS协议
  • SOMEIP通信协议代码实现,两个文件client.c和server.c,实现客户端和服务端通讯;测试在树莓派与电脑虚拟机上的Ubuntu通讯;文件SOMEIP测试实现.docx记录测试结果;
  • 基于 SOMEIP 协议的 CANoe 软件仿真,让你清楚了解SOMEIP的结构。
  • 基于 SOMEIP 协议的 CANoe 软件仿真,内容很使用。
  • 该压缩包提供的内容可以参考博客:https://blog.csdn.net/qq_30391343/article/details/123568915 主要提供SOMEIP中Demo演示,侧重Method和Event的客户端和服务端代码实现。 提供一个比较综合的典型场景应用。
  • SOME/IP协议R20-11版本的中文翻译
  • SOME/IP-SD协议的翻译
  • 不同长度的SOMEIP-SD报文
  • CommonAPI-SomeIP-master.zip

    2019-08-17 12:15:57
    someip 源码 CommonAPI-SomeIP-master.zip
  • SOME/IP传输协议的SD部分协议规范,由AUTOSAR发布的标准文档,同时还有SoAD部分的说明
  • SOMEIP标准.zip

    2020-02-29 15:58:39
    车载以太网上层应用SOME/IP协议,附属于AUTOSAR体系,里面包含6个相关文件,学习了解SOME/IP必备资料,欢迎下载
  • someip-sd报文

    2021-01-26 10:57:45
    someip-sd报文
  • 资源来自pypi官网。 资源全名:someip-0.1.1-py3-none-any.whl
  • 新能源汽车 通信技术 物联网 硬件工程师 文档
  • 车联网SOMEIP应用总结

    万次阅读 多人点赞 2020-01-05 10:54:48
    车联网SOMEIP应用总结

    1 汽车中的SOMEIP
    1.1 IEEE规范
    IEEE 802.3bw:100BASE-T1
    IEEE 802.3bp:1000BASE-T1
    IEEE 802.1Q:VLAN
    IEEE 802.1Qav:FQTSS
    IEEE 802.1Qat:SRP
    IEEE 802.1AS:gPTP

    1.2 AUTOSAR规范
    SOMEIP:                     AUTOSAR_PRS_SOMEIPProtocol
    SOMEIP/SD:               AUTOSAR_PRS_SOMEIPServiceDiscoveryProtocol
    SOMEIP/SD:               AUTOSAR_SWS_ServiceDiscovery
    SOMEIP数据序列化:   AUTOSAR_SWS_SOMEIPTransformer
    SOMEIP:                     AUTOSAR_TR_SomeIpExample
    TCP测试标准:             Acceptance Test Specification of TCP communication
    UDP测试标准:             Acceptance Test Specification of UDP communication
    IPv4测试标准:             Acceptance Test Specification of IPv4 communication
    TCP/IP软件接口描述: Specification of TCP/IP Stack

    ATS:Acceptance Test Specification
    PRS:Protocol Specification
    SRS:Software Requirement Specification
    SWS:Software Specification 
    TR:Technical Report

    1.3 Open Alliance规范
    TC1:Interoperability & Compliance Tests for 100BASE-T1 PHYs
    TC2:100BASE-T1 Ethernet Channel & Components
    TC3:1000BASE-T1 CMC Requirements
    TC4:Tools
    TC6:MII
    TC7:1000BASE-RH Gigabit Ethernet over Plastic-Optical-Fiber
    TC8:Automotive Ethernet ECU Test Specification,2016年1月发布v1.0规范
    TC9:Automotive Ethernet Channel & Components
    TC10:Wake-up and Sleep, BMW MGU21
    TC11:Ethernet switch requirements and qualification
    TC12:1000BASE-T1 PHY
    TC14:10BASE-T1S PHY

    1.4 DoIP规范
    13400-1:DoIP协议基础
    13400-2:DoIP 3/4层
    13400-3:DoIP 1/2层
    13400-4:DoIP引脚定义
    14229-2:UDS5层
    14229-5:UDS7层

    2 SOMEIP协议
    2.1 SOMEIP数据包格式
    SOMEIP SD报文payload的每一个条目用entry表示,类似于配置交换机4096个VLAN中的每一条entry,或者1588保存时间戳的timestamp entry。

    Figure 2-1 SOMEIP报文头及Payload

    Figure 2-2 SOMEIP报文头细节

    Figure 2-3 SOMEIP Service Discovery报文格式

    1)Message ID(包括16bit Service ID和16bit Method ID)
    0xffff8100表示SD消息,其它表示gateway消息。
    2)Offer Service作用
    - 上电启动时,车内各ECU的启动时间各不相同,ECU通过SD可以对外宣布其Service处于可用状态,否则客户端需要不停的尝试socket连接
    - 错误处理,当提供的Service出现问题时,可以通过SD即刻了解Service的不可用状态,接收方就可以做出相应的处理了
    3)Find Service作用
    由Client发起的多播报文,去对端查找对方是否支持特定的Service ID,如果对端支持,会用单播Offer Service回应该请求。
    4)Session ID
    初始值为1,每次传packet,都需要自动加1,一直到0xffff后,再回到1继续累加计数。如果Session ID的值为0,表示本机或者Service正在重启,对端会关闭连接并重新Offer Service和Find Service。

    2.2 SOMEIP Startup Phase
    1)Services are advertized by broadcast Offer msgs
    2)Clients looks for services via broadcast Find msgs
    3)Once a service is located: Subscribe - Ack
    4)2 modes for a client : Request and Listen
    5)2 modes for a service: Offer and Silent(静默模式)

    Client Startup Phase:
    Initial Wait Phase(IWP):
    Repetition Phase:不断地发送Find messages直到超过最大发送次数,如果收到unicast Offer就停止发送Find messages
    Main Phase:periodically Sub - Ack on Offer messages,Request - Response

    Service Startup Phase:
    Initial Wait Phase(IWP):Find messages received in IWP are ignored
    Repetition Phase:周期性发送Offer messsages,Find received后,发送unicast Offer包给Client
    Main Phase:周期性发送Offer messages和其它正常操作

    这个Startup Phase存在的意义就是评估2台ECU初始化时不同步而导致的SOMEIP协议握手可能的延时。

    2.3 订阅SUBSCRIBE
    - 基于Publish/Subscribe模式
    - SUBSCRIBE简写为Sub
    - Offer和Sub都是周期性的,并且是同步的,也就是说service每发送一次Offer,client都要Sub一次;一般收到Offer消息后,使用Linux timerfd创建定时器,延时10毫秒左右向Server发送Sub消息
    - SUBSCRIBE on Offer Service
    once ECU1 someipsdd receives OFFER_SERVICE from ECU2 someipsdd and FIND_SERVICE from local client, someipsdd matches the service id , instance id 's of both OFFER_SERVICE and FIND_SERVICE , if matches, FIND_SERVICE成功,然后local client去连接服务器的UDP和TCP sockets,当TCP和UDP sockets连接成功后,then serverConnected() EVENT is sent to the local client, and local client sends SUBSCRIBE to ECU2.
    - 客户端订阅后,服务端需要立刻发送一条订阅的初始notification给客户端

    tcp/udp socket创建完成 -> serverConnected() -> 客户端订阅
    tcp/udp socket通信异常或者超过3s没有收到offer报文 -> serverDisconnected() -> SOMEIP客户端与服务端断开连接
    订阅回调如果使用TCP协议,server端由于TCP粘包效应(nagle算法),可能会把几个notification的payload合成一个,然后发送到client端;如果client没有很好地解析该报文,可能导致丢失notification,参考《Linux网络TCP sticky分析工具》。

    下面这幅图来之于page 43 of AUTOSAR_PRS_SOMEIPServiceDiscoveryProtocol。
    Picture 2-4 Publish/Subscribe Example

    上图中的订阅描述有点问题,实际上订阅的事件需要传给SOME/IP,SOME/IP处理后,再传ACK或者NAK给SOME/IP-SD发送。
    handleSubscriptionAckWait() for UDP or TCP initial subscription events.

    3 COVESA vSomeIP
    GENIVI Alliance was rebranded as the Connected Vehicle Systems Alliance (COVESA) in October 2021 and now operates under that name.

    3.1 Android boost的编译
    https://www.boost.org/users/download/

    下载2017版本1.66.0,编写Android.bp文件。
    cc_library_static {
        name: "libboost",
        vendor_available: true,

        rtti: true,
        cppflags: [
            "-fexceptions",
            //"-mavx2",
        ],

        local_include_dirs: [
            "./",
            "./libs/log/src/",
        ],
        export_include_dirs: ["./"],
        srcs: [
            "libs/chrono/src/*.cpp",
            "libs/date_time/src/gregorian/*.cpp",
            "libs/log/src/setup/*.cpp",
            "libs/log/src/*.cpp",
            "libs/log/src/posix/*.cpp",
            "libs/filesystem/src/*.cpp",
            "libs/system/src/error_code.cpp",
            "libs/thread/src/future.cpp",
            "libs/thread/src/pthread/thread.cpp",
            "libs/thread/src/pthread/once.cpp",
        ],
    }
    boost.log库在APL A39X0 Gen9平台加上-mavx2后,编译可以通过,但是在Android上运行时会出现“Illegal instruction”的错误。可以通过cat /proc/cpuinfo查看CPU支持的特殊指令集。

    为了简化Android.bp的编写,libs/log/src/*.cpp会包含所有的cpp文件,要解决在APL A39X0 Gen9平台上的运行错误,按照如下步骤修改即可。
    1)注释Android.bp中的-mavx2
    2)将文件libs/log/src/dump_avx2.cpp重命名成libs/log/src/dump_avx2-cpp-
    3)将文件libs/log/src/dump_ssse3.cpp重命名成libs/log/src/dump_ssse3-cpp-
    4)再重新编译生成libboost.a即可

    3.2 Android vSomeIP的编译
    AUTOSAR系统架构中,软件组件的交互是基于虚拟功能总线(Virtual Function Bus,VFB)进行的,使用VFB的模块名字前面都有个v,表示基于VFB通信的意思,譬如AUTOSAR中属于AVB的vAVTP和vSRP等,这里vSomeIP也继承了这一用法,加个前缀v。

    github COVESA/vsomeip

    COVESA vSomeIP基于CAPI(CommonAPI),修改vSomeIP Android.bp,添加如下的boost库依赖。
    rtti: true,
    cppflags: [
        "-fexceptions",
    ],
    static_libs: [
        "libboost",
    ],

    文件implementation/helper/1.66/boost/asio/detail/reactor_op_ext_local.hpp,注释下面的一行头文件。
    #include <boost/asio/detail/pop_options.hpp>

    让系统编译OEM Android.bp,需要将Android.bp的路径添加到build/soong/root.bp

    3.3 Android vSomeIP hello_world的编译
    加上如下的vSomeIP库依赖。
    shared_libs: [
        "libvsomeip",
        "libvsomeip_cfg",
        "libvsomeip_e2e",
        "libvsomeip_sd",
    ],
    /tmp/vsomeip-$CLIENTID: CLIENTID comes from json applications[n].id.
    There are three endpoints in hello_world demo, routing manager is /tmp/vsomeip-0, service sends data to client via /tmp/vsomeip-5555 (SOME/IP header low 16bit Client ID), client sends data to service via /tmp/vsomeip-4444 (SOME/IP header low 16bit Client ID).

    3.4 Franca and CommonAPI
    If you want to generate C++ code directly from Franca interface specifications, CommonAPI C++ might be the proper solution. It is designed to decouple generated API from the actual IPC stack and cooperates seamlessly with Franca. CommonAPI was created in the context of the GENIVI initiative.
    CommonAPI C++ implements serialization for vsomeip.
    一些私有SomeIP方案的序列化是属于SomeIP库的一部分。
    CommonAPI和私有SomeIP的序列化都是利用了C++的2个类InputStream和OutputStream。SOME/IP does not support TLV.
    variable length string: 4 bytes length (including BOM) + 3 bytes BOM (EF BB BF) + string

    implementation/message/src/serializer.cpp
    implementation/message/src/deserializer.cpp

    3.5 Java HIDL
    [28th-Mar-2022]
    Meld for source code compare in Windows.
    G is for getter method, S is for setter method and N is for notification.
    ./hardware/interfaces/update-makefiles.sh
    Android.mk
    LOCAL_STATIC_JAVA_LIBRARIES += \
    android.hardware.foo-V1.0-java
    Android.bp
    static_libs: [
    "android.hardware.foo-V1.0-java",
    ],

    // out/target/common/gen/JAVA_LIBRARIES
    import android.hardware.foo.V1_0.IFoo;
    IFoo server = IFoo.getService();

    4 车载以太网测试
    4.1 测试设备
    驱动开发调试设备:NI
    SOME/IP测试设备:德国Technica engineering车载以太网交换机
    TC8 TCP/IP测试设备:英国Spirent的C50 Appliance及其PC软件TTworkbench

    4.2 抓包工具CANoe.Ethernet
    VN5610A / VN5640
    CANoe文件格式后缀名.blf

    4.3 TC8测试项目
    1)http://www.opensig.org/tech-committees/tc8/
    2)物理层PMA测试
    3)TCP/IP一致性测试 - 测试TCP/IP网络层和传输层是否符合规范,Linux上TCP/IP协议栈是开源的,所以一般的失败就是改改网络的配置参数,不会为了过一个测试去修改Linux内核,所以这个测试意义不大,HU上运行一个二进制uppertester,同时使用Spirent的C50 Appliance及其PC软件TTworkbench;SOMEIP SD报文需要使用参数IP_MULTICAST_TTL和IP_TTL调用setsockopt()将IP报文头中的TTL字段的值设置为1

    譬如:
    ARP老化时间:/proc/sys/net/ipv4/neigh/ethN/gc_stale_time
    IP报头TTL配置:/proc/sys/net/ipv4/ip_default_ttl
    echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_accept

    4)SOME/IP一致性测试 - 测试SOME/IP协议栈是否符合ETS规范,这个是测试重点
    5)AVB/TSN一致性测试 - 测试AVB协议栈中的gPTP、FQTSS、AVTP等

    5 Wireshark SOMEIP plugin
    5.1 插件安装
    https://github.com/jamores/eth-ws-someip

    Wireshark插件目录:Help -> About Wireshark -> Folders/Plugins
    解压后,将所有后缀是lua的文件拷贝到Wireshark安装目录plugins/2.4.10/下。

    Wireshark 3.2 has builtin SOME/IP plugin.

    5.2 时间戳调整为UTC显示格式
    View -> Time Display Format -> Date and Time of Day

    5.3 常用过滤关键字
    Wireshark解析MAC地址时会把前三个字节解析为一个公司的名字。
    1)someip
    2)ip.src == 192.168.1.1 - 改到对应的ip地址
    3)ip.src == 192.168.1.1 and ip.dst == 192.168.1.2 - 改到对应的ip地址
    4)someip.messageid == 0xffff8100 and ip.src == 192.168.1.2 - 改到对应的ip地址
    5)dns - 调试域名解析
    6)tcp.port == 8000
    7)!(tcp.analysis.retransmission)
    8)tcp.flags.syn==1 or tcp.flags.ack==0
    9)tcp.flags.fin == 1
    10)usb.src == "1.6.1" and usb.dst == "host" - 改到对应的USB bus_no.addr.ep_no
    11)OFFER_SERVICE
    12)FIND_SERVICE
    13)SUBSCRIBE

    5.4 SOMEIP TCP连接心跳包
    SOMEIP TCP连接心跳包(4个字节):0x dead beef

    5.5 tcpdump抓到的log循环写
    tcpdump -X -i eth0 -s 0 -C 20 -W 3 -w /data/eth_sniff.pcap -Z root

    -i:设备名
    -s:过滤包大小限制
    -C:定义生成文件大小,兆(Mega Bytes)为单位,取整数
    -W:可生成多少个文件
    -w:指定生成文件的路径
    -Z:用户组,user或者root;Linux如果想循环写文件,此选项必须有,Android不需要

    5.6 Wireshark安装目录下的2个工具
    1) editcap
    2) mergecap

    6 debug
    6.1 TCP_NODELAY and TCP_CORK
    First of all not both of them disables Nagle's algorithm.

    Nagle's algorithm is for reducing more number of small network packets in wire. The algorithm is: if data is smaller than a limit (usually MSS), wait until receiving ACK for previously sent packets and in the mean time accumulate data from user. Then send the accumulated data.

    if [ data > MSS ]
        send(data)
    else
        wait until ACK for previously sent data and accumulate data in send buffer (data). And after receiving the ACK send(data).

    This will help in applications like telnet. However, waiting for the ACK may increase latency when sending streaming data. Additionally, if the receiver implements the 'delayed ACK policy', it will cause a temporary deadlock situation. In such cases, disabling Nagle's algorithm is a better option.

    So TCP_NODELAY is used for disabling Nagle's algorithm.

    TCP_CORK aggressively accumulates data. If TCP_CORK is enabled in a socket, it will not send data until the buffer fills to a fixed limit. Similar to Nagle's algorithm, it also accumulates data from user but until the buffer fills to a fixed limit not until receiving ACK. This will be useful while sending multiple blocks of data. But you have to be more careful while using TCP_CORK.

    Until 2.6 kernel, both of these options are mutually exclusive. But in later kernel, both of them can exist together. In such case, TCP_CORK will be given more preference.

    6.2 SOMEIP ETS网络调试助手
    NetAssist.exe

    使用说明:勾选“按十六进制发送”CheckBox,然后粘贴要发送的16进制数据到“发送窗口”,点击“发送”按钮。

    6.3 multicast
    1) 基本概念
    - Linux组播client需要使用setsockopt()设置IP_ADD_MEMBERSHIP(加入指定的组播组)才能接收组播server发送的数据。
    - 组播MAC地址是指第一个字节的最低位是1的MAC地址。
    - 组播MAC地址的前3个字节固定为01:00:5e,后3个字节使用组播IP的后23位。例如239.192.255.251的MAC地址为01:00:5e:40:ff:fb。
    - Windows 10 Wireshark要抓取SOME/IP组播报文,需要使用SocketTool工具监听239.192.255.251:30490,然后Wireshark才会显示组播报文,否则不显示(Windows netmon不需要任何设置,就可以抓到全部报文)。

    2) Linux
    Map IP addr to multicast MAC is function ip_eth_mc_map(), kernel eventually calls driver ndo_set_rx_mode() to set multicast MAC to NIC RX MAC filter table.

    6.4 switch port mirror
    Read my blog “以太网交换机EtherSwitch”。

    6.5 iptables port mirror
    1) Android iptables TEE
    CONFIG_NF_DUP_IPV4=m
    CONFIG_NF_DUP_IPV6=m
    CONFIG_NETFILTER_XT_TARGET_TEE=m

    # eth0 -> USB eth1 (192.168.2.5) -> Windows NIC (192.168.2.100)
    iptables -A PREROUTING -t mangle -i eth0 -j TEE --gateway 192.168.2.100
    iptables -A POSTROUTING -t mangle -o eth0 -j TEE --gateway 192.168.2.100

    TEE复制报文时,同时替换复制报文的源和目的MAC地址分别到USB eth1和Windows NIC的MAC地址(组播MAC地址也被替换成了Windows NIC的MAC),IP地址不做替换,所以没有路由功能,报文止步于Windows NIC。其缺点是阻碍了原始数据包的快速通过。

    2) Windows Tools
    Netmon: uses LWF (Light-Weight Filter) NDIS driver
    Wireshark: uses NPcap

    Windows 10上,Netmon可以抓取所有TEE后的报文,而Wireshark不可以,必须要用SocketTool或者其它工具监听对应的IP和port,才能够抓到相应的报文。

    6.6 覆盖Android源代码中的cpp或者Java文件
    1) device/<oem>/<soc_platform>/<project>/vendorsetup.sh
    #!/bin/sh

    MY_PATH=${PWD}
    PROJ_PATH="device/<oem>/<soc_platform>/<project>"

    if [ -f ${MY_PATH}/${PROJ_PATH}/overlay_setup.sh ]; then
        chmod a+x ${MY_PATH}/${PROJ_PATH}/overlay_setup.sh
    fi

    2) device/<oem>/<soc_platform>/<project>/overlay_setup.sh
    #!/bin/sh

    MY_PATH=${PWD}
    OVL_PATH="device/<oem>/<soc_platform>/<project>/path/to/overlay"

    # add shell commands here

    3) device/<oem>/<soc_platform>/<project>/device.mk
    $(shell $(LOCAL_PATH)/overlay_setup.sh)

    6.7 Android binder death调试
    echo 0x18 > /sys/module/binder/parameters/debug_mask
    dmesg -C
    dmesg -w | grep binder &
    kill -9 $PID

    6.8 Android debuggered
    Android和传统的Linux下基于glibc的不同,glibc的interpreter是/lib/ld-linux-xx.so.2,Android的interpreter是/system/bin/linker。
    system/core/debuggerd/debuggerd.c

    am broadcast -a <string>
    可以做个启动服务,需要发送广播时就setprop sys.am.broadcast 1
    接收者需要动态注册接收该广播,因为静态注册可能接收不到广播。

    7 Abbreviations
    Audi HCP3: High Compute Platform 3
    Audi NTG: Next Telematic Generation
    BMW BDC_BCP: Body Domain Controller (Gen3)_Basis Central Platform
    BMW IDC: BMW Infotainment Domain Controller
    BMW MARS: Modular Audio Receiver System, previously called RAM
    BMW MGU: Media Graphic Unit (processor for display, I drive interface)
    BMW OAP: Online Application Platform
    BMW RAM: Receiver Audio Module (tuner, diversity antenna, Amplifier)
    BMW WAVE: Wireless Access in Vehicle Environment
    Boost.Asio:Asynchronous network I/O
    boost.msm:Boost.MetaStateMachine
    BPF: Berkeley Packet Filter, tcpdump uses BPF to filter packets
    Daimler MMA: Mercedes-Benz Modular Architecture
    DDS:Data Distribution Service,已被纳入Adaptive AUTOSAR标准中
    ETS:Enhanced Testability Service
    HDMI HEC:HDMI Ethernet Channel,HDMI以太网通道,pin14和pin19传输差分数据,pin17作为差分地
    H-MTD:High-Speed Modular Twisted-Pair Data
    libvsomeip_e2e:end to end
    MDI:Medium Dependent Interface,媒介有关接口,通常是指将以太网主机或控制器连接至电缆的物理连接器,譬如FAKRA;需要使用矢量网络分析仪VNA测量MDI回波损耗,即100 Ω差分阻抗是否匹配
    nmap:Network Mapper,Linux下的网络扫描和嗅探工具
    OABR: OPEN Alliance BroadR-Reach,其中OPEN是One Pair Ethernet Network的缩写
    PVID:Port default VID,PVID属于IEEE 802.1Q,不属于Port-based VLAN
    SOA:Service-Oriented Architecture,面向服务的架构
    TC8:Technical Committees 8,车载以太网测试规范
    Tesla CID: Central Information Display
    Tesla IC: Instrument Cluster
    VNA:Vector Network Analyzer,矢量网络分析仪
    10Base-T1S:S表示Short Reach

    展开全文
  • [someip专题]vsomeip代码解析3

    千次阅读 2022-01-09 11:55:22
    代码下载,大家请参考 ,以下则直接说明每个...1someip基础知识 关于SOME/IP的理解_AgingMoon的博客-CSDN博客_someip 2.vsomeip 安装使用 [someip专题]vsomeip使用以及代码解析1_AgingMoon的博客-CSDN博客 3.hello.

     代码下载,大家请参考 ,以下则直接说明每个文件,每个函数,作用,共同记录学习GitHub - COVESA/vsomeip: An implementation of Scalable service-Oriented MiddlewarE over IP

    1someip基础知识

    关于SOME/IP的理解_AgingMoon的博客-CSDN博客_someip

    2.vsomeip 安装使用

    [someip专题]vsomeip使用以及代码解析1_AgingMoon的博客-CSDN博客

    3.hello world代码解析

    [someip专题]vsomeip代码解析2_AgingMoon的博客-CSDN博客

    4. application 解析

    4.1 vsomeip application主要功能

    主要功能包括

    功能说明
    offer service提供服务
    stop offer service停止提供服务
    publish eventgroup发布事件组
    stop publish eventgroup停止发布事件组
    send request发送请求
    send response发送响应
    trigger event事件驱动
    update field更新域
    receive message接收消息
    subscribe eventgroup订阅事件组
    unsubscribe eventgroup取消订阅事件组
    request service请求服务
    release service释放服务

     4.2 vsomeip application 静态结构

     以下针对application中,涉及到的函数进行说明

    4.3 vsomeip runtime class

    runtime class 接口声明在 interface/vsomeip/runtime.hpp 文件中

    runtime 主要包含,vsomeip公共资源的管理,是一个单例类,是application类,创建实例化的入口,前面我们也提到 用runtime 去创建application。

        /**
         *
         * \brief 创建vsomeip application 对象.
         *
         *应用对象用于管理服务提供,和请求,以及事件订阅,应用对象的名称通过配置文件唯一识别, 
         *如果名字为空,则会从环境变量VSOMEIP_APPLICATION_NAME中获取
         *
         * \param _name Name of the application 
         *
         */
        virtual std::shared_ptr<application> create_application(
                const std::string &_name = "") = 0;
        /**
         *
         * \brief 构建一个空的 message 对象.
         *
         * \param _reliable 可靠性由TCP连接还是UDP连接决定
         *
         */
        virtual std::shared_ptr<message> create_message(
                bool _reliable = false) const = 0;
        /**
         *
         * \brief 构建空的 request message.
         *
         *消息内容和服务实例,有用户设定
         *
         */
        virtual std::shared_ptr<message> create_request(
                bool _reliable = false) const = 0;
        /*
         * \brief 从给定的请求消息 构建 empty response message 
         *
         */
        virtual std::shared_ptr<message> create_response(
                const std::shared_ptr<message> &_request) const = 0;
        /**
         *
         * \brief 创建空的 notification message.
         *
         * Note: Creating notification messages and sending them using
         * @ref application::send is possible but not the standard way of sending
         * notification with vsomeip. The standard way is calling
         * @ref application::offer_event and setting the value using the
         * @ref application::notify / @ref application::notify_one methods.
         *
         */
        virtual std::shared_ptr<message> create_notification(
                bool _reliable = false) const = 0;
        /**
         *
         * \brief 查询应用对象
         *
         */
        virtual std::shared_ptr<application> get_application(
                const std::string &_name) const = 0;
        /**
         *
         * \brief 移除应用对象
         * \param _name Name of the application to be removed.
         *
         */
        virtual void remove_application( const std::string &_name) = 0;

    runtime class 实现在 runtime 文件中,被runtime_impl 继承

    创建应用的方式是,根据应用的名称进行创建一个aplication_impl对象,并保存在application_[its_name_]中。

    获取应用的方式是,根据名字查找application_[_name],查到即返回该对象;

    创建消息的方式是,指定是否可靠(TCP/UDP),创建一个message_impl对象,指定协议版本,返回码,可靠性,接口版本;

    创建消息请求的方式是,指定是否可靠,创建一个message_impl对象,指定协议版本,返回码,可靠性,接口版本,以及 消息类型为 REQUEST

    创建消息请求的方式是,创建一个message_impl对象,根据请求的消息,设定请求service-instance-method-client-session, 设定协议版本,返回码,可靠性  以及消息类型为RESPONSE。

    创建消息通知的方式是,创建一个message_impl对象,设定消息类型为NOTIFICATION

    创建payload方式,实例化一个payload_impl

    4.4 vsomeip application class

    application类定义的接口声明在interface/application.hpp中

    application管理每个用户的生命周期以及所需分配的资源。

        /**
         *
         * \brief 获取应用的名称
         *
         * Note: A user application can use several vsomeip application objects in
         * parallel. The application names must be set explicitly 
         *
         * \return Application name
         *
         */
        virtual const std::string & get_name() const = 0;
        /**
         *
         * \brief 返回客户端ID
         *
         * Each request sent by and each response sent to the application contain
         * the client identifier as part of the request identifier within the
         * SOME/IP message header. The client identifier can either be configured
         * by the configured as part of the application node within a vsomeip
         * configuration file or is automatically set to an unused client
         * identifier by vsomeip. If the client identifier is automatically set,
         * its high byte will always match the diagnosis address of the device.
         *
         * \return Client ID of application
         *
         */
        virtual client_t get_client() const = 0;
        /**
         * \brief  获取诊断地址
         *
         * \return diagnosis address
         */
        virtual diagnosis_t get_diagnosis() const = 0;
    /**
         *
         * \brief 初始化应用  
         *
         */
        virtual bool init() = 0;
    
        /**
         *
         * \brief 开始消息处理
         */
        virtual void start() = 0;
    
        /**
         * \brief 停止消息处理
         *
         */
        virtual void stop() = 0;
    
        /**
         * \brief 处理 messages / events.
         *
         */
        virtual void process(int _number = VSOMEIP_ALL) = 0;
    
    
        /**
         *
         * \brief Offers 服务实例
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _major Major service version (Default: 0).
         * \param _minor Minor service version (Default: 0).
         *
         */
        virtual void offer_service(service_t _service, instance_t _instance,
                major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor =
                        DEFAULT_MINOR) = 0;
    
        /**
         *
         * \brief Stops offering 服务实例
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _major Major service version (Default: 0).
         * \param _minor Minor service version (Default: 0).
         *
         */
        virtual void stop_offer_service(service_t _service, instance_t _instance,
                major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor =
                        DEFAULT_MINOR) = 0;
    
        /**
         *
         * \brief Offers event or field.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _notifier 通知ID
         * \param _eventgroups   eventgroup ID
         * \param _type Pure event, selective event or field.
         * \param _cycle 事件周期
         * \param _change_resets_cycle S
         * \param _update_on_change 
         * \param _epsilon_change_func 
         * \param _reliability Either RT_UNRELIABLE or RT_RELIABLE. 
         */
        virtual void offer_event(service_t _service, instance_t _instance,
                event_t _notifier, const std::set<eventgroup_t> &_eventgroups,
                event_type_e _type = event_type_e::ET_EVENT,
                std::chrono::milliseconds _cycle =std::chrono::milliseconds::zero(),
                bool _change_resets_cycle = false,
                bool _update_on_change = true,
                const epsilon_change_func_t &_epsilon_change_func = nullptr,
                reliability_type_e _reliability = reliability_type_e::RT_UNKNOWN) = 0;
    
        /**
         *
         * \brief Stops offering  event or field.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _event Event ID
         *
         */
        virtual void stop_offer_event(service_t _service,
                instance_t _instance, event_t _event) = 0;
    
        /**
         *
         * \brief 注册应用客户端
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _major Major service version (Default: 0xFF).
         * \param _minor Minor service version (Default: 0xFFFFFF).
         * \param _use_exclusive_proxy Create an IP endpoint
         *
         */
        virtual void request_service(service_t _service, instance_t _instance,
                major_version_t _major = ANY_MAJOR,
                minor_version_t _minor = ANY_MINOR) = 0;
    
        /**
         *
         * \brief 去注册应用客户端
         *
         *
         * \param _service Service ID.
         * \param _instance Instance ID
         *
         */
        virtual void release_service(service_t _service, instance_t _instance) = 0;
    
        /**
         *
         * \brief 注册应用 of an event or field.
         *
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _event Event ID
         * \param _eventgroups Eventgroup ID
         * \param _type Pure event, selective event or field.
         * \param _reliability Either RT_UNRELIABLE or RT_RELIABLE
         */
        virtual void request_event(service_t _service, instance_t _instance,
                event_t _event, const std::set<eventgroup_t> &_eventgroups,
                event_type_e _type = event_type_e::ET_EVENT,
                reliability_type_e _reliability = reliability_type_e::RT_UNKNOWN) = 0;
        /**
         *
         * \brief 去注册应用 of an event or field.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _event Event ID
         * .
         */
        virtual void release_event(service_t _service, instance_t _instance,
                event_t _event) = 0;
    
        /**
         *
         * \brief 订阅 eventgroup.
         *
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _eventgroup Eventgroup ID
         * \param _major Major version number of the service.
         * \param _event All (Default) or a specific event.
         *
         */
        virtual void subscribe(service_t _service, instance_t _instance,
                eventgroup_t _eventgroup, major_version_t _major = DEFAULT_MAJOR,
                event_t _event = ANY_EVENT) = 0;
    
        /**
         *
         * \brief 取消订阅eventgroup.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _eventgroup Eventgroup ID
         *
         */
        virtual void unsubscribe(service_t _service, instance_t _instance,
                eventgroup_t _eventgroup) = 0;
    
        /**
         *
         * \brief 查询可用的服务
         *
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _major Major interface version. Use ANY_MAJOR to ignore the
         * major version.
         * \param _minor Minor interface version. Use ANY_MINOR to ignore the
         * minor version.
         *
         */
        virtual bool is_available(service_t _service, instance_t _instance,
                major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const = 0;
    
    
    
        /**
         *
         * \brief 发送消息
         *
         * 序列化消息,并发送到消息目标
         *
         * \param _message Message object.
         *
         */
        virtual void send(std::shared_ptr<message> _message) = 0;
    
        /**
         *
         * \brief Fire an event or field notification.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _event Event ID
         * \param _payload Serialized payload of the event.
         *
         */
        virtual void notify(service_t _service, instance_t _instance,
                event_t _event, std::shared_ptr<payload> _payload,
                bool _force = false) const = 0;
    
        /**
         *
         * \brief Fire an event to a specific client.
         * \param _service Service ID
         * \param _instance Instance  ID
         * \param _event Event ID
         * \param _payload Serialized payload of the event.
         * \param _client Target client.
         *
         */
        virtual void notify_one(service_t _service, instance_t _instance,
                    event_t _event, std::shared_ptr<payload> _payload, client_t _client,
                    bool _force = false) const = 0;
    
        /**
         *
         * \brief 注册状态处理
         *
         *
         * \param _handler Handler function 
         *
         */
        virtual void register_state_handler(state_handler_t _handler) = 0;
    
        /**
         *
         * \brief 去注册状态处理
         *
         */
        virtual void unregister_state_handler() = 0;
    
        /**
         *
         * \brief 注册处理 指定的 method or event.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _method Method/Event ID
         * \param _handler Callback 函数
         *
         */
        virtual void register_message_handler(service_t _service,
                instance_t _instance, method_t _method,
                message_handler_t _handler) = 0;
        /**
         *
         * \brief 反注册处理 指定的 service method/event notification.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _method Method/Event ID
         */
        virtual void unregister_message_handler(service_t _service,
                instance_t _instance, method_t _method) = 0;
    
        /**
         *
         * \brief 注册一个服务可用回调.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _handler Callback 
         * \param _major Major service version. The parameter defaults to
         * DEFAULT_MAJOR and can be set to ANY_MAJOR.
         * \param _minor Minor service version. The parameter defaults to
         * DEFAULT_MINOR and can be set to ANY_MINOR.
         *
         */
        virtual void register_availability_handler(service_t _service,
                instance_t _instance, availability_handler_t _handler,
                major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) = 0;
    
        /**
         *
         * \brief 反注册一个服务可用回调.
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _handler Callback 
         * \param _major Major service version. The parameter defaults to
         * DEFAULT_MAJOR and can be set to ANY_MAJOR.
         * \param _minor Minor service version. The parameter defaults to
         * DEFAULT_MINOR and can be set to ANY_MINOR.     *
         */
        virtual void unregister_availability_handler(service_t _service,
                instance_t _instance,
                major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) = 0;
    
        /**
         *
         * \brief 注册一个订阅处理
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _eventgroup Eventgroup ID
         * \param _handler Callback .
         *
         */
        virtual void register_subscription_handler(service_t _service,
                instance_t _instance, eventgroup_t _eventgroup,
                subscription_handler_t _handler) = 0;
    
        /**
          *
          * \brief  注册一个异步订阅处理
          *
          * \param _service Service ID
          * \param _instance Instance ID
          * \param _eventgroup Eventgroup ID
          * \param _handler Callback 
          *
          */
         virtual void register_async_subscription_handler(
                 service_t _service, instance_t _instance, eventgroup_t _eventgroup,
                 async_subscription_handler_t _handler) = 0;
    
        /**
         *
         * \brief 反注册一个异步订阅处理
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _eventgroup Eventgroup ID
         *
         */
        virtual void unregister_subscription_handler(service_t _service,
                    instance_t _instance, eventgroup_t _eventgroup) = 0;
    
        /**
         *
         * \brief 清除所有的处理
         *
         */
        virtual void clear_all_handler() = 0;
    
        /**
         *
         * \brief 说明是否包含消息路由
         *
         */
        virtual bool is_routing() const = 0;
    
        /**
         * \brief 设置路由状态
         *
         * . It can be set to RUNNING, SUSPENDED, RESUMED, SHUTDOWN or UNKNOWN.
         *
         * \param _routing_state the current routing state
         */
        virtual  void set_routing_state(routing_state_e _routing_state) = 0;
    
        /**
         *
         * \brief 取消订阅事件组
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _eventgroup Eventgroup ID
         * \param _event Event to unsubscribe 
         */
        virtual void unsubscribe(service_t _service, instance_t _instance,
                eventgroup_t _eventgroup, event_t _event) = 0;
    
        /**
         *
         * \brief 注册订阅状态侦听
         *
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _eventgroup Eventgroup ID
         * \param _event Event ID
         * \param _handler A subscription status handler 
         * \param _is_selective Flag to enable calling the provided handler 
         */
        virtual void register_subscription_status_handler(service_t _service,
                instance_t _instance, eventgroup_t _eventgroup, event_t _event,
                subscription_status_handler_t _handler, bool _is_selective = false) = 0;
    
        /**
         *
         * \brief 取消注册订阅状态侦听
         *
         * \param _service Service ID
         * \param _instance Instance ID
         * \param _eventgroup Eventgroup ID
         * \param _event Event ID
         */
        virtual void unregister_subscription_status_handler(service_t _service,
                instance_t _instance, eventgroup_t _eventgroup, event_t _event) = 0;
    
    
        /**
         *  \brief Enables or disables calling of registered acceptance
         *  handlers for given remote info
         *
         * This method has only an effect when called on the application acting as
         * routing manager
         *
         *  \param _remote IP and port for which SD acceptance handler should be
         *  called
         *  \param _path Path which indicates need for offer acceptance
         *  \param _enable enable or disable calling of offer acceptance handler
         */
        virtual void set_sd_acceptance_required(const remote_info_t& _remote,
                                             const std::string& _path,
                                             bool _enable) = 0;
    
        /**
         *  \brief Enables or disables calling of registered acceptance
         *  handlers for given remote info
         *
         * This method has only an effect when called on the application acting as
         * routing manager
         *
         *  \param _remotes remote infos for which SD acceptance handler should be
         *  called
         *  \param _enable enable or disable calling of offer acceptance handler
         */
        typedef std::map<remote_info_t, std::string> sd_acceptance_map_type_t;
        virtual void set_sd_acceptance_required(
                const sd_acceptance_map_type_t& _remotes, bool _enable) = 0;
    
        /**
         * \brief Returns all configured remote info which require calling of
         * registered service discovery (SD) acceptance handler
         *
         * This method has only an effect when called on the application acting as
         * routing manager
         *
         * \return map with known remotes requiring SD acceptance handling
         */
        virtual sd_acceptance_map_type_t get_sd_acceptance_required() = 0;
    
        /**
         * \brief Registers a handler which will be called upon reception of
         * a remote SD message with the sending ECU's IP address and port as
         * parameter
         *
         * This method has only an effect when called on the application acting as
         * routing manager
         *
         * \param _handler The handler to be called
         */
        virtual void register_sd_acceptance_handler(sd_acceptance_handler_t _handler) = 0;
    
        /**
         * \brief Registers a handler which will be called upon detection of a
         * reboot of a remote ECU with the remote ECU's IP address as a parameter
         *
         * This method has only an effect when called on the application acting as
         * routing manager
         *
         * \param _handler The handler to be called
         */
        virtual void register_reboot_notification_handler(
                reboot_notification_handler_t _handler) = 0;
    
        /**
         * \brief Registers a handler which will be called when the routing reached
         * READY state.
         *
         * This method has only an effect when called on the application acting as
         * routing manager
         *
         * \param _handler The handler to be called
         */
        virtual void register_routing_ready_handler(
                routing_ready_handler_t _handler) = 0;
    
        /**
         * \brief Registers a handler which will be called when the routing state
         * changes.
         *
         * This method has only an effect when called on the application acting as
         * routing manager
         *
         * \param _handler The handler to be called
         */
        virtual void register_routing_state_handler(
                routing_state_handler_t _handler) = 0;
    
        /**
         * \brief Update service configuration to offer a local service on the
         *        network as well
         *
         *  This function is intended to take the necessary information to offer a
         *  service remotely if it was offered only locally beforehand.
         *  Precondition: The service must already be offered locally before
         *  calling this method.
         *  This function only has an effect if called on an application acting as
         *  routing manager.
         *
         * \param _service Service identifier
         * \param _instance Instance identifier
         * \param _port The port number on which the service should be offered
         * \param _reliable Offer via TCP or UDP
         * \param _magic_cookies_enabled Flag to enable magic cookies
         * \param _offer Offer the service or stop offering it remotely
         */
        virtual bool update_service_configuration(service_t _service,
                                                  instance_t _instance,
                                                  std::uint16_t _port,
                                                  bool _reliable,
                                                  bool _magic_cookies_enabled,
                                                  bool _offer) = 0;
    

    application的应用实现内容较多,在下一篇中,进行详细的说明。

    展开全文
  • 浅谈SomeIP以及在AutoSAR中的运用

    千次阅读 2020-11-05 23:16:16
    SomeIP的由来 (以下文章来源于Vehicle软件开发 ,作者Vehicle软件开发) 随着汽车智能化和网络化的发展,汽车自动驾驶、车载娱乐、远程诊断升级等新技术对车载通信提出了更高的要求。如何将现有的以太网技术运用到...

    SomeIP的由来
    (以下文章来源于Vehicle软件开发 ,作者Vehicle软件开发)
    随着汽车智能化和网络化的发展,汽车自动驾驶、车载娱乐、远程诊断升级等新技术对车载通信提出了更高的要求。如何将现有的以太网技术运用到汽车领域是我们面临的一大挑战。而在汽车领域长期都是CAN通信占据主导地位,在汽车中如何找到一种像CAN、MOST一样通信方式,同时支持现有的TCP、UPD协议,又具有网络通信的单播协议,有限制的使用多播和广播通信,加强对以太网的重用性,充分利用以太网传输数据多,安全性高等特点,开发一种合适的中间来满足上面的要求是不容易的,而SomeIP的诞生成功的将以太网通信作为一种中间件成功运用到了车载通信领域。

    SomeIP 简介

    SomeIP (Scalable service-Oriented Middlewareover IP) 是车载以太网的一种通信协议。对于熟悉CAN通信的开发者而言,CAN通信一般属于周期或者触发的形式在总线上传输的,而SOMEIP则不同,它是在接收方有需求的时候才发送,他是一种以服务为导向的数据通信方式。

    SomeIP通信协议基于以太网通信协议传输,在一帧以太网数据中的位置如下所示
    在这里插入图片描述
    SomeIP数据包主要包括两大部分,分别是Header和Data。在传输的过程中可以通过TCP和UDP两种通信数据协议进行传输。SomeIP定义的通信方式主要包括四大类。分别是:

    1. Methods:Methods包含了请求后有应答的Method,和请求后没有应答的Method(Fire&Forget)。

    2. Event:当某种事情发生后,服务端向客户端发送的Message。

    3. Field:Get/Set/Notifier某种属性或者状态。

    4. EventGroup:用来进行publish/subscribe处理Eventsand Fields的通信的逻辑组。

    其中SomeIP中与数据通信相关的几个术语如下:

    1. Request/Response:客户端向服务端请求特定的报文,然后服务端将相应的数据报文返回给客户端。

    2. Fire&Forget:客户端调用服务端方法的报文,通过请求完成方法远程调用;

    3. Notification:对应Event接口类型,类似CAN报文,在特定的事件触发下,服务端会发给客户端一个notification报文主要包括Cyclic事件、数据Changed等

    4. Publish/Subscribe概念:主要用于SomeIP的SD(服务发现),客户端首先订阅相关的服务,只有订阅成功后,才允许进行Notification通信。

    5. Field:一个可被远程访问的属性。主要包含三种类型的数据通信Getter、Setter和Notifier。其中Getter读取属性值,请求报文的payload为空,响应报文中含有当前属性值;Setter设置属性值,将预设值置于请求报文的payload中,属性的设置结果放于响应报文中,Notifier类似于Event,Notifier在订阅完成后,会立即发送InitialEvent,通知当前值。

    SomeIP面向服务的通信机制分两类:分别是请求应答类和提交订阅类。其中请求应答类型的数据主要包括 Fire&Forget通信,Method、Getter、Setter类型的数据通信;而提交订阅类通信主要包括Event和Field中的Notifier。

    Method通信

    分为有应答的通信Request&Response和无应答的Fire&Forget通信

    Request&Response:
    在这里插入图片描述
    Fire&Forget:
    在这里插入图片描述
    Field通信

    主要包括三种类型,Set、Get、Notifier。其中Set和Get是客户端向服务器发送的一种请求通信,而Notifier是订阅后,服务端的通知。

    Set/Get:
    在这里插入图片描述
    Notifier:
    在这里插入图片描述
    事件通知

    由client向server订阅服务内容,然后server向client自动发布服务内容。
    在这里插入图片描述
    Notification分为Event和Field两类,这两类通知都需要首先使用SoemIP-SD(ServiceDiscovery)来进行服务订阅,然后才能发布通知。区别在于,Event是仅仅是某个事件的发生,只是事件通知,Event没有初始值,同时Event的生命周期没有定义,而Field除了事件通知之外,还具有Getter和Setter的功能,即对信息进行读写的操作,同时带有初始化的事件仅仅在Field中。
    在这里插入图片描述
    SomeIP协议的Header主要包括Message ID (32bit)、Length(32bit)、RequestID(32bit)、ProtocolVersion(8bit)、InterfaceVesion(8bit)、MessageType(8bit)、ReturnCode(8bit)。其中Message ID类似CANID主要用于区分不同的服务和服务接口,其中分为16bit的ServiceID和16bit的MethodID,其中MethodID的最高位为0表示的是Method最高为为1表示的是Event或者Notifier。在SomeIP中由于可以支持多种不同的数据通信,因此可以通过MethodID的最高位来判断具体的通信方式。Length(32bit)表示Request ID至Payload的字节长度;RequestID(32bit)用来响应特定的数据请求和发送,主要包括Client ID用来区分特定的车载ECU的客户端,在整车系统中该值必须唯一,SessionID主要对于Request和Response类型的通信协议的多次调用,每调用一次,sessionID增加1,在其他类型的数据通信中可以根据需要进行选择性使用;ProtocolVersion,表明当前的SOMEIP协议版本信息,当前为0x01;InterfaceVersion表明服务接口主版本信息;Message Type表明具体的通信类型;ReturnCode: 主要用来指明通信中的相关错误的信息。

    SomeIP数据域

    SomeIP的数据部分,用来表明具体的传输数据,对于UDP协议而言:SomeIPHeader +payload ≤1416Byte,对于TCP而言分段传输下SomeIP Header +payload≤4095 而UDP TP Payload可达4G大小。

    SomeIP的序列化

    SomeIP的数据在通信的过程中都会放在对应的数据payload中,但是在数据协议中对于结构体、数据、联合体等不同类型的数据在SomeIP传输中必须按照一定的规则定义成相应的二进制数据流,这个就是SomeIP的序列化操作,在数据的接收端按照相应的规则将二进制的数据流按照同样的规则解析成与发送端一样的实际的数据类型,比如结构体、数组等这个过程就是反序列化操作。

    序列化与反序列化的应用主要在AutoSAR中满足整个软件架构的定义。数据在AutoSAR的定义一般都是用PDU的形式存在的定义了一组大小可以配置的数据。典型的应用就是CAN通信,一般一个PDU代表了一帧报文,一般8个字节或者CANFD中64个字节。同样在以太网通信中数据从PDUR到COM层也是基于PDU来传输的。在COM层的数据也是以单个的信号进行数据传输的,因此在序列化过程中要在数据到COM层之前将SomeIP传输的复杂的数据类型通过序列化的操作解析成单个的数据信号,并按照定义的位置和大小映射到具体的PDU中特定的位置,此时在PDU上就是一个个的紧密排列的信号,而在COM层中直接对具体的信号操作便会在PDU中更新特定位置特定长度的信号。而接收的时候,PDU中的信号会在COM层更新到特定位置特定长度的对应的信号,然后在RTE层根据数据的反序列化操作经SomeIP传递的数据进行整合,在APP层实现对一个结构体、数据或者单独一个信号的操作,从而完成数据的传输。在AutoSAR中的传输示意图如下所示
    在这里插入图片描述
    SomeIP-SD为服务发现,可以被当作SomeIP的一种特殊服务,client可以远程调用Server提供的服务,或者订阅Server发布的内容,那么client是怎么知道Server提供哪些服务呢?就是通过SomeIP-SD来实现服务发现过程的。在SomeIP传输过程中主要用来提供和发现有效的服务,并提交和订阅特定的服务实例,实现SomeIP数据的传输。下面是SomeIP的数据帧定义
    在这里插入图片描述
    SomeIP SD主要是通过UDP进行数据传输的,对于特定的SomeIP的Header,SD有明确的定义,其中MessageID固定为0xFFFF8100;ClientID一般固定为0x0000;InterfaceVersion为0x01;Message type固定为0x02;SessionID在初始化配置为0x0001,在没发送一次数据后便加1;ProtocolVersion为0x01;Flag主要包括RebootFlag和UnicastFlag,用于向全局服务发现信息发送信号,其中包括最近一次Reboot的当前状态以及接收单播消息的能力,同时基于单播传输可以检测Reboot,UnicastFlag设置为1可以接收UnicastMessage。Reserved field为空,当前不需要考虑;EntriesArray分为两类,分别是Service和EventGroup。其中ServiceEntry主要是用于Find或者Offer特定的服务包括Find、Offer、StopService三种类型的操作,EventGroup Entry主要用来提交或者订阅特定的服务事件。其中ServiceEntry三种服务支持多播传输,OfferSevice也可以单播传输,EventGroupEntry只支持单播传输。Option类型主要是Entry的附属信息,主要包括:1.配置信息,可以用来配置服务的名称等;2.在Offer服务中定义服务的优先级;3.声明服务实例(offer引用,Request的目的地址,表明使用它所服务的终端地址)或者订阅端(SubscribeEventgroup引用,Request的源地址)的IP、端口号、传输协议等;4.声明服务端发送多播协议数据传达的终端的IP、端口号等,只能被SubscribeEventgroupAckEntry引用;5.声明发送SD信息的IP、端口号、传输协议,接收端使用该地址代替源地址等。

    SD的数据通信一般分为发现服务、订阅事件组、接收事件,其中发现服务和订阅事件组需要SD完成,接收或者通知事件由SomeIP直接完成。主要的通信流程如下所示

    在这里插入图片描述

    AutoSAR中SomeIP的实现

    SomeIP在AutoSAR中的实现主要包括与SD相关的配置和数据通信协议相关模块的配置。在SD中相互关联的模块主要是SoAd、SD、BSWM三个主要模块,而SoAd下层的模块基本与Eth的通用配置一样,根据需要定义相关的UPD和TCP协议即可。如果采用了像Preevision等SomeIP数据描述文件相关的工具定义好系统描述文件导入到AutoSAR工程中就可以,该部分与CAN的DBC导入原理类似,导入相应的系统描述文件会生成相应的模块,然后根据需要修改即可。对于SD而言,导入相应的SomeIP系统描述文件会生成相应的PDU以及跟SD相关的Service、EventGroup、Method等。对于SD而言根据导入的文件修改相关的配置即可。而对于数据通信相关的配置,由于本人没有做过导入现在还没有查看具体的内容。下面主要介绍下在没有系统描述文件过程中自己对SomeIPSD的实现。

    SD模块配置

    在SD模块中主要定义该节点是作为Client还是Server端使用,在SD中主要的定义的配置选项如下所示

    在这里插入图片描述

    其中General的配置主要包括了定义一些SD的主函数的周期,以及部分API的使能,在使用的时候根据需要选择即可。SdInstanceUnicastRxPdu定义了接收单播PDU的参考,SdInstanceMulticastRxPdu定义了接收多播的PDU、SdInstanceTxPdu定义了发送数据的PDU参考,对于定义的这三个全局的PDU需要且在SoAd模块将该PDU与特定的Socket进行关联,建立起PDU与特定的IP和Port之间的交互,实现Socket数据与PDU数据的关联。

    SdProvidedMethods中主要用于定义SdServerServiceActivationRef,关联到特定的SoAdroutingGroup在Server端来控制激活或者禁用相应的Method。

    SdConsumedMethods中主要用于定义 SdClientServiceActivationRef关联到特定的SoAdroutingGroup在Client端来控制激活或者禁用相应的Method。

    Config中主要定义如下所示,主要是下边标记的一般主要考虑,用于在订阅EventGroup没有ACK下继续尝试订阅的次数和每次的间隔。

    在这里插入图片描述

    SD 如果作为Server使用的时候,配置的参数主要如下所示,其中SdServerTimerd定义了在SD通信过程中相关的时间参数,主要包括了OfferServer的周期时间、Server的存活时间等。TCP/UDPRef在SD层要将相应的服务关联到SoAd定义的数据Connection中,用来获得数据通信的TCP、UPD协议,建立起LocalIP与EndPoint的绑定。其中有两个主要的ID需要区分,SdServerServiceHandleId用于BswM控制相关的状态变换,而SdServerServiceInstanceId指明了特定的服务ID,用来提供相应的服务。

    在这里插入图片描述

    SD Client的定义与Server基本相似,这里就不做介绍,具体的配置内容可以参考相应的AutoSAR标准。

    在这里插入图片描述

    SD定义了相应的EventGroup,只有在服务端定义的服务可以被客户端消费,每次客户端使用相应的服务的时候必须进行订阅特定的EventGroup,订阅成功后,服务端才会提供特定的Event供客户端使用。具体的配置参数如下,其中SdConsumedEventGroupHandleId用作BswM进行控制,而SdConsumedEventGroupId表明特定的ID,用来区分订阅和提供不同的实例,每个SdConsumedEventGroupId包含了多个不同的Event,一旦订阅成功,内部的Event可以通知。对于相关的TCP/UDPRef同样是关联到SoAd中定义的RoutingGroup用来激活接收相应的Event,同时也会用于得到对应的IP地址和Port用于绑定Subscribe EventGroup Entry中的Endpoint。

    在这里插入图片描述

    SD EventHandler作为一个服务实体的EventGroup存在。其中SdEventHandlerEventGroupId 用来标识特定的EventGroup,也就是提供给订阅者使用的特定事件组,而SdEventHandlerHandleId主要用于被BswM模块进行状态控制使用。对于SdEventActivationRef关联到SoAdRoutingGroup用来控制激活与否,激活后在订阅后,才可以提供特定的Event。SdEventTriggeringRef用于触发事件的发送。SdMulticastEventSoConRef主要将其关联到特定的组播连接中,将特定的PDU数据与多播的Socket进行连接。

    在这里插入图片描述

    在SD中主要配置所用的Instance以及对应的EventGroup和Method。同时SD与BSWM建立了对应的控制逻辑。通过BSWM定义相关的参考,APP通过BSWM的接口可以控制SD中的Instanc、EventGroup的Request和Release。根据需要先定义Instance也就是一个特定的服务,然后定义该服务内部的EventGroup,剩下的就是根据相应的SD数据头定义相关的参数即可。其中在SD通信过程中有相关的状态变换的时间参数,根据实际的需要定义即可。在SD中主要定义三个传输数据用的PDU用于和SoAd模块进行数据的交互,其中一个Tx、一个UnicastRx、一个MulticastRx,所有这些PDU都用于SD和SoAd之间的数据交互,用于SomeIPSD端数据的接收和发送,根据SD数据通信中Offer/Find/StopService以及Supscribe/Provice EventGroup等进行具体的选择,同时在SD层要将相应的服务关联到SoAd定义的数据Connection中,用来获得数据通信的TCP、UPD协议,建立起LocalIP与EndPoint的绑定。一旦发现服务,订阅EventGroup成功后,客户端便可以接收服务端发来的事件通知。

    SoAd配置

    SoAd主要将以太网传输的Socket与PDU进行关联。在SomeIP的配置中主要有以下参数
    在这里插入图片描述

    SoAdBswModules用来指定SoAd对于UL(Upper Layer)层的模块,对于SD相关的Socket与PDU的交互UL主要是SD模块,而对于普通的不需要SD介入的SomeIP操作只需要定义为PDUR就可以可,在PDUR层将数据传输到COM层,这一点与CAN基本一致。SoAdSocketConnectionGroup定义特定的连接,将本地IP、Port与远端的IP和Port关联在一起。每一个Connection都关联到有特定的TCP、UDP中,一方面用来控制以太网通信中TCP、UDP连接的打开还是关闭,另一方面定义了TCP、UDP数据如何被接收和发送。SoAdSocketRoute定义了Socket的路由Socket来源,并关联到SocketConnection中,SoAdSocketRouteDest定义了Socket UL层的PDU的目的地址,将UL层的PDU与Socket进行关联,实现了将Socket数据解析成PDU数据,实现了数据的接收。SoAdPduRoute定义了UL层的PDU来源,SoAdPduRouteDest定义了UL层的PDU的目的地址,并且关联到了Socket Connection和RoutingGroup 中,实现了UL层PDU与Socket的关联,实现了PDU数据的发送。SoAdRoutingGroup包含了多个PDU,可以实现对PDU的使能和禁用,同时实现了UL层PDU到TCP/UDP Socket的数据传递。

    SomeIP数据通信

    对于SomeIP中非SD相关的数据操作,在SoAd中将接收和发送的PDU关联到PDUR中即可,通过在PDUR中将SoAd参考的PDU通过PDUR关联到COM层,从而实现以太网数据在COM层的解析。如果采用相关的配置工具配置SomeIP的数据通信矩阵,导入到AutoSAR工具中,根据配置手册对SoAd以及PDUR、COM等模块的修改,达到对SomeIP数据通信的要求即可。除了前面提到的Event和Field中的Notifier外,其它的数据通信方式都可以不需要SD。但是在使用中要注意SomeIP的序列化和反序列化操作即可。如果没有相关的工具来配置SomeIP的数据通信矩阵也是可以实现的,但是比较麻烦,本人在测试中就模仿了CAN的数据通信,自己定义了以太网的数据PDU,定义信号在PDU的位置和长度,可以直接在APP解析以太网的数据,但是这样问题比较多,实现起来遇到复杂的逻辑很难处理,最好定义好SomeIP的通信矩阵,然后导入到工具中使用比较好。

    展开全文
  • 4_SOMEIP 协议处理

    千次阅读 2021-03-10 19:40:03
    [PRS_SOMEIP_00138] 如果服务器运行同一服务的不同实例,属于实例的消息应通过服务器端传输协议端口映射到服务实例。 [PRS_SOMEIP_00535] 所有传输协议绑定应支持在传输层PDU(udp pkg or tcp pkg)中传输多个SOME/IP...
  • 作者结合自身的工作经验介绍SomeIP协议以及在AutoSAR中的实现。汽车不断智能化和网联化的趋势,使得原本的通讯方式(CAN)不堪重负,因此新的需求带来了新的技术,SomeIP应运而生。 1 SomeIP的由来 随着汽车智能化...
  • 一、 Wireshark SOMEIP plugin 1.1 插件安装 Wireshark插件目录:Help -> About Wireshark -> Folders/Pluginshttps://github.com/jamores/eth-ws-someip 解压后,将所有后缀是lua的文件拷贝到Wireshark安装...
  • 1someip基础知识 关于SOME/IP的理解_AgingMoon的博客-CSDN博客_someip 2.vsomeip 安装使用 [someip专题]vsomeip使用以及代码解析1_AgingMoon的博客-CSDN博客 3.hello world代码解析 代码下载,大家请参考 ,以下则...
  • someip安装

    2022-03-09 11:00:58
    cd boost_1_74_0/ ./bootstrap.sh ./b2 link=shared sudo ./b2 install 库文件默认安装到/usr/local/lib/libboost* 头文件默认安装到/usr/local/include/boost ...cd vsomeip mkdir build cd build ...
  • 详细介绍SOMEIP 规范和实现
  • 汽车电子AUTOSAR标准定义的SOMEIP通信协议实现的开源CommonAPI,CommonAPI-SOMEIP,VSomeIP,是一种使用较为广泛的车载以太网应用层协议
  • SOME-IP Intro.pdf

    2020-04-11 15:44:11
    SOME-IP Scalable service-Oriented MiddlewarE over IP • Designed by BMW group in 2011 • It’s compatible to AUTOSAR standard – AUTOSAR 4.0 – basic support for SOME/IP messages already existing....
  • CommonAPI-SomeIP 使用

    千次阅读 2021-01-19 08:39:12
    想了解SOME/IP协议,可以移步: SOME/IP 协议介绍 SOME/IP-SD 深入浅出 上一篇,我们已经可以基于vsomeip实现SOME/IP应用,并且服务端和客户端之间进行消息的通信,消息的内容称为Payload。但是设想一下,如果当...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 117,643
精华内容 47,057
关键字:

SOMEIP