vsomeip之E2E

1、AUTOSAR_E2E

E2E的概念是在运行时对与安全相关的数据交互进行保护,以防止通信链路故障的影响。基本实现方式是在要保护的数据区添加额外的E2E Header。发送端负责添加E2E Header,接收端会对Header进行校验检查,保证数据的完整性。

参考 AUTOSAR_PRS_E2EProtocol Specification R20-11 ,规定了不同的E2E Profiles,如1,2,4,5,6,7,8,11,22等

以E2E Profile 4为例,规范中定义了Profile 4 包含的控制字段Length、Counter、CRC、DataID,以及Header的数据结构

1.1 E2E Profile 4 Header的数据结构

Length : 16位,为了支持可变长度引入此字段。

          Length = user data + E2E Header(CRC + Counter + Length + DataID)

Counter :16位, 取值 0 ~ 0xFFFF

DataID :32位,必须是全局唯一的,用户定义

CRC :32位,应该使用 Crc_CalculateCRC32P4() 函数 [SWS CRCLibrary],CRC32 0x1F4ACFB13多项式   ,确保高检测率和高汉明距离

在 E2E Profile 4, CRC计算包含 整个 E2E Header(CRC字段除外) 和 user data(RS_E2E_08531)

整个Header字段被编码为:

(1)大端:(最重要的字节在前面) - 由Profile规定,PS:高字节在前,低字节在后

(2)LSB(字节内的最低有效位)先传输 - 由TCP/IP总线强制

1.2 Creation of E2E-Header

1.2.1 E2E_P04Project

E2E_P04Project函数执行图表所示的步骤

E2E_P04Protect() 中 ”Verify inputs of the protect function”执行如下的步骤:

"Compute offset" 执行如下步骤

 

 “Write Length” 执行步骤

 “Write Counter”执行步骤:

“Wirte DataID” 执行步骤:

 “Compute CRC”步骤:

“Write CRC” 步骤:

“Increment Counter” 步骤:

 1.2.2 E2E_P04Forward

        E2E Profile 4的E2E_P04Forward()函数由SW-C调用,以保护其应用程序数据,并转发接收 到的E2E-Status,用于基于面向服务通信的信号转换等用例。 如果接收到的 E2E状态等于E2E_P_OK,那么函数的行为应该与E2E_P04Protect()相同。

1.3 Evaluation of the E2E-Header

目录

1、AUTOSAR_E2E

1.1 E2E Profile 4 Header的数据结构

1.2 Creation of E2E-Header

1.2.1 E2E_P04Project

 1.2.2 E2E_P04Forward

1.3 Evaluation of the E2E-Header

1.3.1 E2E_P04Check


        E2E_P04Check函数按照本节中的以下七个图和PRS_E2EProtocol_00367图指定的操作。

E2E_P04Check() 函数中 ”Verify inputs of the check function” 执行步骤

"Read Length" 步骤:

“Read Counter” 步骤:

 “Read DataID” 步骤:

“Read CRC” 步骤:

“Do Checks” 步骤:

 2、vsomeip E2E

 2.1 概要

vsomeip中也实现了E2E的相关机制,包括 Profile 1、Profile 4 和 Profile custom,整体是以插件的形式执行。

e2e源码文件路径: vsomeip-x.x.xx.x/implementation/e2e_protection/

2.2 实现流程

vsomeip E2E的发送 protecter 和 接收checker 都是在routing中完成的。以E2E Profile 4 为例分析。

2.2.1 Protect

implementation/routing/routing_manager_impl.cpp

挂载e2e插件

