全部例程

使用 SLAAC 自动配置 IPv6 地址

W6300

更新于 2026年10月19日

本篇总结

在 W6300-EVB-M4 平台上通过 QSPI 接口驱动 W6300,运行 IPv6 地址自动配置(SLAAC 无状态自动配置 + Stateful DHCPv6 有状态配置),自动获取链路本地地址、全局地址、IPv6 网关与 IPv6 DNS,并完成重复地址检测(DAD)验证。

🔑 MH2457、QSPI、UART调试、硬件TOE引擎、SLAAC、DHCPv6、DAD、RA

硬件平台:本例程基于 W6300-EVB-M4 开发板运行,主控 MCU 为 MH2457,通过 QSPI(HSPI)接口与 W6300 通信。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板

本示例演示如何在 W6300 上通过 IPv6 地址自动配置(AAC,Address Auto Configuration)自动获取链路本地地址、全局地址、IPv6 网关与 IPv6 DNS 等网络配置参数。IPv6 地址自动配置分为两条路径:SLAAC(无状态自动配置)根据路由通告(RA)中的前缀信息(PIO)自动生成全局地址;当 RA 携带 M/O 管理标志时,则进一步启用 Stateful DHCPv6 获取 DNS 等有状态配置。设备入网即自动完成 IPv6 配置,即插即用。

前置工具准备

开始本例程前,请确认以下工具已安装:

IPv6 地址自动配置协议简介

IPv6 地址自动配置是节点接入 IPv6 网络后自动获得地址的机制,主要包含 无状态地址自动配置(SLAAC)与 有状态地址自动配置(DHCPv6)两条路径。二者由 Router Advertisement(RA)报文中的标志位协调:

配置方式机制获取内容
SLAAC节点监听 RA,解析 PIO(Prefix Information Option)前缀,结合自身 MAC(EUI-64)自动生成全局地址全局 IPv6 地址、前缀长度、网关(fe80:: 链路本地)
Stateful DHCPv6当 RA 的 M/O 标志请求有状态配置时,节点向 DHCPv6 服务器请求地址/配置地址(若 M 标志)/ DNS 等其他配置参数
DAD重复地址检测,向待测地址发送邻居请求,确认网络中无冲突后才采用该地址地址唯一性验证

链路本地地址由 MAC 通过 EUI-64 规则生成:将 48 位 MAC 中间插入 FFFE,并翻转 U/L 位。本例 MAC 为 00:08:DC:12:34:56,对应链路本地地址即 fe80::0208:dcff:fe12:3456(与日志输出一致)。

RA 报文各主要字段 / 选项说明(对应本例程日志中 W6300 解析出的内容):

字段/选项说明
RA type = 0x86ICMPv6 类型 134(十六进制 0x86)= Router Advertisement 路由通告报文
Router_lifetime路由器作为默认网关的有效时间,本例 1800 秒
Option Type 1Source Link-layer Address,路由器链路层地址
Option Type 3 (PIO)Prefix Information,前缀 /64、前缀标志 0xC0(L+A)、有效生命周期 174438s、首选生命周期 88038s,SLAAC 据此生成全局地址
Option Type 5MTU,链路最大传输单元
Option Type 25Recursive DNS Server,递归 DNS 服务器(DNSv6),生命周期 1800s
M/O 管理标志M 表示管理地址配置、O 表示其他有状态配置;本例 MO 归一化结果 3,判定启用 Stateful DHCPv6

地址自动配置流程:节点收到 RA 后先进行 重复地址检测(DAD)验证链路本地地址唯一性,DAD 通过后根据 PIO 自动生成全局地址;若 RA 请求有状态配置,再运行 Stateful DHCPv6 获取 DNS 等参数,最终得到完整的 IPv6 网络配置。

RA capture mode : W6300 MACRAW        (W6300 以 MACRAW 方式捕获 RA 报文)
type : 86                              (ICMPv6 类型 134 = Router Advertisement)
code : 0
RA_flag : c0
Router_lifetime : 1800 s
Option Type : 1, length : 8            (Source Link-layer Address)
Option Type : 5, length : 8            (MTU)
Option Type : 3, length : 32           (Prefix Information /64 PIO)
Prefix Length : 64
Prefix Information Flag : c0           (L + A:可用作链路上、可自动配置)
valid lifetime : 174438
preferred lifetime : 88038
Accepted first autonomous /64 PIO
Option Type : 25, length : 24          (Recursive DNS Server)
DNS lifetime : 1800
Option Type : 7, length : 8
MO normalized result : 3               (M + O 标志 → 请求 Stateful DHCPv6)
RA requests Stateful DHCPv6

W6300 的优势

