00 SOME/IP nedir — genel bakış
SOME/IP (Scalable service-Oriented MiddlewarE over IP), AUTOSAR standardı kapsamında tanımlanmış, araç içi Ethernet üzerinde servis tabanlı haberleşmeyi sağlayan bir middleware protokolüdür.
Geleneksel CAN/LIN mimarisinde ECU'lar sinyaller aracılığıyla iletişim kurardı: her ECU belirli CAN frame ID'lerini dinler, periyodik olarak kendi ID'leriyle veri yayardı. Servis sayısı ve veri miktarı arttıkça bu yaklaşım yetersiz kaldı. SOME/IP bu sorunu servis odaklı mimari (SOA) ile çözer:
- Her ECU, sunduğu fonksiyonu bir servis olarak bildirir.
- İstemci ECU'lar bu servisi keşfeder ve kullanır.
- Haberleşme TCP veya UDP üzerinden gerçekleşir — Ethernet altyapısından yararlanır.
┌─────────────────────────────────────────────────────────────┐
│ AUTOSAR Katman Modeli │
├─────────────────────────────────────────────────────────────┤
│ Uygulama Katmanı │ ara::com API (Adaptive AUTOSAR) │
│ Middleware │ SOME/IP ← bu rehber │
│ Taşıma │ TCP / UDP │
│ Ağ │ IPv4 / IPv6 │
│ Veri Bağlantısı │ Ethernet (100BASE-T1 / 1000BASE-T1) │
└─────────────────────────────────────────────────────────────┘
Neden SOME/IP?
SOME/IP, AUTOSAR'ın PRS_SOMEIPProtocol ve TPS_ManifestSpecification belgelerinde tanımlanmıştır. Açık kaynak referans implementasyonu vsomeip'tir (COVESA / Eclipse Foundation). RFC yoktur; endüstri standardıdır.
01 Mesaj formatı anatomisi
Her SOME/IP mesajı sabit uzunlukta 16 byte'lık bir başlık taşır. Bu başlık, hangi servise ait hangi metodun çağrıldığını, mesajın ne tür olduğunu ve dönüş kodunu kodlar.
┌─────────────────────────────────────────────────────────────┐
│ SOME/IP Mesaj Başlığı (16 byte) │
├──────────────┬──────────────┬─────────────────────────────┤
│ Message ID │ │ Service ID (16 bit) │
│ (32 bit) │ │ Method ID (16 bit) │
├──────────────┼──────────────┴─────────────────────────────┤
│ Length │ Toplam uzunluk - 8 byte (Header sonrası) │
│ (32 bit) │ │
├──────────────┼─────────────────────────────────────────────┤
│ Request ID │ Client ID (16 bit) │
│ (32 bit) │ Session ID (16 bit) │
├──────┬───────┼───────┬──────────────────────────────────┤
│ PV │ IV │ MType │ Return Code │
│(8b) │(8b) │(8b) │(8b) │
└──────┴───────┴───────┴──────────────────────────────────┘
PV = Protocol Version (0x01) IV = Interface Version
Alanların anlamı
Wireshark ile başlık inceleme
# Service ID: 0x1234, Method ID: 0x0001, Length: 0x0000000C
# Client ID: 0x0001, Session ID: 0x0003
# Proto Ver: 0x01, Iface Ver: 0x01
# Msg Type: 0x00 (REQUEST), Return Code: 0x00 (E_OK)
# Payload: 0xDEAD BEEF
12 34 00 01 # Message ID
00 00 00 0C # Length (8 byte header tail + 4 byte payload)
00 01 00 03 # Request ID
01 01 00 00 # PV IV MType RC
DE AD BE EF # Payload
02 Servis türleri — Method, Event, Field
SOME/IP üç temel iletişim paradigmasını destekler: istek/yanıt (Method), yayın (Event) ve durum yönetimi (Field). Her birinin farklı kullanım senaryosu vardır.
Method — İstek/Yanıt
İstemci, sunucuya bir REQUEST gönderir. Sunucu işlemi yapıp RESPONSE döner. Senkron RPC çağrısına benzer. Method ID 0x0001–0x7FFF aralığındadır.
Client Server
│ │
│── REQUEST (MType=0x00) ──────►│
│ Service 0x1234 │ işlem yap()
│ Method 0x0005 │
│ Session 0x0001 │
│ │
│◄─ RESPONSE (MType=0x80) ──────│
│ Return Code: E_OK │
│ Payload: sonuç │
Fire-and-forget kullanmak istiyorsan Message Type'ı REQUEST_NO_RETURN (0x01) olarak set et. Sunucu yanıt göndermez.
Event — Yayın/Abone
Sunucu, belirli bir olayda veya periyodik olarak abone olan tüm istemcilere NOTIFICATION gönderir. Event ID 0x8001–0xFFFF aralığındadır. UDP multicast veya unicast ile taşınır.
Client A Client B Server (Event Producer)
│ │ │
│── SUBSCRIBE ──────│──────────────────►│
│ │── SUBSCRIBE ─────►│
│ │ │
│◄── NOTIFICATION ──│───────────────────│ (event: 0x8001)
│◄── NOTIFICATION ──│───────────────────│ payload: sensor data
Field — Durum Yönetimi
Field, bir değerin getter/setter/notifier üçlüsüyle yönetilmesini sağlar. Getter bir method (READ), setter başka bir method (WRITE), notifier ise bir event'tir. Değer değiştiğinde notifier tetiklenir.
Method: Klima sıcaklığı ayarla, kapı kilidini aç. Event: Motor devri her 10ms'de yayınla, hız sensörü bildirimi. Field: Araç konumu — abone ol ve değişince bildirim al, mevcut konumu sor.
03 SOME/IP-SD — Servis Discovery
SOME/IP Service Discovery (SOME/IP-SD), ECU'ların ağdaki servisleri dinamik olarak bulmasını ve abone olmasını sağlayan protokoldür. UDP port 30490 üzerinden çalışır.
SD Mesaj Türleri
SD Akış Diyagramı
ECU-A (Client) ECU-B (Server)
│ │
│ [Açılışta] │ [Açılışta]
│ │──► OfferService (multicast)
│ │ Service: 0x1234
│ │ TTL: 3 saniye
│ │ Endpoint: 192.168.1.10:50001
│ │
│◄─── OfferService ─────────────────────│
│ │
│──── SubscribeEventgroup ─────────────►│
│ EventGroup: 0x0001 │
│ Endpoint: 192.168.1.20:50002 │
│ │
│◄─── SubscribeEventgroupAck ───────────│
│ │
│◄══ NOTIFICATION (her 10ms) ══════════│ (veri akışı başlar)
TTL ve Yenileme
OfferService mesajındaki TTL (Time-To-Live) saniye cinsindendir. İstemci TTL süresi dolmadan önce yeni bir Offer görmezse servisi geçersiz sayar. Sunucu TTL/2 süresinde bir tekrar Offer gönderir.
Endpoint Option yapısı
# Length: 0x0009 (9 byte)
# Type: 0x04 (IPv4 Endpoint Option)
# Reserved: 0x00
# IPv4: 192.168.1.10 → C0 A8 01 0A
# Reserved: 0x00
# L4-Proto: 0x11 (UDP) / 0x06 (TCP)
# Port: 50001 → C3 51
00 09 04 00 C0 A8 01 0A 00 11 C3 51
SOME/IP-SD varsayılan multicast adresi 239.192.255.251, port 30490'dır. Ağ switch'inin IGMP snooping'i desteklemesi gerekir; aksi halde multicast tüm portlara flood edilir.
04 vsomeip kütüphanesi — konfigürasyon
vsomeip, COVESA (Connected Vehicle Systems Alliance) bünyesindeki açık kaynak SOME/IP implementasyonudur. Linux/QNX/Windows üzerinde çalışır, C++ API sunar ve JSON dosyasıyla yapılandırılır.
Kurulum
# Bağımlılıklar
sudo apt-get install -y \
libboost-system-dev libboost-thread-dev libboost-log-dev \
cmake g++ git
# vsomeip kaynak kodu
git clone https://github.com/COVESA/vsomeip.git
cd vsomeip
mkdir build && cd build
cmake .. -DENABLE_SIGNAL_HANDLING=1
make -j$(nproc)
sudo make install
JSON Konfigürasyon Dosyası
Her vsomeip uygulaması bir JSON dosyasıyla yapılandırılır. VSOMEIP_CONFIGURATION ortam değişkeni dosyayı gösterir.
{
"unicast": "192.168.1.10", // bu ECU'nun IP adresi
"logging": {
"level": "debug",
"console": true
},
"applications": [
{
"name": "body-control",
"id": "0x1111" // Client ID
}
],
"services": [
{
"service": "0x1234", // Service ID
"instance": "0x0001",
"unreliable": "30501", // UDP port
"reliable": {
"port": "30500", // TCP port
"enable-magic-cookies": "false"
}
}
],
"routing": "body-control", // routing manager bu app'ta
"service-discovery": {
"enable": "true",
"multicast": "239.192.255.251",
"port": "30490",
"protocol": "udp",
"initial_delay_min": "10",
"initial_delay_max": "100",
"repetitions_max": "3",
"ttl": "3"
}
}
Temel API çağrıları
05 Event group ve subscribe
SOME/IP Event'leri, event group'lar altında organize edilir. İstemci bir event group'a abone olur; bu group içindeki tüm event'leri almaya başlar.
Event group kavramı
Bir servis birden fazla event içerebilir. Bu event'ler mantıksal gruplar halinde organize edilir. İstemci tüm event'lere değil, yalnızca ilgilendiği event group'a abone olur. Bu, gereksiz ağ trafiğini önler.
// Service ID: 0x1234, Event ID: 0x8001, EventGroup: 0x0001
const vsomeip::service_t SERVICE = 0x1234;
const vsomeip::instance_t INSTANCE = 0x0001;
const vsomeip::event_t EVENT_ID = 0x8001;
const vsomeip::eventgroup_t EG_ID = 0x0001;
// Event'i tanımla ve event group'a ekle
std::set<vsomeip::eventgroup_t> its_groups;
its_groups.insert(EG_ID);
app->offer_event(
SERVICE, INSTANCE, EVENT_ID,
its_groups,
vsomeip::event_type_e::ET_FIELD, // ET_EVENT veya ET_FIELD
std::chrono::milliseconds::zero(), // cycle time (0 = on-change)
false, // change_resets_cycle
true, // update_on_change
nullptr, // payload filter
vsomeip::reliability_type_e::RT_UNRELIABLE
);
// Servisi duyur
app->offer_service(SERVICE, INSTANCE);
// Payload gönder (event tetiklendiğinde)
auto its_payload = vsomeip::runtime::get()->create_payload();
std::vector<vsomeip::byte_t> data = { 0x01, 0x02, 0x03 };
its_payload->set_data(data);
app->notify(SERVICE, INSTANCE, EVENT_ID, its_payload);
// Servisi talep et
app->request_service(SERVICE, INSTANCE);
// Event group'a abone ol
app->request_event(SERVICE, INSTANCE, EVENT_ID,
its_groups, vsomeip::event_type_e::ET_FIELD);
app->subscribe(SERVICE, INSTANCE, EG_ID);
// Bildirim handler'ı kaydet
app->register_message_handler(
SERVICE, INSTANCE, EVENT_ID,
[](std::shared_ptr<vsomeip::message> msg) {
auto payload = msg->get_payload();
std::cout << "Event alındı, uzunluk: "
<< payload->get_length() << std::endl;
// payload->get_data() ile bayt erişimi
}
);
ET_FIELD türündeki event'ler, yeni bir abone bağlandığında mevcut (cache'lenmiş) değeri hemen gönderir. ET_EVENT ise sadece değişiklik olduğunda bildirim yapar. Araç koltuk pozisyonu gibi "mevcut durum" değerleri için ET_FIELD tercih edilir.
06 C++ uygulama örneği
İki vsomeip uygulaması: biri servis sunar (server), diğeri servisi bulup hem method çağırır hem event'e abone olur (client).
Sunucu — service_server.cpp
// g++ service_server.cpp -lvsomeip3 -lboost_system -lboost_thread -o server
#include <vsomeip/vsomeip.hpp>
#include <iostream>
#include <thread>
#include <chrono>
static const vsomeip::service_t SVC = 0x1234;
static const vsomeip::instance_t INST = 0x0001;
static const vsomeip::method_t MTH = 0x0001; // get_temperature
static const vsomeip::event_t EVT = 0x8001; // temperature_update
static const vsomeip::eventgroup_t EG = 0x0001;
std::shared_ptr<vsomeip::application> app;
void on_message(std::shared_ptr<vsomeip::message> request) {
// Method isteğini yanıtla
auto response = vsomeip::runtime::get()->create_response(request);
std::vector<vsomeip::byte_t> data = { 0x00, 0x50 }; // 80°C (örnek)
auto payload = vsomeip::runtime::get()->create_payload();
payload->set_data(data);
response->set_payload(payload);
app->send(response);
std::cout << "Method çağrısı yanıtlandı\n";
}
int main() {
app = vsomeip::runtime::get()->create_application("temperature-server");
app->init();
// Event tanımla
std::set<vsomeip::eventgroup_t> groups = { EG };
app->offer_event(SVC, INST, EVT, groups,
vsomeip::event_type_e::ET_FIELD);
// Method handler
app->register_message_handler(SVC, INST, MTH, on_message);
app->offer_service(SVC, INST);
// Periyodik notification thread
std::thread notifier([&]() {
uint16_t temp = 70;
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
auto pl = vsomeip::runtime::get()->create_payload();
pl->set_data({ (vsomeip::byte_t)(temp >> 8),
(vsomeip::byte_t)(temp & 0xFF) });
app->notify(SVC, INST, EVT, pl);
temp++;
}
});
app->start(); // blocking
notifier.join();
return 0;
}
İstemci — service_client.cpp
#include <vsomeip/vsomeip.hpp>
#include <iostream>
static const vsomeip::service_t SVC = 0x1234;
static const vsomeip::instance_t INST = 0x0001;
static const vsomeip::method_t MTH = 0x0001;
static const vsomeip::event_t EVT = 0x8001;
static const vsomeip::eventgroup_t EG = 0x0001;
std::shared_ptr<vsomeip::application> app;
void on_availability(vsomeip::service_t s, vsomeip::instance_t i, bool available) {
if (available) {
std::cout << "Servis bulundu, method çağrılıyor...\n";
// Method isteği oluştur
auto req = vsomeip::runtime::get()->create_request();
req->set_service(s);
req->set_instance(i);
req->set_method(MTH);
app->send(req);
// Event group'a abone ol
std::set<vsomeip::eventgroup_t> groups = { EG };
app->request_event(s, i, EVT, groups,
vsomeip::event_type_e::ET_FIELD);
app->subscribe(s, i, EG);
}
}
void on_message(std::shared_ptr<vsomeip::message> msg) {
auto data = msg->get_payload()->get_data();
uint16_t temp = (data[0] << 8) | data[1];
std::cout << "Sıcaklık: " << temp << " °C\n";
}
int main() {
app = vsomeip::runtime::get()->create_application("temperature-client");
app->init();
app->register_availability_handler(SVC, INST, on_availability);
app->register_message_handler(SVC, INST, MTH, on_message); // response
app->register_message_handler(SVC, INST, EVT, on_message); // notification
app->request_service(SVC, INST);
app->start();
return 0;
}
Derleme ve çalıştırma
g++ service_server.cpp -lvsomeip3 -lboost_system -lboost_thread -o server
g++ service_client.cpp -lvsomeip3 -lboost_system -lboost_thread -o client
# Terminal 1 — sunucu başlat
VSOMEIP_CONFIGURATION=./vsomeip-server.json ./server
# Terminal 2 — istemci başlat
VSOMEIP_CONFIGURATION=./vsomeip-client.json ./client
07 Güvenlik — TLS ve erişim kontrolü
Araç içi ağların güvenliği artan öneme sahiptir. SOME/IP, TLS ile şifrelenebilir ve ara::com güvenlik politikasıyla erişim denetlenebilir.
SOME/IP-TP over TLS
SOME/IP TCP bağlantıları TLS 1.3 ile şifrelenebilir. vsomeip, OpenSSL/wolfSSL entegrasyonuyla bunu destekler. Sertifika yönetimi AUTOSAR Identity and Access Management (IAM) veya basit PKI altyapısıyla yapılır.
{
"security": {
"check_credentials": true,
"allow_remote_clients": false
},
"tls": {
"enabled": true,
"certificate": "/etc/vsomeip/certs/ecu.crt",
"private_key": "/etc/vsomeip/certs/ecu.key",
"ca_certificate": "/etc/vsomeip/certs/ca.crt"
}
}
Erişim Kontrol Politikası
vsomeip, her uygulamanın hangi servislerle iletişim kurabileceğini politika dosyasında tanımlar. Bu dosya sistem başlangıcında yüklenir ve runtime'da değiştirilemez.
{
"policies": [
{
"credentials": { "uid": 1001, "gid": 1001 },
"allow": {
"offers": [
{ "service": "0x1234", "instance": "0x0001" }
]
}
},
{
"credentials": { "uid": 1002, "gid": 1002 },
"allow": {
"requests": [
{ "service": "0x1234", "instance": "0x0001" }
]
}
}
]
}
ara::com Güvenlik Modeli
AUTOSAR Adaptive Platform'da ara::com, SOME/IP binding üzerinden güvenlik politikası uygular. Her servis proxy'si UID/GID kimlik bilgileriyle doğrulanır. Manifests içindeki ServiceInstance konfigürasyonu hangi uygulamanın hangi servisi sunabileceğini ya da talep edebileceğini belirler.
vsomeip güvenlik kontrollerini etkinleştirmek için JSON'da "check_credentials": true ayarı zorunludur. Üretim araçlarında bu ayar kapalıysa herhangi bir process herhangi bir servise ulaşabilir — ciddi güvenlik riski.
08 Pratik: Linux ECU Simülasyonu
İki vsomeip instance ile Gateway ↔ Body Control Module haberleşmesini tek Linux makinesinde simüle et. Wireshark SOME/IP dissector ile trafiği incele.
Senaryo
Gateway ECU, araç dışından gelen kapı kilidi komutlarını Body Control Module (BCM) servisine iletir. BCM, kapı durumunu (kilitli/açık) event olarak yayınlar.
┌────────────────┐ SOME/IP Method (lock/unlock) ┌──────────────┐
│ Gateway ECU │ ─────────────────────────────────► │ BCM ECU │
│ 192.168.1.10 │ │ 192.168.1.11│
│ (istemci) │ ◄──── SOME/IP Event (door state) ─ │ (sunucu) │
└────────────────┘ └──────────────┘
vcan0 / lo interface
Sanal interface kurulumu
# Loopback interface ile test (tek makine)
sudo ip addr add 192.168.1.10/24 dev lo label lo:gw
sudo ip addr add 192.168.1.11/24 dev lo label lo:bcm
# Ya da iki sanal Ethernet interface oluştur
sudo ip link add veth-gw type veth peer name veth-bcm
sudo ip addr add 192.168.1.10/24 dev veth-gw
sudo ip addr add 192.168.1.11/24 dev veth-bcm
sudo ip link set veth-gw up
sudo ip link set veth-bcm up
# Multicast route ekle (SD için)
sudo ip route add 239.192.255.251/32 dev veth-gw
Wireshark SOME/IP Dissector
# Wireshark >= 2.0 SOME/IP desteği yerleşiktir
# Dissector etkinleştirme: Analyze → Decode As
# UDP port 30490 → SOMEIP-SD
# UDP/TCP port 30500/30501 → SOMEIP
# Komut satırından tshark ile yakalama
tshark -i lo \
-d 'udp.port==30490,someipsd' \
-d 'udp.port==30501,someip' \
-T fields \
-e someip.serviceid \
-e someip.methodid \
-e someip.msgtype
# SOME/IP-SD Offer mesajlarını filtrele
tshark -r capture.pcap -Y 'someipsd.type == 1'
Senaryo çalıştırma
# Terminal 1 — BCM (sunucu)
VSOMEIP_CONFIGURATION=./bcm-config.json \
VSOMEIP_APPLICATION_NAME=bcm-ecu \
./bcm_server
# Terminal 2 — Gateway (istemci)
VSOMEIP_CONFIGURATION=./gw-config.json \
VSOMEIP_APPLICATION_NAME=gateway-ecu \
./gw_client
# Beklenen çıktı (Gateway):
# [info] BCM servisi bulundu: 0x1234/0x0001
# [info] Kapı durumu event alındı: LOCKED
# [info] unlock() methodu yanıtlandı: E_OK
# [info] Kapı durumu event alındı: UNLOCKED
Bu simülasyonu genişletmek için: UDS servisi ekle (bkz. UDS rehberi), DoIP üzerinden tanılama akışı kur (bkz. DoIP rehberi) ya da AUTOSAR Adaptive manifest ile ara::com binding yaz (bkz. AUTOSAR Adaptive rehberi).