What Does an Embedded Developer Actually Write at Each OSI Layer?

Thread Starter

Embededd

Joined Jun 4, 2025
158
I have a question about the OSI model from an embedded software developer's perspective.

Suppose we have a laptop connected to a Wi-Fi router and an embedded system (sensor + MCU + Wi-Fi module) connected to another router. Both devices communicate over the Internet.

My main focus is understanding what control logic an embedded developer typically writes for the Data Link, Network, and Transport layers.

I can understand writing drivers for hardware interfaces, but I am not clear about what software responsibilities belong to the Data Link layer, what logic belongs to the Network layer (IP), and what logic belongs to the Transport layer (TCP/UDP) in a real project.

I know that nowadays much of this functionality is already available in libraries, firmware, or existing software, so developers often spend more time working on the application side. However, I would like to understand what functionality actually exists inside the Data Link, Network, and Transport layers and what kind of control logic would need to be written if we were implementing them ourselves.

Also, I often hear the term "TCP/IP stack." In C programming, I know a stack as the memory area used for function calls and local variables. What does the word "stack" mean in the networking context?

Could someone explain this using a simple real-world example, such as a sensor node sending data over Wi-Fi to a laptop through the Internet?
 

joeyd999

Joined Jun 6, 2011
6,331
I have a question about the OSI model from an embedded software developer's perspective.

Suppose we have a laptop connected to a Wi-Fi router and an embedded system (sensor + MCU + Wi-Fi module) connected to another router. Both devices communicate over the Internet.

My main focus is understanding what control logic an embedded developer typically writes for the Data Link, Network, and Transport layers.

I can understand writing drivers for hardware interfaces, but I am not clear about what software responsibilities belong to the Data Link layer, what logic belongs to the Network layer (IP), and what logic belongs to the Transport layer (TCP/UDP) in a real project.

I know that nowadays much of this functionality is already available in libraries, firmware, or existing software, so developers often spend more time working on the application side. However, I would like to understand what functionality actually exists inside the Data Link, Network, and Transport layers and what kind of control logic would need to be written if we were implementing them ourselves.

Also, I often hear the term "TCP/IP stack." In C programming, I know a stack as the memory area used for function calls and local variables. What does the word "stack" mean in the networking context?

Could someone explain this using a simple real-world example, such as a sensor node sending data over Wi-Fi to a laptop through the Internet?
To save everyone time, I posed your question to Grok exactly as you wrote it. You can do this too.

Unverified. Caveat emptor.

-----------------

"TCP/IP stack" in networking refers to the protocol stack — a layered collection of protocols (and the software/firmware implementing them) that work together hierarchically. Each layer provides services to the layer above it and uses the layer below it. Data is passed down the stack on transmission (each layer adds its own header — encapsulation) and up the stack on reception (headers are stripped — decapsulation).


This is a conceptual model for modularity and interoperability, visualized as layers "stacked" like building blocks or a layered cake. It is not the same as the call stack in C (the memory area for function frames, locals, and return addresses). The word "stack" here is just a metaphor for layering. The actual implementation is often a library (e.g., lwIP), kernel component, or firmware that provides a clean API (usually Berkeley sockets) so your application code doesn't have to deal with the details below.


The practical model used on the Internet is the TCP/IP model (4 layers). The theoretical OSI model has 7 layers. The layers you asked about map as:


  • Transport → OSI Layer 4 (TCP/UDP)
  • Network → OSI Layer 3 (IP, routing, addressing)
  • Data Link → OSI Layer 2 (framing, MAC addressing, local error handling; includes 802.11 for Wi-Fi)

(Physical = OSI Layer 1 — radio bits, handled in hardware/firmware.)

Real-World Example

A temperature sensor node (MCU + sensor + Wi-Fi module) periodically sends readings to a laptop application over the Internet. The sensor is associated with Router A (its local Wi-Fi AP); the laptop is on Wi-Fi via Router B. Multiple routers/hops exist in between (ISP, backbone, etc.).


Typical modern flow (what actually happens):


  • MCU reads sensor → formats payload (e.g., JSON or binary "temp:23.5").
  • Calls a high-level send/publish API (socket send(), MQTT publish, HTTP POST, etc.).
  • The stack/firmware handles everything below.
  • Data travels: MCU → Wi-Fi radio → Router A → Internet → Router B → laptop Wi-Fi → laptop app.

Key distinction:


  • Transport (TCP/UDP) is end-to-end (between your sensor MCU and the laptop). It survives all the router hops.
  • Network (IP) is hop-by-hop for routing across networks (uses IP addresses + routing tables; each router decides the next hop).
  • Data Link is per-link (local on each Wi-Fi or Ethernet segment; uses MAC addresses; handles the noisy wireless medium).

