Skip to content

Commit eb6e86f

Browse files
authored
Merge pull request #103 from danielinux/multicast
Add multicast UDP sockets
2 parents 7280c2d + f9982fd commit eb6e86f

9 files changed

Lines changed: 1519 additions & 7 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Multicast interop tests
2+
3+
on:
4+
push:
5+
branches: [ 'master', 'main', 'release/**' ]
6+
pull_request:
7+
branches: [ '*' ]
8+
9+
jobs:
10+
multicast:
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 10
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
submodules: true
18+
19+
- name: Install dependencies
20+
run: |
21+
sudo apt-get update
22+
sudo apt-get install -y build-essential check libwolfssl-dev pkg-config
23+
sudo modprobe tun
24+
25+
- name: Build and run multicast unit tests
26+
timeout-minutes: 5
27+
run: |
28+
set -euo pipefail
29+
make unit-multicast
30+
timeout --preserve-status 5m ./build/test/unit
31+
32+
- name: Build and run multicast TAP interop
33+
timeout-minutes: 3
34+
run: |
35+
set -euo pipefail
36+
make build/test-multicast-interop
37+
timeout --preserve-status 3m sudo ./build/test-multicast-interop
38+
39+
- name: Cleanup TAP state
40+
if: always()
41+
run: sudo ip link del wmcast0 2>/dev/null || true

Makefile

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,16 @@ build/test-evloop-tun: $(OBJ) build/test/test_eventloop_tun.o build/port/posix/l
242242
@echo "[LD] $@"
243243
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)
244244

245+
build/test-multicast-interop: CFLAGS+=-DIP_MULTICAST
246+
build/test-multicast-interop: build/multicast/wolfip.o build/test/test_multicast_interop.o build/port/posix/tap_linux.o
247+
@echo "[LD] $@"
248+
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)
249+
250+
build/multicast/wolfip.o: src/wolfip.c
251+
@mkdir -p `dirname $@` || true
252+
@echo "[CC] $< (multicast)"
253+
@$(CC) $(CFLAGS) -DIP_MULTICAST -c $< -o $@
254+
245255
build/test-dns: $(OBJ) build/test/test_dhcp_dns.o
246256
@echo "[LD] $@"
247257
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)
@@ -374,7 +384,8 @@ UNIT_TEST_SRCS:=src/test/unit/unit.c \
374384
src/test/unit/unit_tests_dns_dhcp.c \
375385
src/test/unit/unit_tests_tcp_ack.c \
376386
src/test/unit/unit_tests_tcp_flow.c \
377-
src/test/unit/unit_tests_proto.c
387+
src/test/unit/unit_tests_proto.c \
388+
src/test/unit/unit_tests_multicast.c
378389

379390
unit: build/test/unit
380391

@@ -385,6 +396,9 @@ build/test/unit: $(UNIT_TEST_SRCS)
385396
@echo "[LD] $@"
386397
@$(CC) build/test/unit.o -o build/test/unit $(UNIT_LDFLAGS) $(LDFLAGS)
387398

399+
unit-multicast: CFLAGS+=-DIP_MULTICAST
400+
unit-multicast: clean-unit unit
401+
388402
ESP_UNIT_CHECK_CFLAGS := $(CHECK_PKG_CFLAGS)
389403
ifeq ($(UNAME_S),Darwin)
390404
ifneq ($(CHECK_PREFIX),)
@@ -445,6 +459,8 @@ unit-leaksan: clean-unit build/test/unit
445459
COV_DIR:=build/coverage
446460
COV_UNIT:=$(COV_DIR)/unit
447461
COV_UNIT_O:=$(COV_DIR)/unit.o
462+
COV_MCAST_UNIT:=$(COV_DIR)/unit-multicast
463+
COV_MCAST_UNIT_O:=$(COV_DIR)/unit-multicast.o
448464

449465
$(COV_UNIT_O): $(UNIT_TEST_SRCS)
450466
@mkdir -p $(COV_DIR)
@@ -456,6 +472,16 @@ $(COV_UNIT): $(COV_UNIT_O)
456472
@echo "[LD] $@"
457473
@$(CC) $(COV_UNIT_O) -o $(COV_UNIT) $(UNIT_LDFLAGS) $(LDFLAGS)
458474

