Otomotiv Middleware
TEKNİK REHBER OTOMOTİV MİDDLEWARE DoIP ISO 13400 2026

DoIP
Diagnostics over IP — ISO 13400.

Modern araçlarda OBD-2 konnektörünün yerini alan Ethernet tanılama protokolü — UDS'yi IP ağı üzerinden taşır.

00 DoIP nedir — ISO 13400

DoIP (Diagnostics over Internet Protocol), ISO 13400 standardıyla tanımlanan ve UDS diagnostics mesajlarını Ethernet/IP ağı üzerinden taşıyan protokoldür.

Geleneksel OBD-II tanılama, fiziksel bir D-Sub konnektör (OBD-II port) üzerinden CAN bus'a doğrudan erişim sağlardı. Modern araçlar zonal mimariye geçtikçe ve araç içi Ethernet yaygınlaştıkça bu yaklaşım yetersiz kaldı:

  • Yüzlerce ECU'ya tek fiziksel port üzerinden ulaşmak olanaksız
  • OTA (over-the-air) güncelleme için fiziksel bağlantı zorunlu olmamalı
  • Büyük firmware dosyaları CAN'ın 1 Mbps bant genişliğinde çok yavaş aktarılır
  ┌──────────────────────────────────────────────────────────────┐
  │                    DoIP Ağ Topolojisi                        │
  ├──────────────────────────────────────────────────────────────┤
  │                                                              │
  │  [Harici Tester / OTA Server]                                │
  │          │                                                   │
  │          │ Ethernet / WiFi / LTE                             │
  │          ▼                                                   │
  │  [DoIP Gateway / VCI (Vehicle Communication Interface)]      │
  │     ├── 192.168.1.100  (harici interface)                    │
  │     └── 10.0.0.1       (araç içi interface)                  │
  │          │                                                   │
  │          │ Araç içi Ethernet (100BASE-T1)                    │
  │          ├── [ECU-1 DoIP Node]  10.0.0.10                   │
  │          ├── [ECU-2 DoIP Node]  10.0.0.11                   │
  │          └── [ECU-3 DoIP Node]  10.0.0.12                   │
  │                                                              │
  └──────────────────────────────────────────────────────────────┘
    

DoIP'in CAN Diagnostics ile farkı

Bant Genişliği
100 Mbps / 1 Gbps Ethernet vs. CAN 1 Mbps. Büyük firmware dosyaları dakikalar yerine saniyeler içinde.
Uzaktan Erişim
OTA güncelleme için araç üreticisi sunucusundan direkt bağlantı. Servis merkezine gerek yok.
Çoklu ECU
DoIP Gateway, tek TCP bağlantısı üzerinden farklı ECU'lara (logical address ile) mesaj yönlendirir.
Güvenlik
TLS üzerinden DoIP (DoIP over TLS) ile şifreli tanılama. CAN bus'ta şifreleme yoktur.
STANDART PORT

DoIP, UDP ve TCP port 13400 kullanır. Vehicle Identification UDP üzerinden, Routing Activation ve Diagnostic Messages TCP üzerinden çalışır. Port 13400, IANA'ya kayıtlıdır.

01 Ağ topolojisi detayı

DoIP'te her katılımcının bir Logical Address (LA) ve bir Physical Address (IP) vardır. Gateway, dışarıdan gelen tanılama isteklerini doğru ECU'ya logical address ile yönlendirir.

Adres yapısı