Routers generally don't touch the Transport layer (except for NAT, which rewrites IP/port at the L3/L4 boundary). TCP provides reliability, ordering, and flow control between the two ends despite packet loss, reordering, or duplication on the path.

What Each Layer Does + Embedded Developer Responsibilities
1. Data Link Layer (OSI L2 — Wi-Fi 802.11 MAC in this case)

Responsibilities:



  • Local framing and delivery on one link (your Wi-Fi segment).
  • MAC addressing (source/destination MAC addresses; for Wi-Fi, often to the AP's MAC).
  • Medium access control (CSMA/CA — listen-before-talk, random backoff, NAV, optional RTS/CTS).
  • Error detection (FCS/CRC) and retransmission at link level (MAC-level ACKs and retries — very important on noisy Wi-Fi).
  • Wi-Fi specifics: scanning/association/authentication to AP, beacon monitoring, power-save modes, encryption (WPA2/WPA3 — 4-way handshake for keys), management frames, frame aggregation/block ACK (802.11n/ac/ax), rate adaptation.

In the example: The sensor's Wi-Fi module turns the IP packet into 802.11 data frames, handles association to Router A if needed, encrypts, transmits with proper timing/backoff, and retransmits at MAC level if no ACK from the AP. The AP forwards it onward (peeling the 802.11 header and adding the next link's header).


What an embedded developer typically writes:


  • Almost nothing direct for the core logic.
  • Configuration: SSID, password (or provisioning like BLE/SmartConfig), power-save settings, maybe hostname or regulatory domain.
  • Event handling: Callbacks or events for "Wi-Fi connected", "disconnected", "IP obtained", RSSI monitoring, or roaming (rare on simple sensors).
  • In vendor SDKs (e.g., ESP-IDF on ESP32): esp_wifi_set_config(), esp_wifi_connect(), register event handler for WIFI_EVENT_STA_* and IP_EVENT_STA_GOT_IP. Then you mostly react to "connected + have IP" and start your application protocol.
  • Reconnection logic on disconnect (critical for wireless — Wi-Fi can drop due to interference, AP reboot, etc.).
  • If using a simple AT-command module (e.g., ESP8266 AT firmware over UART): Even less — just send AT+CWJAP="ssid","pass" and parse responses. The module's firmware owns the entire 802.11 state machine.

If you had to implement it yourself (rare for Wi-Fi): Extremely complex. Full 802.11 MAC state machines (scanning with probe requests, authentication, association request/response, 4-way WPA handshake, data path with QoS, power management, beacon parsing, etc.). Thousands of lines of careful code, timing-sensitive, standards compliance is brutal. Most chips use FullMAC firmware (offloaded to the module/SoC ROM) precisely to avoid this. SoftMAC (host implements MAC) exists but is heavy on the MCU and usually for Linux drivers (mac80211), not tiny embedded sensors. For wired Ethernet it's far simpler (hardware MAC controller + driver for descriptors/interrupts).

2. Network Layer (OSI L3 — IP)

Responsibilities:



  • Logical addressing (IPv4/IPv6 addresses — your sensor gets one via DHCP from Router A).
  • Routing / forwarding to the next hop (default gateway = your Wi-Fi router; minimal routing table on an end device).
  • Packet fragmentation/reassembly (if needed; rare for small sensor payloads).
  • Basic diagnostics (ICMP — ping, destination unreachable).
  • Header construction: source/dest IP, protocol (TCP=6 or UDP=17), TTL (hop limit), checksum (header only).

In the example: Your sensor gets an IP (e.g., 192.168.1.105) via DHCP. It builds an IP packet addressed to the laptop's public or relayed IP. The local router (default gateway) routes it across the Internet. Each hop decrements TTL and re-encapsulates for the next link.


What an embedded developer typically writes:


  • Very little core logic — it's in the stack/library.
  • Configuration: DHCP (default and automatic in most cases) vs. static IP/gateway/DNS. Set mDNS hostname if desired. React to "IP event" to know you're ready to communicate.
  • In practice (ESP32 + lwIP/ESP-NETIF or similar): The Wi-Fi connect event chain automatically runs DHCP. You just wait for the GOT_IP event, then proceed to open sockets or start an MQTT/HTTP client. Fallback to static IP on DHCP failure is common.
  • DNS resolution if using hostnames instead of raw IPs.
  • Diagnostics: Occasionally implement or use ping for debugging connectivity.
  • Resource awareness: IP buffers, MTU (usually 1500 or lower on some links).

If implementing from scratch: Manageable but non-trivial. IP header build/parse + Internet checksum, ARP (resolve IP→MAC for local delivery), simple routing (default gw + connected routes), DHCP client state machine (INIT → SELECTING → REQUESTING → BOUND, with timeouts and retransmits), optional fragmentation. lwIP implements exactly this (plus more) in a lightweight way suitable for embedded RAM (tens of KB).