475+
$(COV_MCAST_UNIT_O): $(UNIT_TEST_SRCS)
476+
@mkdir -p $(COV_DIR)
477+
@echo "[CC] unit.c (multicast coverage)"
478+
@$(CC) $(UNIT_CFLAGS) $(CFLAGS) -DIP_MULTICAST --coverage -c src/test/unit/unit.c -o $(COV_MCAST_UNIT_O)
479+
480+
$(COV_MCAST_UNIT): LDFLAGS+=--coverage $(UNIT_LIBS)
481+
$(COV_MCAST_UNIT): $(COV_MCAST_UNIT_O)
482+
@echo "[LD] $@"
483+
@$(CC) $(COV_MCAST_UNIT_O) -o $(COV_MCAST_UNIT) $(UNIT_LDFLAGS) $(LDFLAGS)
484+
459485
cov: unit $(COV_UNIT)
460486
@echo "[RUN] unit (coverage)"
461487
@rm -f $(COV_DIR)/*.gcda
@@ -473,6 +499,14 @@ autocov: unit $(COV_UNIT)
473499
@mkdir -p build/coverage
474500
@gcovr -r . --exclude "src/test/unit/.*" --html-details -o build/coverage/index.html
475501

502+
autocov-multicast: unit-multicast $(COV_MCAST_UNIT)
503+
@echo "[RUN] unit multicast (coverage)"
504+
@rm -f $(COV_DIR)/*.gcda
505+
@$(COV_MCAST_UNIT)
506+
@echo "[COV] gcovr multicast html"
507+
@mkdir -p build/coverage
508+
@gcovr -r . --exclude "src/test/unit/.*" --html-details -o build/coverage/multicast.html
509+
476510
# Install dynamic library to re-link linux applications
477511
#
478512
install:
@@ -571,7 +605,7 @@ build/test/test-wolfguard-interop: src/test/test_wolfguard_interop.c src/port/po
571605
clean-test-wolfguard-interop:
572606
@rm -f build/test/test-wolfguard-interop build/test/test_wolfguard_interop.o build/test/linux_tun.o
573607

574-
.PHONY: clean all static cppcheck cov autocov unit-asan unit-ubsan unit-leaksan clean-unit \
608+
.PHONY: clean all static cppcheck cov autocov autocov-multicast unit-multicast unit-asan unit-ubsan unit-leaksan clean-unit \
575609
unit-esp-asan unit-esp-ubsan unit-esp-leaksan clean-unit-esp \
576610
unit-wolfguard unit-wolfguard-asan unit-wolfguard-ubsan clean-unit-wolfguard \
577611
test-wolfguard-loopback test-wolfguard-loopback-asan test-wolfguard-loopback-ubsan \

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ configured to forward traffic between multiple network interfaces.
1717
- Pre-allocated buffers for packet processing in static memory
1818
- Multi-interface support
1919
- Optional IPv4-forwarding
20+
- Optional IPv4 UDP multicast with IGMPv3 ASM membership reports
2021

2122
## Supported socket types
2223

@@ -39,8 +40,9 @@ wolfIP exposes a BSD-like `socket(2)` API for IPv4 sockets:
3940
| **Network** | IPv4 | Datagram delivery, TTL handling | [RFC 791](https://datatracker.ietf.org/doc/html/rfc791) |
4041
| **Network** | IPv4 Forwarding | Multi-interface routing (optional) | [RFC 1812](https://datatracker.ietf.org/doc/html/rfc1812) |
4142
| **Network** | ICMP | Echo request/reply, TTL exceeded | [RFC 792](https://datatracker.ietf.org/doc/html/rfc792) |
43+
| **Network** | IGMPv3 | ASM membership reports for IPv4 multicast (optional) | [RFC 3376](https://datatracker.ietf.org/doc/html/rfc3376) |
4244
| **Network** | IPsec | ESP Transport mode | [RFC 4303](https://datatracker.ietf.org/doc/html/rfc4303) |
43-
| **Transport** | UDP | Unicast datagrams, checksum | [RFC 768](https://datatracker.ietf.org/doc/html/rfc768) |
45+
| **Transport** | UDP | Unicast datagrams, checksum, optional IPv4 multicast | [RFC 768](https://datatracker.ietf.org/doc/html/rfc768) |
4446
| **Transport** | TCP | Connection management, reliable delivery | [RFC 793](https://datatracker.ietf.org/doc/html/rfc793), [RFC 9293](https://datatracker.ietf.org/doc/html/rfc9293) |
4547
| **Transport** | TCP | Maximum Segment Size negotiation | [RFC 793](https://datatracker.ietf.org/doc/html/rfc793) |
4648
| **Transport** | TCP | TCP Timestamps, RTT measurement, PAWS, Window Scaling | [RFC 7323](https://datatracker.ietf.org/doc/html/rfc7323) |
@@ -139,6 +141,32 @@ The `-I wtcp0` flag pins the test to the injected interface and `-c5`
139141
generates five echo requests. Successful replies confirm the ICMP
140142
datagram socket support end-to-end through the tap device.
141143

144+
## Optional UDP Multicast
145+
146+
IPv4 UDP multicast is compiled out by default. Define `IP_MULTICAST` to enable
147+
BSD-style multicast socket options and IGMPv3 ASM membership reports:
148+
149+
- `WOLFIP_IP_ADD_MEMBERSHIP`
150+
- `WOLFIP_IP_DROP_MEMBERSHIP`
151+
- `WOLFIP_IP_MULTICAST_IF`
152+
- `WOLFIP_IP_MULTICAST_TTL`
153+
- `WOLFIP_IP_MULTICAST_LOOP`
154+
155+
The implementation supports any-source multicast joins and leaves. Source
156+
filter APIs such as `MCAST_JOIN_SOURCE_GROUP` are not implemented.
157+
158+
```sh
159+
make unit-multicast
160+
./build/test/unit
161+
162+
make build/test-multicast-interop
163+
sudo ./build/test-multicast-interop
164+
```
165+
166+
The multicast interop test creates a Linux TAP interface (`wmcast0`) and
167+
validates both directions: Linux sending to a wolfIP multicast receiver, and
168+
wolfIP sending to a Linux multicast receiver.
169+
142170
## FreeRTOS Port
143171

144172
wolfIP now includes a dedicated FreeRTOS wrapper port at:

docs/API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ wolfIP is a minimal TCP/IP stack designed for resource-constrained embedded syst
1616
- ICMP (RFC 792) - ping replies only
1717
- DHCP (RFC 2131) - client only
1818
- DNS (RFC 1035) - client only
19-
- UDP (RFC 768) - unicast only
19+
- UDP (RFC 768) - unicast, optional IPv4 multicast with `IP_MULTICAST`
2020
- TCP (RFC 793) with options (Timestamps, MSS)
2121

2222
## Core Data Structures

0 commit comments

Comments
 (0)