W6300 SDK 内置了完整的 IPv6 地址自动配置库(AddressAutoConfig.c/h)与 DHCPv6 客户端库(dhcpv6.c/h)。RA 捕获解析、DAD 检测、PIO 生成全局地址、Stateful DHCPv6 状态机全部由库函数处理。你只需要:注册 1 秒 DHCPv6 定时器 → 设置 NETINFO_SLAAC_V6 模式 → 调用 ipv6_aac_configure()。W6300 硬件 TOE 引擎在 MACRAW 模式即可参与 RA 报文的收发处理。

硬件连接与拓扑

请注意:

PC 和开发板需接入同一路由器(同一 IPv6 网络)。路由器需开启 IPv6 功能并下发 RA(家用路由器的 IPv6 默认开启)。

  1. Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
  2. 网线连接开发板 RJ45 网口 到路由器 LAN 口
  3. 确保 W6300 与 MH2457 之间的 QSPI 连线正确(CSn、SCK、DATA0~DATA3)
┌─────────────────────────────────────┐
│ 路由器 / IPv6 网关(RA + DHCPv6) │
└────┬───────────────────────┬─────────┘
│ │
┌────┴──────┐ ┌────┴──────┐
│ W6300 │ │ PC │
│(IPv6 AAC)│ │(ping -6) │
└────┬──────┘ └───────────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │──────────────→ WIZ UartTool
│ MCU │
└───────────┘
网络拓扑:路由器作为 IPv6 网关下发 RA 并运行 DHCPv6,MH2457 通过 QSPI 驱动 W6300,开发板自动配置地址后 PC 可 ping 通

工程结构

工程核心文件如下:

Project/
├── main.c                    ← 系统入口:串口、GPIO、QSPI 初始化 + user_run()
├── USER/
│   ├── user_main.c/h         ← MAC 地址定义 + user_run() 主流程
│   ├── wiz_platform.c/h      ← 平台适配:debug_usart_init、wizchip_gpio_init、hspi_init
│   ├── wiz_interface.c/h     ← W6300 驱动接口:wizchip_initialize、PHY 检测、软件定时器
│   ├── ipv6_aac.c/h          ← IPv6 地址自动配置:ipv6_aac_configure() 主流程
│   └── wizchip_conf.h        ← WIZnet 配置与 wiz_NetInfo 定义
└── Internet/
    ├── ipv6_common.c/h       ← 公共函数:定时器时基、网络准备、地址校验与打印
    ├── AddressAutoConfig.c/h ← SLAAC 自动配置:RA 捕获解析、DAD、PIO 生成全局地址
    └── dhcpv6.c/h            ← Stateful DHCPv6 客户端状态机

步骤1:注册 DHCPv6 定时器

文件:USER/ipv6_aac.c — 地址自动配置可能根据 RA 的 M/O 标志进入 DHCPv6 路径,因此先注册 1 秒定时器为 DHCPv6 状态机提供时基(RA 超时重传、DHCPv6 重试均依赖该时基)。

/* AddressAutoConfig may enter DHCPv6 paths depending on RA M/O flags. */
wiz_add_timer(DHCP6_time_handler, 1000U);
result = AddressAutoConfig_Init(IPV6_AAC_SOCKET, &net_info);
wiz_delete_timer(DHCP6_time_handler);

ipv6_common.c 中将定时器时基桥接到 W6300 平台的毫秒时基,保证定时精度与平台一致:

uint32_t timer_get_ms(void)
{
    return wiz_get_tick_ms();
}

步骤2:启用 IPv6 地址自动配置

文件:USER/ipv6_aac.c — ipv6_aac_configure() 完成网络准备、初始化地址自动配置,并在配置完成后校验并打印 IPv6 地址。

#define IPV6_AAC_SOCKET 0U

int ipv6_aac_configure(const uint8_t mac[6])
{
    wiz_NetInfo net_info;
    uint8_t result;

    if (mac == NULL)
    {
        return -1;
    }

    if (ipv6_prepare_network(&net_info, mac, NETINFO_SLAAC_V6, NETINFO_STATIC) < 0)
    {
        return -1;
    }

    /* AddressAutoConfig may enter DHCPv6 paths depending on RA M/O flags. */
    wiz_add_timer(DHCP6_time_handler, 1000U);
    result = AddressAutoConfig_Init(IPV6_AAC_SOCKET, &net_info);
    wiz_delete_timer(DHCP6_time_handler);

    if (result != 1U)
    {
        return -1;
    }

    wizchip_getnetinfo(&net_info);
    if (ipv6_address_is_zero(net_info.lla) || ipv6_address_is_zero(net_info.gua))
    {
        return -1;
    }

    ipv6_print_address("Link-local address: ", net_info.lla);
    ipv6_print_address("Global address: ", net_info.gua);

    if (!ipv6_address_is_zero(net_info.gw6))
    {
        ipv6_print_address("IPv6 gateway: ", net_info.gw6);
    }
    if (!ipv6_address_is_zero(net_info.dns6))
    {
        ipv6_print_address("IPv6 DNS: ", net_info.dns6);
    }

    return 0;
}

