00 RNDIS nedir — protokol ve tarihçe
RNDIS (Remote Network Driver Interface Specification), Microsoft'un USB üzerinden Ethernet benzeri ağ iletişimi sağlamak amacıyla geliştirdiği tescilli protokoldür. Windows XP döneminde tanıtılmış, Windows Phone, bazı Android telefon ve gömülü Linux cihazlarında USB tethering/debug ağı olarak yaygın kullanım alanı bulmuştur.
Temel çalışma prensibi
RNDIS, USB Bulk aktarımları üzerine paketlenmiş bir NDIS mesajlaşma katmanıdır. Fiziksel ethernet kablosu yerine USB kablosunu taşıyıcı (carrier) olarak kullanır; host tarafı bunu standart bir ağ adaptörü olarak görür.
Linux gadget (device) ──USB Bulk EP──► Windows host ──► NDIS ağ adaptörü ──► IP yığını
Protokol mesaj tipleri
| Mesaj | Yön | Açıklama |
|---|---|---|
| REMOTE_NDIS_INITIALIZE | Host → Device | Bağlantı başlatma, versiyon müzakeresi |
| REMOTE_NDIS_QUERY | Host → Device | OID (Object ID) ile cihaz parametresi sorgulama |
| REMOTE_NDIS_SET | Host → Device | OID ile parametre ayarlama (multicast filtresi vb.) |
| REMOTE_NDIS_INDICATE_STATUS | Device → Host | Bağlantı durumu değişikliği bildirimi |
| REMOTE_NDIS_PACKET_MSG | Çift yön | Veri çerçevesi (ethernet frame sarmalı) |
| REMOTE_NDIS_KEEPALIVE | Host → Device | Bağlantı canlılık kontrolü |
Neden hâlâ önemli
01 RNDIS vs CDC ECM vs CDC NCM
USB ağ sınıfı protokolleri arasındaki farkları anlamak, hangi senaryoda hangisini kullanacağınızı belirler. CDC (Communications Device Class) standart IEEE protokolleridir; RNDIS ise Microsoft tescilli uzantısıdır.
| Özellik | RNDIS | CDC ECM | CDC NCM |
|---|---|---|---|
| Standart | Microsoft tescilli | USB-IF CDC 1.2 | USB-IF CDC 1.2 (NCM) |
| Windows desteği | Yerleşik (inbox) | Win 10+ inbox / eski: INF gerekir | Win 10 1903+ inbox |
| Linux host desteği | rndis_host.ko | cdc_ether.ko | cdc_ncm.ko |
| macOS desteği | Hayır (üçüncü taraf) | Evet (native) | Evet (native) |
| Maksimum hız | ~30–40 MB/s | ~40–50 MB/s | ~55–60 MB/s (paket toplama) |
| Çoklu çerçeve (aggregation) | Hayır | Hayır | Evet (NTB) |
| Kontrol kanalı | USB Control EP | CDC Notify EP | CDC Notify EP |
| Ideal senaryo | Windows-only debug | Düşük hız, geniş uyumluluk | Yüksek hız, çapraz platform |
NCM'in RNDIS'e teknik üstünlüğü: NTB yapısı
CDC NCM, Network Transfer Block (NTB) adı verilen bir kapsülleme şeması kullanır. Tek bir USB transferine birden fazla ethernet çerçevesi sığdırabilir (aggregation). Bu, düşük paket boyutlarında USB overhead'ini dramatik biçimde azaltır.
RNDIS: [RNDIS hdr][frame1] | [RNDIS hdr][frame2] | [RNDIS hdr][frame3] ← 3 USB transfer NCM: [NTB hdr][frame1][frame2][frame3] ← 1 USB transfer
Özet tavsiye
02 Linux kernel: usb_f_rndis ve g_rndis
Linux, RNDIS gadget fonksiyonunu iki farklı katman üzerinden sunar: eski g_rndis legacy modülü ve modern usb_f_rndis fonksiyon sürücüsü. Günümüzde configfs üzerinden kullanılan usb_f_rndis tercih edilmelidir.
Kernel modülleri ve bağımlılıklar
# Temel USB Gadget altyapısı
libcomposite # configfs composite framework
u_ether # USB ethernet yardımcı kütüphanesi (gadget tarafı)
# RNDIS fonksiyon sürücüsü
usb_f_rndis # Modern configfs RNDIS fonksiyon sürücüsü
# Legacy (eski yöntem — configfs olmadan)
g_rndis # Tek işlevli RNDIS gadget modülü (kullanımdan kalkmakta)
# UDC sürücüleri (SoC'a göre değişir)
dwc2 # DesignWare USB 2.0 OTG (RPi Zero, i.MX, STM32MP)
dwc3 # DesignWare USB 3.0 (Snapdragon, i.MX8, Renesas R-Car)
chipidea # ChipIdea UDC (i.MX6, eski i.MX)
Kernel konfigürasyonu (menuconfig)
Device Drivers
└── USB support
├── USB Gadget Support [M/Y]
│ ├── USB Gadget precomposed configurations
│ │ └── RNDIS plus CDC Serial Gadget [M] # g_rndis (legacy)
│ └── USB Gadget functions configurable through configfs
│ ├── RNDIS function [M/Y] # usb_f_rndis
│ └── Ethernet Gadget (CDC ECM/NCM) [M/Y]
└── USB Device Controller drivers
├── DesignWare USB2 DRD Core Support [M/Y] # dwc2
└── DesignWare USB3 DRD Core Support [M/Y] # dwc3
u_ether: gadget tarafı sanal ethernet
u_ether modülü, usb_f_rndis ve usb_f_ncm gibi tüm USB ethernet gadget fonksiyonlarının paylaştığı alt katmandır. UDC üzerinden gelen ham USB paketlerini alır ve kernel'in ağ yığınına usb0 (veya usb1, …) sanal ethernet arayüzü olarak sunar.
usb_f_rndis ──► u_ether (gether_*) ──► netdev (usb0) ──► Linux IP stack
│
└── net_device ops: ndo_open, ndo_start_xmit, ndo_set_mac_address
Legacy g_rndis modülü parametreleri
# Sadece test/hızlı prototipleme için
modprobe g_rndis \
host_addr=12:34:56:78:9a:bc \
dev_addr=12:34:56:78:9a:bd \
idVendor=0x1234 \
idProduct=0x5678
03 configfs ile RNDIS gadget kurulumu
configfs API ile RNDIS gadget'ı adım adım kurun. Bu yöntem production tercihidir: birden fazla fonksiyonu composite gadget olarak birleştirebilir, UDC'yi çalışma zamanında bağlayıp çözebilirsiniz.
Adım 1 — Modülleri yükle
modprobe libcomposite
modprobe usb_f_rndis
# UDC modülü otomatik yüklenmiyorsa:
modprobe dwc2 # veya dwc3, chipidea — SoC'a göre
Adım 2 — Gadget dizin yapısını oluştur
#!/bin/bash
GADGET=/sys/kernel/config/usb_gadget/rndis_gadget
# 1. Gadget oluştur
mkdir -p $GADGET
echo 0x04e8 > $GADGET/idVendor # Samsung örneği (kendi VID'inizi kullanın)
echo 0x6863 > $GADGET/idProduct
echo 0x0100 > $GADGET/bcdDevice
echo 0x0200 > $GADGET/bcdUSB
# 2. Strings
mkdir -p $GADGET/strings/0x409 # İngilizce
echo "MyCompany" > $GADGET/strings/0x409/manufacturer
echo "RNDIS Gadget" > $GADGET/strings/0x409/product
echo "RNDIS0001" > $GADGET/strings/0x409/serialnumber
# 3. Yapılandırma
mkdir -p $GADGET/configs/c.1
echo 250 > $GADGET/configs/c.1/MaxPower # 250 mA
mkdir -p $GADGET/configs/c.1/strings/0x409
echo "RNDIS Config" > $GADGET/configs/c.1/strings/0x409/configuration
# 4. RNDIS fonksiyonu oluştur
mkdir -p $GADGET/functions/rndis.usb0
# MAC adresleri (host ve device)
echo "12:34:56:78:9a:bc" > $GADGET/functions/rndis.usb0/host_addr
echo "12:34:56:78:9a:bd" > $GADGET/functions/rndis.usb0/dev_addr
# 5. Fonksiyonu yapılandırmaya bağla
ln -s $GADGET/functions/rndis.usb0 $GADGET/configs/c.1/
# 6. UDC'ye bağla (mevcut UDC'yi bul ve kullan)
UDC=$(ls /sys/class/udc | head -1)
echo $UDC > $GADGET/UDC
echo "Gadget $UDC'ye bağlandı"
Composite gadget: RNDIS + ACM (serial) aynı anda
# Aynı gadget'a ACM (seri konsol) da ekle
mkdir -p $GADGET/functions/acm.usb0
ln -s $GADGET/functions/acm.usb0 $GADGET/configs/c.1/
# Bağlama sırası önemlidir: RNDIS önce, ACM sonra
ls $GADGET/configs/c.1/
# rndis.usb0 acm.usb0 MaxPower strings/
Windows uyumluluğu için OS Descriptor (WinUSB)
Windows 7 ve altında RNDIS'in otomatik tanınması için Microsoft OS Descriptor gerekir. Bu, Windows'un doğru .inf dosyasını yüklemeden sürücüyü eşleştirmesini sağlar.
# OS Descriptor etkinleştir
echo 1 > $GADGET/os_desc/use
echo 0xcd > $GADGET/os_desc/b_vendor_code
echo "MSFT100" > $GADGET/os_desc/qw_sign
# RNDIS fonksiyonu için compatible ID
echo "RNDIS" > $GADGET/functions/rndis.usb0/os_desc/interface.rndis/compatible_id
echo "5162001" > $GADGET/functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id
# OS Descriptor'ı yapılandırmaya bağla
ln -s $GADGET/configs/c.1 $GADGET/os_desc/
Gadget'ı kapat / UDC'den ayır
# Çalışan gadget'ı devre dışı bırak
echo "" > /sys/kernel/config/usb_gadget/rndis_gadget/UDC
# Temizlik (modülü kaldırmadan önce)
rm /sys/kernel/config/usb_gadget/rndis_gadget/configs/c.1/rndis.usb0
rmdir /sys/kernel/config/usb_gadget/rndis_gadget/functions/rndis.usb0
rmdir /sys/kernel/config/usb_gadget/rndis_gadget/configs/c.1/strings/0x409
rmdir /sys/kernel/config/usb_gadget/rndis_gadget/configs/c.1
rmdir /sys/kernel/config/usb_gadget/rndis_gadget/strings/0x409
rmdir /sys/kernel/config/usb_gadget/rndis_gadget
04 Windows host: sürücü ve tanıma
Linux RNDIS gadget Windows bilgisayara bağlandığında, Windows bunu USB sınıfı kodlarına göre (Class=0xe0, SubClass=0x01, Protocol=0x03) veya OS Descriptor üzerinden tanır ve inbox RNDIS sürücüsünü yükler.
Sürücü yükleme süreci (Windows 10/11)
%windir%\inf\netrndis.inf — RNDIS Miniport sürücüsüWindows Aygıt Yöneticisi'nde beklenen görünüm
Ağ bağdaştırıcıları
└── Remote NDIS Compatible Device
USB denetleyicileri
└── RNDIS Gadget (USB ID: 04e8:6863)
Sorun: "Bilinmeyen Cihaz" görünüyor
OS Descriptor doğru yapılandırılmamışsa veya USB Class kodu yanlışsa Windows RNDIS sürücüsünü otomatik yükleyemez. Manuel sürücü kurulumu gerekir:
; netrndis.inf — manuel kurulum için .inf içeriği
[Version]
Signature = "$Windows NT$"
Class = Net
ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318}
Provider = %Microsoft%
DriverVer = 07/28/2009, 6.30.5454.0
[Manufacturer]
%Microsoft% = Models, NTx86, NTamd64
[Models.NTx86]
%RNDIS.DeviceDesc% = RNDIS.NT, USB\VID_04e8&PID_6863
[RNDIS.NT.ndi]
AddReg = RNDIS.NT.reg
[RNDIS.NT.reg]
HKR, NDI\interfaces, FilterMediaTypes,, "ethernet"
HKR, Ndi, Service,, "RNDIS"
Windows PowerShell ile bağlantı doğrulama
# Ağ adaptörlerini listele
Get-NetAdapter | Where-Object {$_.InterfaceDescription -match "RNDIS"}
# IP adresi kontrol
Get-NetIPAddress -InterfaceAlias "Ethernet*" | Where-Object {$_.AddressFamily -eq "IPv4"}
# Ping testi (Linux cihazın IP'si)
ping 192.168.7.2
05 IP yapılandırması ve Internet Connection Sharing
Linux gadget tarafında usb0 arayüzüne IP atandıktan sonra Windows üzerinden Internet paylaşımı (ICS) veya Linux üzerinden masquerade ile embedded cihaza internet erişimi sağlanabilir.
Linux gadget tarafı — statik IP
# usb0 arayüzü hazır olduğunda
ip link set usb0 up
ip addr add 192.168.7.2/24 dev usb0
# DHCP sunucusu ekle (isteğe bağlı — dnsmasq)
dnsmasq \
--interface=usb0 \
--dhcp-range=192.168.7.100,192.168.7.200,255.255.255.0,12h \
--no-daemon
Linux gadget tarafı — systemd-networkd ile kalıcı yapılandırma
# /etc/systemd/network/10-usb0.network
[Match]
Name=usb0
[Network]
Address=192.168.7.2/24
DHCPServer=yes
[DHCPServer]
PoolOffset=100
PoolSize=20
EmitDNS=yes
DNS=8.8.8.8
Windows ICS (Internet Connection Sharing) — GUI
Windows'ta Wi-Fi bağlantısını RNDIS adaptörüyle paylaşmak için:
Linux gadget tarafında masquerade (NAT) ile internet paylaşımı
Linux cihazın kendisi gateway rolünü üstlenirse (örneğin Raspberry Pi hotspot senaryosu):
# İnternet arayüzü: wlan0 — USB ağ arayüzü: usb0
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
iptables -A FORWARD -i usb0 -o wlan0 -j ACCEPT
iptables -A FORWARD -i wlan0 -o usb0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# Kalıcı yapmak için iptables-save
iptables-save > /etc/iptables/rules.v4
SSH erişim testi
# Windows tarafından Linux cihaza SSH (IP'yi DHCP'den aldıktan sonra)
ssh root@192.168.137.2 # ICS ile
ssh root@192.168.7.2 # Statik IP ile
# Linux'tan bağlantı testi
ping -c 4 192.168.137.1 # Windows gateway
curl -s ifconfig.me # Dış IP (internet erişimi varsa)
06 Android / iOS USB tethering ve RNDIS
Android telefonlar USB tethering aktif edildiğinde genellikle RNDIS (veya NCM/ECM) gadget olarak çalışır. Linux host tarafında rndis_host.ko modülü bunu destekler. iOS ise RNDIS yerine CDC ECM kullanır.
Android USB Tethering — Linux host tarafı
# Gerekli modüller
modprobe rndis_host # Android RNDIS desteği
modprobe cdc_ether # Bazı Android cihazlar CDC ECM kullanır
# Bağlantı sonrası ağ arayüzü
ip link show # usb0 veya enp0s20u1 benzeri arayüz oluşur
dmesg | tail -20 # USB tanıma mesajlarını izle
# DHCP ile IP al
dhclient usb0
# veya
udhcpc -i usb0
# Bağlantı testi
ping 192.168.42.129 # Android default tethering IP
Android sürüm farkları
| Android Sürümü | Protokol | Linux modülü |
|---|---|---|
| 4.x – 9 (Pie) | RNDIS | rndis_host.ko |
| 10+ | CDC NCM (birincil) | cdc_ncm.ko |
| 10+ (fallback) | RNDIS | rndis_host.ko |
| Bazı üreticiler | CDC ECM | cdc_ether.ko |
iOS USB Tethering — Linux host tarafı
# iOS CDC ECM veya ECM/NCM kullanır — RNDIS kullanmaz
modprobe ipheth # iPhone USB Ethernet (ipheth.ko)
# ipheth sürücüsü bağlandıktan sonra
# libusbmuxd gerekebilir (iPhone pairing için)
apt install libimobiledevice-utils usbmuxd
# Arayüz
ip link show # eth0 veya enp0s20u4i1 benzeri arayüz
udhcpc -i eth0
udev kuralı ile otomatik DHCP
# /etc/udev/rules.d/90-usb-tethering.rules
# Android RNDIS bağlandığında otomatik DHCP
ACTION=="add", SUBSYSTEM=="net", ATTRS{idVendor}=="04e8", \
ATTRS{idProduct}=="6863", RUN+="/sbin/udhcpc -i %k"
# Genel RNDIS cihazlar için
ACTION=="add", SUBSYSTEM=="net", ENV{ID_USB_DRIVER}=="rndis_host", \
RUN+="/sbin/dhclient %k"
07 Hata ayıklama — dmesg, lsusb, Wireshark
RNDIS bağlantı sorunlarını sistematik şekilde teşhis etmek için kernel mesajları, USB tanımlayıcıları ve ağ trafiği analizi birlikte kullanılmalıdır.
dmesg ile gadget tarafı izleme
# Gadget tarafında (Linux cihaz)
dmesg -w | grep -E "usb|rndis|g_ether|UDC"
# Beklenen başarılı çıktı
# usb: registered new interface driver rndis_host
# configfs-gadget gadget: rndis_bind_config: OK
# configfs-gadget gadget: high-speed config #1: RNDIS Config
# Bağlantı sonrası
# g_ether gadget: RNDIS RX: host MAC 12:34:56:78:9a:bc
Host tarafında (Linux) modül ve arayüz durumu
# Modül listesi
lsmod | grep -E "rndis|cdc|usbnet"
# USB cihaz tanıma
lsusb -v | grep -A 20 "Remote NDIS"
# Ağ arayüzü durumu
ip link show usb0
ip -s link show usb0 # istatistikler: RX/TX paket sayıları
# Hata sayıcıları
ethtool -S usb0 # sürücü istatistikleri
Linux USB gadget debug: tracefs
# USB gadget event trace etkinleştir
echo 1 > /sys/kernel/debug/tracing/events/gadget/enable
# veya belirli eventlar
echo 1 > /sys/kernel/debug/tracing/events/gadget/usb_ep_queue/enable
cat /sys/kernel/debug/tracing/trace_pipe
# usb_ep_queue: ep=ep1in length=60 status=0
Wireshark ile USB RNDIS paketi yakalama
# Linux host — USB trafiğini yakala
modprobe usbmon
# usbmon arayüzleri: usbmon0 (tüm), usbmon1 (bus 1), ...
lsusb | grep RNDIS # Bus numarasını öğren: Bus 001 → usbmon1
# tcpdump ile düşük seviye USB yakalama
tcpdump -i usbmon1 -w usb_rndis.pcap
# Wireshark'ta açarken: Analyze → Enabled Protocols → RNDIS etkinleştir
# Filtreleme: rndis || usb.transfer_type == 0x03 (Bulk)
Yaygın sorunlar ve çözümleri
| Belirti | Olası neden | Çözüm |
|---|---|---|
| Windows "Bilinmeyen Cihaz" | Yanlış Class/SubClass kodu veya eksik OS Descriptor | OS Descriptor ekle veya manuel .inf yükle |
| Arayüz UP ama ping çalışmıyor | MAC adresi çakışması veya yanlış IP | host_addr/dev_addr farklı MAC'lere ayarla |
| usb0 arayüzü oluşmuyor | u_ether modülü yüklenmemiş | modprobe u_ether |
| Bağlantı sürekli kopuyor | KEEPALIVE timeout — Windows sürücü hatası | CDC NCM'e geç veya keepalive_interval artır |
| Düşük hız (<5 MB/s) | RNDIS agregasyon yok, FS mod | High-Speed UDC kullan, NCM'e geç |
| macOS'ta görünmüyor | RNDIS macOS'ta desteklenmez | CDC NCM kullan |
08 Geçiş rehberi: RNDIS'ten CDC NCM'e
Windows 10 1903 sürümünden itibaren CDC NCM inbox sürücüsüne kavuşmuştur. Yeni projeler için CDC NCM geçişi önerilir: daha yüksek performans, standart uyumluluk ve macOS/Linux'ta native destek.
configfs'de RNDIS'i NCM ile değiştirme
#!/bin/bash
GADGET=/sys/kernel/config/usb_gadget/ncm_gadget
mkdir -p $GADGET
echo 0x1234 > $GADGET/idVendor
echo 0x5678 > $GADGET/idProduct
echo 0x0200 > $GADGET/bcdUSB
mkdir -p $GADGET/strings/0x409
echo "MyCompany" > $GADGET/strings/0x409/manufacturer
echo "CDC NCM Eth" > $GADGET/strings/0x409/product
echo "NCM0001" > $GADGET/strings/0x409/serialnumber
mkdir -p $GADGET/configs/c.1
echo 250 > $GADGET/configs/c.1/MaxPower
# NCM fonksiyonu (RNDIS yerine)
mkdir -p $GADGET/functions/ncm.usb0
echo "12:34:56:78:9a:be" > $GADGET/functions/ncm.usb0/host_addr
echo "12:34:56:78:9a:bf" > $GADGET/functions/ncm.usb0/dev_addr
ln -s $GADGET/functions/ncm.usb0 $GADGET/configs/c.1/
echo $(ls /sys/class/udc | head -1) > $GADGET/UDC
Composite gadget: RNDIS + NCM birlikte (uyumluluk)
Eski ve yeni Windows'u aynı anda desteklemek için her iki fonksiyon aynı composite gadget'a eklenebilir. Windows, desteklediği protokolü otomatik seçer.
# Hem RNDIS hem NCM fonksiyonu oluştur
mkdir -p $GADGET/functions/rndis.usb0
mkdir -p $GADGET/functions/ncm.usb1
echo "aa:bb:cc:dd:ee:00" > $GADGET/functions/rndis.usb0/host_addr
echo "aa:bb:cc:dd:ee:01" > $GADGET/functions/rndis.usb0/dev_addr
echo "aa:bb:cc:dd:ee:02" > $GADGET/functions/ncm.usb1/host_addr
echo "aa:bb:cc:dd:ee:03" > $GADGET/functions/ncm.usb1/dev_addr
# İki ayrı yapılandırma
mkdir -p $GADGET/configs/c.1 # RNDIS için
mkdir -p $GADGET/configs/c.2 # NCM için
echo 250 > $GADGET/configs/c.1/MaxPower
echo 250 > $GADGET/configs/c.2/MaxPower
ln -s $GADGET/functions/rndis.usb0 $GADGET/configs/c.1/
ln -s $GADGET/functions/ncm.usb1 $GADGET/configs/c.2/
echo $(ls /sys/class/udc | head -1) > $GADGET/UDC
Geçiş sonrası fark
| Metrik | RNDIS | CDC NCM |
|---|---|---|
| iperf3 TCP (USB HS) | ~280 Mbit/s | ~420 Mbit/s |
| CPU yükü (TX yoğun) | Yüksek (her çerçeve ayrı URB) | Düşük (NTB agregasyon) |
| macOS uyumluluğu | Hayır | Evet (native) |
| Windows 7 desteği | Evet (inbox) | Kısmi (INF gerekebilir) |
BeagleBone Black — önceden yapılandırılmış RNDIS
BeagleBone Black, Debian imajında /opt/scripts/boot/autoconfigure_usb0.sh betiği ile USB0 arayüzünü RNDIS (veya ECM) olarak otomatik yapılandırır. Windows'ta 192.168.7.2, macOS/Linux'ta 192.168.6.2 varsayılan IP'sidir.
# BBB'de mevcut gadget yapılandırmasını görüntüle
cat /sys/kernel/config/usb_gadget/g-*/UDC
ls /sys/kernel/config/usb_gadget/g-*/functions/
# BBB USB ağı üzerinden SSH
ssh debian@192.168.7.2 # Windows (RNDIS)
ssh debian@192.168.6.2 # macOS/Linux (ECM)