Logical Address (LA)
2 byte'lık ECU kimliği. AUTOSAR konfigürasyonunda tanımlanır. 0x0E00: tester, 0x0E80–0x0EFF: ECU'lar tipik aralık.
External Test Equipment Address
Tester (PC, OTA server) tipik olarak 0x0E00 kullanır.
DoIP Gateway Address
Gateway'in LA'sı, tipik olarak 0x0001 veya 0x0E80.
ECU Node Address
Her ECU'nun benzersiz LA'sı. Örnek: 0x0E81 (Engine), 0x0E82 (ABS), 0x0E83 (BCM).
Örnek araç Logical Address haritası
# Tipik LA tahsisi
0x0E00  → Harici Tester (OBD dongle, laptop, OTA server)
0x0E80  → DoIP Gateway / Central VCI
0x0E81  → Engine Control Unit (ECM)
0x0E82  → Transmission Control Unit (TCM)
0x0E83  → Anti-lock Braking System (ABS)
0x0E84  → Body Control Module (BCM)
0x0E85  → Airbag Control Unit (ACU)
0x0E86  → Instrument Cluster (IPC)

02 DoIP mesaj yapısı

Her DoIP mesajı 8 byte'lık Generic Header ile başlar. Header, protocol versiyonu, mesaj tipini ve payload uzunluğunu tanımlar.

  ┌─────────────────────────────────────────────────────────────┐
  │                   DoIP Generic Header (8 byte)              │
  ├──────────┬──────────┬──────────────┬───────────────────────┤
  │ Protocol │ Inverse  │ Payload Type │ Payload Length        │
  │ Version  │ Protocol │  (16 bit)    │   (32 bit)            │
  │  (8 bit) │ Version  │              │                       │
  │          │  (8 bit) │              │                       │
  └──────────┴──────────┴──────────────┴───────────────────────┘
    

Header Alanları

Protocol Version
ISO 13400-2:2012 için 0x02, 2019 revizyonu için 0x03.
Inverse Protocol Version
Protocol Version'ın bitwise NOT'u: 0xFD (0x02 için) veya 0xFC (0x03 için). Header bütünlük kontrolü.
Payload Type
Mesaj türünü belirler. Her mesaj tipi farklı bir 16 bit kod taşır.
Payload Length
Header sonrasındaki veri uzunluğu (byte). Header dahil değil.

Payload Type Tablosu

0x0000 — Generic Header NACK
Hatalı header alındığında gönderilir. NACK kodu 1 byte payload içerir.
0x0001 — Vehicle Identification Request
Tester, ağdaki DoIP node'larını keşfetmek için UDP broadcast gönderir.
0x0004 — Vehicle Announcement / ID Response
DoIP node'u VIN, EID, GID ve IP adresini bildirir.
0x0005 — Routing Activation Request
Tester, TCP bağlantısı kurulduktan sonra routing'i aktive eder.
0x0006 — Routing Activation Response
Gateway tester'ın routing talebini onaylar veya reddeder.
0x0007 — Alive Check Request
Bağlantı canlılık kontrolü.
0x8001 — Diagnostic Message
UDS payload'u taşıyan ana mesaj tipi. Source + Target LA + UDS data içerir.
0x8002 — Diagnostic Message Positive ACK
Gateway, mesajı hedef ECU'ya iletti onayı.
0x8003 — Diagnostic Message Negative ACK
Gateway, mesajı iletemedi. Neden kodu içerir (unknown LA, invalid source address...).

03 Vehicle Identification

Tester, ağdaki DoIP node'larını keşfetmek için UDP broadcast kullanır. Araç VIN, EID ve GID gibi kimlik bilgilerini yanıt olarak döner.