地址自动配置库根据 RA 的 M/O 标志自动决策:若为无状态(仅 SLAAC)则只解析 PIO 生成全局地址;若 RA 请求有状态配置则自动进入 DHCPv6 路径。整个过程封装在 AddressAutoConfig_Init() 中。

void user_run(void)
{
    printf("%s IPv6 address auto configuration example\r\n", _WIZCHIP_ID_);
    wizchip_initialize();
    (void)ipv6_aac_configure(app_mac);
    while (1)
    {
    }
}

请注意

进行 IPv6 地址自动配置时,需要将网络准备时的 ipmode 设为 NETINFO_SLAAC_V6;DHCPv6 是否启动由 RA 的 M/O 标志决定,无需手动强制开启。

步骤3:网络准备与地址校验打印

文件:Internet/ipv6_common.c — ipv6_prepare_network() 初始化 W6300 套接字缓冲(每套接字 2 KB)并写入网络信息;ipv6_address_is_zero() 与 ipv6_print_address() 负责地址有效性校验与格式化打印。

int ipv6_prepare_network(wiz_NetInfo *net_info,
                         const uint8_t mac[6],
                         ipconf_mode ipmode,
                         dhcp_mode dhcp_mode)
{
    uint8_t tx_size[8] = {2U, 2U, 2U, 2U, 2U, 2U, 2U, 2U};
    uint8_t rx_size[8] = {2U, 2U, 2U, 2U, 2U, 2U, 2U, 2U};

    if ((net_info == NULL) || (mac == NULL))
    {
        return -1;
    }

    wizchip_getnetinfo(net_info);
    (void)wizchip_init(tx_size, rx_size);

    memcpy(net_info->mac, mac, sizeof(net_info->mac));
    net_info->ipmode = ipmode;
    net_info->dhcp = dhcp_mode;

    wizchip_setnetinfo(net_info);
    return 0;
}

地址打印采用每 2 字节一组、以冒号分隔的格式化输出,链路本地地址自动追加前缀 fe80:::

int ipv6_address_is_zero(const uint8_t address[16])
{
    uint8_t index;

    if (address == NULL)
    {
        return 1;
    }
    for (index = 0U; index < 16U; ++index)
    {
        if (address[index] != 0U)
        {
            return 0;
        }
    }
    return 1;
}

void ipv6_print_address(const char *label, const uint8_t address[16])
{
    uint8_t index;

    if ((label == NULL) || (address == NULL))
    {
        return;
    }

    printf("%s", label);
    for (index = 0U; index < 16U; index += 2U)
    {
        printf("%02X%02X", address[index], address[index + 1U]);
        if (index < 14U)
        {
            printf(":");
        }
    }
    printf("\r\n");
}

MAC 地址定义位于 USER/user_main.c,其低 48 位直接参与 EUI-64 生成 IPv6 接口标识:

static const uint8_t app_mac[6] = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56};

运行验证

烧录例程运行后,首先进行 PHY 链路检测,然后执行地址自动配置:先做 DAD 验证链路本地地址,再解析 RA 生成全局地址,并根据 M/O 标志运行 Stateful DHCPv6,最后打印网络地址信息。打开 WIZ UartTool V1.0,连接 DEBUG USB 对应 COM 口(115200 / 8N1),预期串口输出如下:

MH2457 W6300 QSPI example start
W6300 IPv6 address auto configuration example
PHY link
The current Mbtis speed : 100Mbps
The current Duplex Mode : Full-Duplex
Duplicate_Address_Detection
Wait RQIR.....
Timeout !!! DAD SUCCESSED
flags = 0x80
Address_Auto_Configuration Start
RA capture mode : W6300 MACRAW
Sn_SR : 42
RA
type : 86
code : 0
RA_flag : c0
Router_lifetime : 1800 s
Reachable_time : 0 ms
Retrans_time : 0 ms
Option Type : 1, length : 8
Option Type : 5, length : 8
Option Type : 3, length : 32
Prefix Length : 64
Prefix Information Flag : c0
valid lifetime : 174438
preferred lifetime : 88038
Accepted first autonomous /64 PIO
Option Type : 25, length : 24
DNS lifetime : 1800
Option Type : 7, length : 8
MO normalized result : 3
RA requests Stateful DHCPv6
Mac address : 00:08:dc:12:34:56
your Link Local IP is fe80:0000:0000:0000:0208:dcff:fe12:3456
your Global IP is 240e:033d:945a:a301:0208:dcff:fe12:3456
your Gateway IP is fe80:0000:0000:0000:0000:0000:0000:0002
your DNSv6 is 240e:033d:945a:a301:0000:0000:0000:0001
Stateful DHCPv6 succeeded
Link-local address: FE80:0000:0000:0000:0208:DCFF:FE12:3456
Global address: 240E:033D:945A:A301:0000:0000:0000:05EC
IPv6 gateway: FE80:0000:0000:0000:0000:0000:0000:0002
IPv6 DNS: 240E:033D:945A:A301:0000:0000:0000:0001