3. Transport Layer (OSI L4 — TCP and/or UDP)

Responsibilities:



  • End-to-end delivery between the two applications (sensor ↔ laptop), identified by ports.
  • UDP: Connectionless, lightweight datagrams. Ports + optional checksum. No reliability, ordering, or flow control. "Fire and forget" (or implement your own ACKs/retransmits at app level).
  • TCP: Connection-oriented. 3-way handshake (SYN → SYN-ACK → ACK), sequence numbers + ACKs for reliability and ordering, retransmission timers, flow control (sliding window), congestion control (important on Internet paths), connection teardown (FIN). Much more state and overhead.

In the example:


  • UDP: Sensor just sends a datagram to laptop_ip:some_port. Simple, low overhead, good for periodic sensor data if occasional loss is acceptable.
  • TCP: Establishes a connection first (handshake), then reliably delivers the data in order. Better if you need guaranteed delivery or are going through NAT/firewalls. Many IoT sensors use MQTT over TCP (or TLS).

What an embedded developer typically writes:


  • Choice of protocol and high-level usage.
  • Socket (or equivalent) management: create socket, connect (for TCP), send data, receive (if bidirectional or for ACKs), close, handle errors/timeouts.
  • In practice: Use the sockets API provided by lwIP or the module's stack (socket(), connect(), send(), recv(), close() or netconn/raw API for efficiency). Or higher-level libraries (MQTT client, HTTP client, CoAP) that hide even more.
  • Application-level logic on top: reconnection on failure, keep-alives (TCP keepalive or app-level pings), buffering, serialization of sensor data, power management around network activity.
  • Tuning: Socket buffer sizes (critical for RAM usage), timeouts, keepalive intervals. For battery sensors, minimize airtime (UDP or MQTT with long keepalives + sleep modes).
  • Event-driven reconnection and error recovery (wireless links are unreliable).

If implementing from scratch (or deeply customizing):


  • UDP: Relatively simple — header (ports, length, checksum), demultiplexing to sockets by port, pbuf/packet buffer handling.
  • TCP: Complex and state-machine heavy. ~10–15 connection states (CLOSED, LISTEN, SYN_SENT, SYN_RCVD, ESTABLISHED, FIN_WAIT_1/2, CLOSING, TIME_WAIT, etc.). Multiple timers per connection (retransmit, persist, keepalive, 2MSL for TIME_WAIT). Sequence/ACK number management, out-of-order reassembly, sliding window, congestion control (Reno/NewReno or simpler), RTT estimation, SYN flood protection optional. Needs careful memory management for TCP Control Blocks (TCBs). lwIP implements a full-featured but optimized version of this; writing it correctly from zero is a major project and easy to get subtly wrong (especially timers and edge cases).
Summary: What You Actually Write in a Real Embedded Wi-Fi Project

In 2026 practice with typical hardware (ESP32, similar Wi-Fi SoCs, or AT modules):


  • Data Link: Configuration + event handling for link status. The heavy 802.11 state machines, encryption, MAC retransmissions, etc., live in the module firmware or integrated ROM/firmware. You rarely touch it.
  • Network (IP): Mostly automatic (DHCP). You handle the "got IP" event and perhaps static fallback or DNS.
  • Transport: Use the provided sockets or higher-level protocol libraries (MQTT, HTTP, etc.). You manage connections, send/receive your sensor data, and implement resilience/reconnect logic.
  • Your main focus (Application layer): Sensor reading, data formatting, business logic (thresholds, sampling rate), power optimization, security (TLS where needed), OTA if applicable, and robust error handling.

You spend the vast majority of time on the application and making the whole thing reliable over a flaky wireless + Internet path. The lower layers are largely a black box provided by vendors or lightweight stacks like lwIP (very common in embedded, used by ESP-IDF, many RTOS ports, etc.).


Why modules/firmware offload so much: Implementing a correct, efficient, power-aware, standards-compliant Wi-Fi MAC + TCP/IP from scratch on a small MCU is extremely time-consuming and resource-heavy. That's why you buy modules or use SoCs with integrated stacks.


Understanding the layers still helps enormously for:


  • Debugging (is it Wi-Fi association? DHCP? TCP handshake? Your app protocol?).
  • Choosing TCP vs. UDP (or MQTT/CoAP).
  • Tuning resources (buffers, timeouts).
  • App-level reliability (since wireless isn't perfect even with L2 retries).

If you're working with a specific MCU (e.g., PIC18F + external module, ESP32, STM32 + Wi-Fi, etc.) or stack (lwIP, vendor SDK, AT commands), the exact APIs change but the division of responsibilities stays very similar.
 
Top