Keşif Akışı

  Tester (UDP)                                DoIP Gateway (UDP)
       │                                               │
       │── VehicleIdentificationRequest ──────────────►│
       │   Dest: 255.255.255.255:13400                 │
       │   Payload Type: 0x0001                        │
       │   Payload Length: 0                           │
       │                                               │
       │◄─ VehicleAnnouncementMessage (Unicast) ───────│
       │   VIN:    "WBAC5441X1LB12345" (17 byte)       │
       │   LA:     0x0E80                              │
       │   EID:    6 byte (MAC address)                │
       │   GID:    6 byte (Group ID)                   │
       │   FTA:    0x00 (No further action)            │
       │   SYNC:   0x10 (VIN + LA sync'd)              │
    

VIN ile arama

Belirli bir VIN'e sahip aracı bulmak için VehicleIdentificationRequestWithVIN mesajı gönderilir (Payload Type 0x0003). Sadece eşleşen araç yanıt verir.

DoIP Vehicle Identification Request — ham çerçeve
# Generic Header: Proto=0x02, Inv=0xFD, Type=0x0001, Len=0x00000000
02 FD 00 01 00 00 00 00

# VehicleAnnouncement yanıtı (örnek):
# 02 FD 00 04 00 00 00 21  (header, payload 33 byte)
# 57 42 41 43 35 34 34 31 58 31 4C 42 31 32 33 34 35  (VIN: WBAC5441X1LB12345)
# 0E 80                    (Logical Address: 0x0E80)
# 00 1A 2B 3C 4D 5E        (EID: MAC adresi)
# 00 00 00 00 00 00        (GID: 0 = tanımlanmamış)
# 00                       (FurtherActionRequired: 0)
# 10                       (SyncStatus: VIN+GID sync)

EID ve GID

EID (Entity ID)
DoIP varlık kimliği, genellikle Ethernet MAC adresi. Değişmez fiziksel kimlik.
GID (Group ID)
DoIP Gateway grubunun kimliği. Birden fazla Gateway varsa aynı gruba aittir. 0 = tek gateway.

04 Routing Activation

Vehicle Identification'dan sonra tester, TCP bağlantısı kurar ve Routing Activation yaparak tanılama mesajları gönderme iznini alır.

Routing Activation Akışı

  Tester (TCP client)                       DoIP Gateway (TCP server)
       │                                               │
       │── TCP SYN ────────────────────────────────────►│ :13400
       │◄─ TCP SYN-ACK ────────────────────────────────│
       │── TCP ACK ────────────────────────────────────►│
       │                                               │
       │── RoutingActivationRequest ───────────────────►│
       │   Source LA: 0x0E00 (tester)                  │
       │   Activation Type: 0x00 (Default)             │
       │   OEM-specific: 0x00000000                    │
       │                                               │
       │◄─ RoutingActivationResponse ──────────────────│
       │   Tester LA: 0x0E00                           │
       │   Gateway LA: 0x0E80                          │
       │   Response Code: 0x10 (Success)               │
    

Response Code'lar

0x00 — Denied, unknown source address
Tester'ın Logical Address tanınmadı.
0x01 — Denied, all sockets registered
Gateway maksimum bağlantı limitine ulaştı.
0x04 — Denied, missing authentication
OEM kimlik doğrulaması gerekli ve sağlanmadı.
0x10 — Successfully activated
Routing aktif, tanılama mesajları gönderilebilir.
0x11 — Successfully activated (confirmation required)
Aktif, ancak OEM onayı bekleniyor.

Activation Type

0x00 — Default
Standart aktivasyon. Üretim araçlarında yaygın.
0x01 — WWH-OBD
World Wide Harmonized OBD için. Emisyon tanılama.
0xE0–0xFE — OEM-specific
Her OEM kendi aktivasyon tipini tanımlayabilir (örn. yüksek güvenlik seviyesi).

05 Diagnostic Message

Routing Activation başarılı olduktan sonra tester, hedef ECU'ya Diagnostic Message göndererek UDS servisleri çağırabilir.

Diagnostic Message Yapısı

  ┌────────────────────────────────────────────────────────────┐
  │              DoIP Diagnostic Message Payload               │
  ├───────────────┬───────────────┬──────────────────────────┤
  │ Source Address│ Target Address│ UDS User Data             │
  │   (16 bit)    │   (16 bit)    │  (variable length)       │
  │  Tester LA    │  ECU LA       │  0x22 0xF1 0x90 (VIN?)  │
  └───────────────┴───────────────┴──────────────────────────┘
    
DoIP DiagnosticMessage — ham örnek (UDS VIN oku)
# DoIP header: Proto=0x02, Inv=0xFD, Type=0x8001, Len=7 byte
02 FD 80 01 00 00 00 07

# Payload:
# Source LA: 0x0E00 (tester)
0E 00
# Target LA: 0x0E81 (Engine ECU)
0E 81
# UDS: ReadDataByIdentifier, DID=0xF190 (VIN)
22 F1 90

# Gateway → Tester: Positive ACK (0x8002)
02 FD 80 02 00 00 00 05
0E 00   # Tester LA
0E 81   # ECU LA (target)
00      # ACK code: 0x00 = OK

# ECU → Tester (UDS Response via DoIP DiagnosticMessage 0x8001):
02 FD 80 01 00 00 00 18
0E 81   # Source: ECU
0E 00   # Target: Tester
# UDS: 0x62 F1 90 + 17 byte VIN
62 F1 90 57 42 41 43 35 34 34 31 58 31 4C 42 31 32 33 34 35

Negative ACK Nedenleri

0x02 — Invalid source address
Kaynak Logical Address bu socket için geçerli değil.
0x03 — Unknown target address
Hedef Logical Address ağda bulunamadı.
0x04 — Diagnostic message too large
Mesaj Gateway'in desteklediği maksimum boyutu aşıyor.
0x05 — Out of memory
Gateway bellek yetersizliği nedeniyle mesajı işleyemedi.
0x06 — Target unreachable
Hedef ECU'ya ulaşılamıyor (CAN bus hatası, ECU kapalı vb.).

06 Python ile DoIP istemcisi

doipclient kütüphanesi, DoIP protokolünü Python'da soyutlar. Vehicle Identification, Routing Activation ve Diagnostic Message akışlarını otomatik yönetir.

Kurulum

bash
pip install doipclient

Temel kullanım

Python
from doipclient import DoIPClient
from doipclient.messages import *

# DoIP Gateway IP ve port
GATEWAY_IP   = "192.168.1.100"
GATEWAY_PORT = 13400

# Tester ve hedef ECU Logical Address
TESTER_LA = 0x0E00
ECU_LA    = 0x0E81

# İstemci oluştur ve bağlan
client = DoIPClient(GATEWAY_IP, ECU_LA,
                    client_logical_address=TESTER_LA)

# Vehicle Identification (opsiyonel — zaten bilinen IP)
vin_response = client.request_entity_status()
print(f"Gateway durum: {vin_response}")

# Routing Activation otomatik yapılır bağlantıda
# Manuel tetiklemek için:
result = client.request_activation(0x00)  # Default activation
print(f"Routing activation: {result.response_code}")

# Raw UDS mesajı gönder (0x22 F190 = ReadDataByIdentifier VIN)
uds_request = bytes([0x22, 0xF1, 0x90])
response = client.send_doip_payload(
    DiagnosticMessage(TESTER_LA, ECU_LA, uds_request))

print(f"UDS yanıtı: {response.user_data.hex()}")

# Bağlantıyı kapat
client.close()

UDP Vehicle Discovery

Python — ağdaki tüm DoIP node'larını keşfet
from doipclient import DoIPClient
import socket, struct

def discover_doip_nodes(timeout=2.0):
    """UDP broadcast ile ağdaki DoIP node'larını keşfet"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.settimeout(timeout)

    # VehicleIdentificationRequest: 02 FD 00 01 00 00 00 00
    header = struct.pack('!BBHI', 0x02, 0xFD, 0x0001, 0)
    sock.sendto(header, ('255.255.255.255', 13400))

    nodes = []
    try:
        while True:
            data, addr = sock.recvfrom(1024)
            nodes.append({
                'ip': addr[0],
                'vin': data[8:25].decode('ascii', errors='replace'),
                'la':  struct.unpack('!H', data[25:27])[0],
                'eid': data[27:33].hex(':')
            })
    except socket.timeout:
        pass

    sock.close()
    return nodes

for node in discover_doip_nodes():
    print(f"IP: {node['ip']:20s}  VIN: {node['vin']}  LA: {node['la']:#06x}  EID: {node['eid']}")

07 Kombine UDS + DoIP

python-udsoncan, transport katmanı olarak DoIP'i destekler. Bu kombinasyon, UDS'nin tam özellik setini Ethernet üzerinden kullanmayı sağlar.

DoIP transport bağlantısı

Python
import udsoncan
from udsoncan.client import Client
from doipclient import DoIPClient
from doipclient.connectors import DoIPClientUDSConnector

# DoIP bağlantısı
doip = DoIPClient("192.168.1.100", 0x0E81,
                  client_logical_address=0x0E00)

# UDS transport olarak DoIP kullan
conn = DoIPClientUDSConnector(doip)

config = udsoncan.configs.default_client_config.copy()
config['request_timeout'] = 10

with Client(conn, config=config) as uds:
    # Artık tam UDS API'si DoIP üzerinden çalışır

    # Extended session
    uds.change_session(
        udsoncan.services.DiagnosticSessionControl.Session.extendedDiagnosticSession)

    # VIN oku
    result = uds.read_data_by_identifier([0xF190])
    vin = result.service_data.values[0xF190].decode('ascii')
    print(f"VIN: {vin}")

    # DTC oku
    dtcs = uds.get_dtc_by_status_mask(0xFF)
    for dtc in dtcs.service_data.dtcs:
        print(f"DTC: {dtc.id:06X}")

doip.close()

Firmware flash senaryosu (DoIP + UDS)

Python — ECU flash via DoIP
def doip_flash_ecu(gateway_ip, ecu_la, fw_path, flash_addr):
    """DoIP üzerinden UDS flash akışı"""
    doip = DoIPClient(gateway_ip, ecu_la,
                      client_logical_address=0x0E00)
    conn = DoIPClientUDSConnector(doip)

    with open(fw_path, 'rb') as f:
        firmware = f.read()

    with Client(conn) as uds:
        # Programming session
        uds.change_session(
            udsoncan.services.DiagnosticSessionControl.Session.programmingSession)

        # Security access
        seed = uds.request_seed(0x11).service_data.seed
        uds.send_key(0x12, calculate_key(seed))

        # Request Download
        mem = udsoncan.MemoryLocation(address=flash_addr,
                                      memorysize=len(firmware),
                                      address_format=32, memorysize_format=32)
        result = uds.request_download(mem,
                    udsoncan.DataFormatIdentifier(0x00))
        max_blk = result.service_data.max_length

        # Transfer bloklar
        seq, offset = 1, 0
        while offset < len(firmware):
            chunk = firmware[offset:offset + max_blk - 2]
            uds.transfer_data(seq, chunk)
            offset += len(chunk)
            seq = (seq % 0xFF) + 1

        uds.request_transfer_exit()
        uds.ecu_reset(udsoncan.services.ECUReset.ResetType.hardReset)

    doip.close()
    print("Flash tamamlandı.")
PERFORMANS

DoIP + 100 Mbps araç içi Ethernet ile 10 MB firmware yaklaşık 1–2 saniyede aktarılır (transfer overhead dahil). CAN üzerinden aynı firmware 80+ saniye sürerdi. Modern araçlarda OTA güncellemelerini pratik kılan budur.

08 Pratik: Simülasyon ve End-of-Line flash

Wireshark DoIP dissector ile trafik inceleme, Linux'ta DoIP gateway simülasyonu ve üretim hattı End-of-Line flash akışını uygula.

Wireshark DoIP Dissector

bash
# Wireshark >= 3.0 DoIP desteği yerleşiktir
# TCP port 13400 otomatik olarak DoIP olarak decode edilir

# tshark ile DoIP trafiği yakala
tshark -i eth0 \
    -f 'tcp port 13400 or udp port 13400' \
    -T fields \
    -e doip.type \
    -e doip.sourceaddress \
    -e doip.targetaddress \
    -e doip.uds.service

# Routing Activation mesajlarını filtrele
tshark -r doip_capture.pcap \
    -Y 'doip.type == 0x0005 || doip.type == 0x0006'

# Sadece UDS yanıtlarını göster
tshark -r doip_capture.pcap \
    -Y 'doip.type == 0x8001 and doip.uds.service >= 0x40'

DoIP Gateway Simülasyonu (Python)

Python — minimal DoIP gateway simülatörü
import socket, struct, threading

PROTO_VER    = 0x02
INV_PROTO    = 0xFD
GATEWAY_IP   = '0.0.0.0'
GATEWAY_LA   = 0x0E80
GATEWAY_PORT = 13400
VIN          = b'SIMGW0000000000A'  # 17 byte

def build_header(ptype, length):
    return struct.pack('!BBHI', PROTO_VER, INV_PROTO, ptype, length)

def handle_tcp_client(sock, addr):
    print(f"Bağlantı: {addr}")
    while True:
        data = sock.recv(4096)
        if not data:
            break
        ptype = struct.unpack('!H', data[2:4])[0]

        if ptype == 0x0005:  # Routing Activation Request
            # Yanıt: 0x0006, response code 0x10 (success)
            src_la = struct.unpack('!H', data[8:10])[0]
            payload = struct.pack('!HHHIB',
                src_la, GATEWAY_LA, 0x0000, 0x00000000, 0x10)
            sock.sendall(build_header(0x0006, len(payload)) + payload)
            print(f"  Routing Activation: tester LA={src_la:#06x}")

        elif ptype == 0x8001:  # Diagnostic Message
            src = struct.unpack('!H', data[8:10])[0]
            tgt = struct.unpack('!H', data[10:12])[0]
            uds = data[12:]
            print(f"  DiagMsg: {src:#06x} → {tgt:#06x}, UDS: {uds.hex()}")
            # Positive ACK gönder
            ack_pl = struct.pack('!HHB', src, tgt, 0x00)
            sock.sendall(build_header(0x8002, len(ack_pl)) + ack_pl)
    sock.close()

tcp_srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp_srv.bind((GATEWAY_IP, GATEWAY_PORT))
tcp_srv.listen(5)
print(f"DoIP Gateway simülatörü dinliyor: {GATEWAY_PORT}")
while True:
    c, a = tcp_srv.accept()
    threading.Thread(target=handle_tcp_client, args=(c, a), daemon=True).start()

End-of-Line (EoL) DoIP Flash Akışı

Araç üretim hattında son kontrol istasyonunda ECU'lar programlanır. Bu süreç şu adımları izler:

  EoL Test Sistemi                          Araç DoIP Gateway
       │                                         │
       │── UDP: Vehicle Identification ─────────►│  (araç kimliğini doğrula)
       │◄─ VehicleAnnouncement (VIN) ────────────│
       │                                         │
       │── TCP: Connect + Routing Activation ───►│
       │◄─ Routing Activated ────────────────────│
       │                                         │
       │  [Her ECU için]                         │
       │── UDS: 10 02 (Programming Session) ────►│ ECU LA
       │── UDS: 27 11/12 (SecurityAccess) ──────►│
       │── UDS: 34 (RequestDownload) ────────────►│
       │── UDS: 36 (TransferData × N) ───────────►│  firmware blokları
       │── UDS: 37 (TransferExit) ───────────────►│
       │── UDS: 31 (CheckProgrammingDependency) ─►│
       │── UDS: 11 01 (ECU Reset) ───────────────►│
       │                                         │
       │  [Flash sonrası doğrulama]              │
       │── UDS: 22 F101 (SW Version oku) ────────►│  yeni versiyon kontrolü
       │◄─ 62 F101 [yeni versiyon] ──────────────│
    
SONRAKİ ADIMLAR

DoIP üzerinden UDS konusunda daha fazla bilgi için UDS rehberini incele. AUTOSAR Adaptive sistemlerde DoIP gateway'i yapılandırmak için AUTOSAR Adaptive rehberine bak. Araç sinyal verilerini standartlaştırmak için VSS rehberini incele.