请注意

测试实例需要 PC 端和 W6300 处于同一 IPv6 网络(同一前缀 240e:033d:945a:a301::/64)。

接着在 PC 端打开 CMD,用 ping -6 发送 ICMPv6 Echo 请求到 W6300 的全局地址,可以正常 PING 通。

CMD ping -6 全局地址(4 包全通,0% 丢包)+ WIZ UartTool 串口输出(PHY + DAD + RA 解析 + Stateful DHCPv6 + IPv6 网络地址)

常见问题

Q: 为什么 DAD 提示 Timeout 后仍显示 DAD SUCCESSED

重复地址检测(DAD)会向待测链路本地地址发送邻居请求(NS),并在一定时间内监听邻居通告(NA)。若在等待周期内未收到任何 NA 响应(Wait RQIR 超时),则判定网络中不存在冲突地址,DAD 通过(SUCCESSED)。这是正常的:超时即代表无冲突,节点可以放心采用该链路本地地址。

Q: SLAAC 和 Stateful DHCPv6 有什么区别

SLAAC 是无状态自动配置,节点从 RA 的 PIO 选项取得 /64 前缀,用 EUI-64 规则自动生成全局地址,无需与服务器交互;DHCPv6 是有状态配置,节点向 DHCPv6 服务器请求地址或 DNS 等参数。本例程根据 RA 的 M/O 标志自动决策:M/O 归一化结果 3 表示请求有状态配置,因此在 SLAAC 生成地址的同时还运行了 Stateful DHCPv6 获取 DNS。

Q: 为什么没有打印 IPv6 gateway 也能联网

IPv6 默认网关通常是路由器的链路本地地址(本例为 fe80::2),通过 RA 报文获知。ipv6_aac_configure 只在 net_info.gw6 非零时才打印;若路由器以链路本地方式通告默认路由,该地址可能不写入 net_info.gw6 字段,但数据仍可通过 IPv6 邻居发现(ND)正常转发。

Q: 为什么需要 W6300 的 MACRAW 模式捕获 RA

RA 报文的目的地址是链路本地多播地址 ff02::1,不会由普通 TCP/UDP 套接字主动接收。因此地址自动配置在 W6300 上以 MACRAW 模式(Sn_SR 打印为 0x42,即 SOCK_MACRAW)捕获并解析链路层 RA 报文,提取前缀、MTU、DNS、M/O 标志等信息,用于 SLAAC 与 DHCPv6 决策。

Q: W6300 平台 IPv6 自动配置定时器如何实现

W6300 平台通过 wiz_add_timer() 向软件定时器链表注册回调,wiz_timer_handler() 由 1ms 定时器中断调用,累计到设定的触发时间(DHCP6 为 1000ms)后执行 DHCP6_time_handler,为 DHCPv6 状态机提供秒级时基;毫秒时基由 timer_get_ms() 桥接到 wiz_get_tick_ms()。该时基用于 RA 超时重传和 DHCPv6 重试计时,缺少该中断将导致地址自动配置无法正常超时重试。

总结

  • 协议定位:IPv6 地址自动配置结合无状态 SLAAC 与有状态 DHCPv6,根据 RA 的 M/O 标志自动选择路径,即插即用
  • 核心机制:DAD 保证地址唯一,RA 的 PIO 通过 EUI-64 生成全局地址,链路本地地址 fe80:: 始终可自生成
  • 关键字段:RA 类型 0x86(134)、PIO /64、M/O 管理标志、DNS 选项共同决定最终配置
  • 实现步骤:注册 1 秒 DHCPv6 定时器 → 设置 NETINFO_SLAAC_V6 模式 → 调用 ipv6_aac_configure 执行地址自动配置
  • 运行验证:烧录后完成 PHY 检测、DAD、RA 解析与 Stateful DHCPv6,PC 端可正常 PING 通全局地址
  • 硬件底座:W6300 硬件 TOE 引擎 + MACRAW 模式负责 RA 捕获与收发,MH2457 经 QSPI 驱动

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5

Andy

W5500 技术支持专家