void routing_manager_impl::init() {
    ...
    ...
    ...
    if( configuration_->is_e2e_enabled()) {
        VSOMEIP_INFO << "E2E protection enabled.";

        const char *its_e2e_module = getenv(VSOMEIP_ENV_E2E_PROTECTION_MODULE);
        std::string plugin_name = its_e2e_module != nullptr ? its_e2e_module : VSOMEIP_E2E_LIBRARY;

        auto its_plugin = plugin_manager::get()->get_plugin(plugin_type_e::APPLICATION_PLUGIN, plugin_name);
        if (its_plugin) {
            VSOMEIP_INFO << "E2E module loaded.";
            e2e_provider_ = std::dynamic_pointer_cast<e2e::e2e_provider>(its_plugin);
        }
    }

    if(e2e_provider_) {
        std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> its_e2e_configuration = configuration_->get_e2e_configuration();
        for (auto &identifier : its_e2e_configuration) {
            if(!e2e_provider_->add_configuration(identifier.second)) {
                VSOMEIP_INFO << "Unknown E2E profile: " << identifier.second->profile << ", skipping ...";
            }
        }
    }
#endif
}

在usr data 发送的时候,给数据添加E2E Header,对消息进行保护

bool routing_manager_impl::send(client_t _client, const byte_t *_data,
        length_t _size, instance_t _instance, bool _reliable,
        client_t _bound_client,
        credentials_t _credentials,
        uint8_t _status_check, bool _sent_from_remote)
e2e_buffer its_buffer;

                if (e2e_provider_) {
                    if ( !is_service_discovery) {
                        service_t its_service = VSOMEIP_BYTES_TO_WORD(
                                _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
                        method_t its_method = VSOMEIP_BYTES_TO_WORD(
                                _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
#ifndef ANDROID
                        if (e2e_provider_->is_protected({its_service, its_method})) {
                            // Find out where the protected area starts 定位CRC计算起始位置
                            size_t its_base = e2e_provider_->get_protection_base({its_service, its_method});

                            // Build a corresponding buffer 将需要Protect的部分拷贝出来
                            its_buffer.assign(_data + its_base, _data + _size);

                            e2e_provider_->protect({ its_service, its_method }, its_buffer, _instance);

                            // Prepend header 将someip头插入protect数据区前面
                            its_buffer.insert(its_buffer.begin(), _data, _data + its_base);

                            _data = its_buffer.data();
                       }
#endif
                    }
                }

implementation/e2e_protection/e2e_provider_impl.cpp

 根据配置文件的设置,映射到不同的profile实现

bool e2e_provider_impl::add_configuration(std::shared_ptr<cfg::e2e> config)
{
    if (config->profile == "CRC8" || config->profile == "P01") {
        process_e2e_profile<profile01::profile_config, profile01::profile_01_checker, profile01::protector>(config);
        return true;
    }

    if (config->profile == "CRC32" || config->profile == "CSTM") {
        process_e2e_profile<profile_custom::profile_config, profile_custom::profile_custom_checker, profile_custom::protector>(config);
        return true;
    }

    if (config->profile == "P04") {
        process_e2e_profile<profile04::profile_config, profile04::profile_04_checker, profile04::protector>(config);
        return true;
    }

    return false;
}

获取Protect数据区的起始位置get_protection_base。以Profile 4 为例,此位置依赖于implementation/e2e_pretection/include/e2e/profile/profile04/profile_04.hpp    profile_config中base_的赋值

std::size_t e2e_provider_impl::get_protection_base(e2exf::data_identifier_t id) const
{
    const auto found_base = custom_bases_.find(id);
    if (found_base != custom_bases_.end())
        return (found_base->second);

    return (0);
}
// [SWS_E2E_00200]
struct profile_config {
    profile_config() = delete;

    profile_config(uint32_t _data_id, size_t _offset,
            size_t _min_data_length, size_t _max_data_length,
            uint16_t _max_delta_counter)
        : data_id_(_data_id), offset_(_offset),
          min_data_length_(_min_data_length), max_data_length_(_max_data_length),
          max_delta_counter_(_max_delta_counter),
          base_(VSOMEIP_SOMEIP_HEADER_SIZE) { //起始位置包含someip Header的8个字节,根据需要自行修改
    }
    profile_config(const profile_config &_config) = default;
    profile_config &operator=(const profile_config &_config) = default;

    // [SWS_E2E_00334]
    uint32_t data_id_;
    size_t offset_; // This must be configured in bit but as a multiple of 8.
                    // As we must use it as an index, we do the math once at
                    // configuration time and use the correct data type here.
                    // Thus, this value is always the byte where the CRC starts.
    size_t min_data_length_;
    size_t max_data_length_;
    uint16_t max_delta_counter_;

    // SOME/IP base
    size_t base_;
};

implementation/e2e_protection/src/e2e/profile/profile04/protector.cpp

AUTOSAR E2E Profile 4 Protect报头创建

void
protector::protect(e2e_buffer &_buffer, instance_t _instance) {
    std::lock_guard<std::mutex> lock(protect_mutex_);

    if (_instance > VSOMEIP_E2E_PROFILE04_MAX_INSTANCE) {
        VSOMEIP_ERROR << "E2E Profile 4 can only be used for instances [1-255]";
        return;
    }

    /** @req: [SWS_E2E_00363] */
    if (verify_inputs(_buffer)) {

        /** @req [SWS_E2E_00364] */
        write_16(_buffer, static_cast<uint16_t>(_buffer.size()), 0);

        /** @req [SWS_E2E_00365] */
        write_16(_buffer, counter_, 2);

        /** @req [SWS_E2E_00366] */
        uint32_t its_data_id(uint32_t(_instance) << 24 | config_.data_id_);
        write_32(_buffer, its_data_id, 4);

        /** @req [SWS_E2E_00367] */
        uint32_t its_crc = profile_04::compute_crc(config_, _buffer);

        /** @req [SWS_E2E_0368] */
        write_32(_buffer, its_crc, 8);

        /** @req [SWS_E2E_00369] */
        increment_counter();
    }
}

implementation/e2e_protection/src/e2e/profile/profile04/profile_04.cpp

Profile 4  crc计算

uint32_t profile_04::compute_crc(const profile_config &_config, const e2e_buffer &_buffer) {

    buffer_view its_before(_buffer, _config.offset_ + 8);
    uint32_t computed_crc = e2e_crc::calculate_profile_04(its_before);

    if (_config.offset_ + 12 < _buffer.size()) {
        buffer_view its_after(_buffer, _config.offset_ + 12, _buffer.size());
        computed_crc = e2e_crc::calculate_profile_04(its_after, computed_crc);
    }

    return (computed_crc);
}

implementation/e2e_protection/src/crc/crc.cpp

uint32_t e2e_crc::calculate_profile_04(buffer_view _buffer_view, const uint32_t _start_value) {

    uint32_t crc = (_start_value ^ 0xFFFFFFFFU);

    for (uint8_t byte : _buffer_view)
        crc = lookup_table_profile_04_[static_cast<uint8_t>(byte ^ crc)] ^ (crc >> 8U);

    return (crc ^ 0xFFFFFFFFU);
}

const uint32_t e2e_crc::lookup_table_profile_04_[256] = {
    0x00000000U, 0x30850FF5U, 0x610A1FEAU, 0x518F101FU, 0xC2143FD4U, 0xF2913021U, 0xA31E203EU, 0x939B2FCBU,
    0x159615F7U, 0x25131A02U, 0x749C0A1DU, 0x441905E8U, 0xD7822A23U, 0xE70725D6U, 0xB68835C9U, 0x860D3A3CU,
    0x2B2C2BEEU, 0x1BA9241BU, 0x4A263404U, 0x7AA33BF1U, 0xE938143AU, 0xD9BD1BCFU, 0x88320BD0U, 0xB8B70425U,
    0x3EBA3E19U, 0x0E3F31ECU, 0x5FB021F3U, 0x6F352E06U, 0xFCAE01CDU, 0xCC2B0E38U, 0x9DA41E27U, 0xAD2111D2U,
    0x565857DCU, 0x66DD5829U, 0x37524836U, 0x07D747C3U, 0x944C6808U, 0xA4C967FDU, 0xF54677E2U, 0xC5C37817U,
    0x43CE422BU, 0x734B4DDEU, 0x22C45DC1U, 0x12415234U, 0x81DA7DFFU, 0xB15F720AU, 0xE0D06215U, 0xD0556DE0U,
    0x7D747C32U, 0x4DF173C7U, 0x1C7E63D8U, 0x2CFB6C2DU, 0xBF6043E6U, 0x8FE54C13U, 0xDE6A5C0CU, 0xEEEF53F9U,
    0x68E269C5U, 0x58676630U, 0x09E8762FU, 0x396D79DAU, 0xAAF65611U, 0x9A7359E4U, 0xCBFC49FBU, 0xFB79460EU,
    0xACB0AFB8U, 0x9C35A04DU, 0xCDBAB052U, 0xFD3FBFA7U, 0x6EA4906CU, 0x5E219F99U, 0x0FAE8F86U, 0x3F2B8073U,
    0xB926BA4FU, 0x89A3B5BAU, 0xD82CA5A5U, 0xE8A9AA50U, 0x7B32859BU, 0x4BB78A6EU, 0x1A389A71U, 0x2ABD9584U,
    0x879C8456U, 0xB7198BA3U, 0xE6969BBCU, 0xD6139449U, 0x4588BB82U, 0x750DB477U, 0x2482A468U, 0x1407AB9DU,
    0x920A91A1U, 0xA28F9E54U, 0xF3008E4BU, 0xC38581BEU, 0x501EAE75U, 0x609BA180U, 0x3114B19FU, 0x0191BE6AU,
    0xFAE8F864U, 0xCA6DF791U, 0x9BE2E78EU, 0xAB67E87BU, 0x38FCC7B0U, 0x0879C845U, 0x59F6D85AU, 0x6973D7AFU,
    0xEF7EED93U, 0xDFFBE266U, 0x8E74F279U, 0xBEF1FD8CU, 0x2D6AD247U, 0x1DEFDDB2U, 0x4C60CDADU, 0x7CE5C258U,
    0xD1C4D38AU, 0xE141DC7FU, 0xB0CECC60U, 0x804BC395U, 0x13D0EC5EU, 0x2355E3ABU, 0x72DAF3B4U, 0x425FFC41U,
    0xC452C67DU, 0xF4D7C988U, 0xA558D997U, 0x95DDD662U, 0x0646F9A9U, 0x36C3F65CU, 0x674CE643U, 0x57C9E9B6U,
    0xC8DF352FU, 0xF85A3ADAU, 0xA9D52AC5U, 0x99502530U, 0x0ACB0AFBU, 0x3A4E050EU, 0x6BC11511U, 0x5B441AE4U,
    0xDD4920D8U, 0xEDCC2F2DU, 0xBC433F32U, 0x8CC630C7U, 0x1F5D1F0CU, 0x2FD810F9U, 0x7E5700E6U, 0x4ED20F13U,
    0xE3F31EC1U, 0xD3761134U, 0x82F9012BU, 0xB27C0EDEU, 0x21E72115U, 0x11622EE0U, 0x40ED3EFFU, 0x7068310AU,
    0xF6650B36U, 0xC6E004C3U, 0x976F14DCU, 0xA7EA1B29U, 0x347134E2U, 0x04F43B17U, 0x557B2B08U, 0x65FE24FDU,
    0x9E8762F3U, 0xAE026D06U, 0xFF8D7D19U, 0xCF0872ECU, 0x5C935D27U, 0x6C1652D2U, 0x3D9942CDU, 0x0D1C4D38U,
    0x8B117704U, 0xBB9478F1U, 0xEA1B68EEU, 0xDA9E671BU, 0x490548D0U, 0x79804725U, 0x280F573AU, 0x188A58CFU,
    0xB5AB491DU, 0x852E46E8U, 0xD4A156F7U, 0xE4245902U, 0x77BF76C9U, 0x473A793CU, 0x16B56923U, 0x263066D6U,
    0xA03D5CEAU, 0x90B8531FU, 0xC1374300U, 0xF1B24CF5U, 0x6229633EU, 0x52AC6CCBU, 0x03237CD4U, 0x33A67321U,
    0x646F9A97U, 0x54EA9562U, 0x0565857DU, 0x35E08A88U, 0xA67BA543U, 0x96FEAAB6U, 0xC771BAA9U, 0xF7F4B55CU,
    0x71F98F60U, 0x417C8095U, 0x10F3908AU, 0x20769F7FU, 0xB3EDB0B4U, 0x8368BF41U, 0xD2E7AF5EU, 0xE262A0ABU,
    0x4F43B179U, 0x7FC6BE8CU, 0x2E49AE93U, 0x1ECCA166U, 0x8D578EADU, 0xBDD28158U, 0xEC5D9147U, 0xDCD89EB2U,
    0x5AD5A48EU, 0x6A50AB7BU, 0x3BDFBB64U, 0x0B5AB491U, 0x98C19B5AU, 0xA84494AFU, 0xF9CB84B0U, 0xC94E8B45U,
    0x3237CD4BU, 0x02B2C2BEU, 0x533DD2A1U, 0x63B8DD54U, 0xF023F29FU, 0xC0A6FD6AU, 0x9129ED75U, 0xA1ACE280U,
    0x27A1D8BCU, 0x1724D749U, 0x46ABC756U, 0x762EC8A3U, 0xE5B5E768U, 0xD530E89DU, 0x84BFF882U, 0xB43AF777U,
    0x191BE6A5U, 0x299EE950U, 0x7811F94FU, 0x4894F6BAU, 0xDB0FD971U, 0xEB8AD684U, 0xBA05C69BU, 0x8A80C96EU,
    0x0C8DF352U, 0x3C08FCA7U, 0x6D87ECB8U, 0x5D02E34DU, 0xCE99CC86U, 0xFE1CC373U, 0xAF93D36CU, 0x9F16DC99U
};

2.2.2 Check

消息的验证主要是在收到消息阶段,也是在routing里面实现。

implementation/routing/routing_manager_impl.cpp

void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
        endpoint *_receiver, const boost::asio::ip::address &_destination,
        client_t _bound_client, credentials_t _credentials,
        const boost::asio::ip::address &_remote_address,
        std::uint16_t _remote_port){









    if (e2e_provider_) {
                its_method = VSOMEIP_BYTES_TO_WORD(
                           _data[VSOMEIP_METHOD_POS_MIN],
                           _data[VSOMEIP_METHOD_POS_MAX]);
    #ifndef ANDROID
                if (e2e_provider_->is_checked({its_service, its_method})) {
                    auto its_base =             e2e_provider_->get_protection_base({its_service, its_method});
                    e2e_buffer its_buffer(_data + its_base, _data + _size);
                    e2e_provider_->check({its_service, its_method},
                            its_buffer, its_instance, its_check_status);

                    if (its_check_status != e2e::profile_interface::generic_check_status::E2E_OK) {
                        VSOMEIP_INFO << "E2E protection: CRC check failed for service: "
                                << std::hex << its_service << " method: " << its_method;
                    }
                }
#endif
            }












}

后续函数调用路径与 protect 类似,不再赘述。

3、vsomeip E2E 应用

vsomeip的发行包在 test/e2e_tests中提供了相应profile的应用例程,具体编译过程参考上一篇博客。

3.1 e2e 配置

client 和 service端配置方法相同

"e2e" :
    {
        "e2e_enabled" : "true",  // E2E 插件使能
        "protected" :
        [
            {
                "service_id" : "0xd025",
                "event_id" : "0x0001",
                "profile" : "P04",
                "variant" : "checker",
                "crc_offset" : "64",    //这里为报头偏移的 bit
                "data_id" : "0x1011"    // vsomeip实际发送会用_instance作为最高字节 its_data_id(uint32_t(_instance) << 24 | config_.data_id_);
            },
            {
                "service_id" : "0xd025",
                "event_id" : "0x8001",
                "profile" : "P04",
                "variant" : "checker",
                "crc_offset" : "64",
                "data_id" : "0x2d"
            }
        ]
    },

3.2 E2E Header 注意

加E2E保护时,根据profile4的标准长度,vsome是会覆盖掉E2E报头所在位置对应的data的12个字节,所以E2E报头不是位于 user data 后面的时候,一定要设计出放置报头的空间

3.3 测试数据

修改json配置文件,将报头放置在user data 后面;修改了报头计算的起始位置,从someip的Payload开计算

 

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值