网络管理
概述
网络管理 API 允许应用以及网络层代码本身在 IP 协议栈的任意层调用已定义的网络例程,或者接收相关网络事件的通知。例如,应用代码可以使用这些 API 请求在基于 Wi-Fi 或 Bluetooth 的网络接口上执行扫描,或者在网络接口 IP 地址发生变化时请求通知。
网络管理 API 的实现旨在通过在构建时剔除未使用的管理例程代码来节省内存。它不使用各自独立、静态定义的网络管理过程 API,而是通过 NET_MGMT_REGISTER_REQUEST_HANDLER 宏注册已定义的过程处理程序。过程请求通过单个 net_mgmt() API 发起,该 API 会调用与相应请求关联的已注册处理程序。
当前实现是实验性的,在未来的版本中可能会发生变化和改进。
请求已定义的过程
所有网络管理请求的形式都是 net_mgmt(mgmt_request, ...)。mgmt_request 参数是一个位掩码,用于指明所针对的协议栈层、是否隐含 net_if 对象,以及所请求的具体管理过程。可用的过程请求取决于协议栈中已实现的内容。
为避免额外开销,所有 net_mgmt() 调用都是直接的。尽管这一点在未来的版本中可能改变,但不会影响该函数的使用者。
监听网络事件
通过注册回调函数并指定一组用于过滤回调触发时机的网络事件,即可接收网络事件通知。对于每一对层和代码,回调必须是唯一的;而在命令部分,它是一组事件的掩码。
运行时有两个可用函数:net_mgmt_add_event_callback() 用于注册回调函数,net_mgmt_del_event_callback() 用于注销回调。辅助函数 net_mgmt_init_event_callback() 可用于简化回调结构体的初始化。
此外,可以使用 NET_MGMT_REGISTER_EVENT_HANDLER 在编译时注册回调处理程序。
当发生与某个回调的事件集合匹配的事件时,会以实际的事件代码调用关联的回调函数。因此,如有需要,同一个回调函数可以处理不同的事件。
警告
事件集合过滤对于层和层代码相同的事件会产生误报。回调处理函数 必须 将传入的事件代码(作为参数)与它要处理的特定网络事件进行比对,无论 传给 net_mgmt_init_event_callback() 的集合中有多少个事件。
请注意,要接收来自多个层的事件,必须注册多个监听器,每个被监听的层各一个。回调处理函数可以在不同层的事件之间共享。
(对于层和层代码相同的事件会出现误报。)
示例如下。
/*
* Set of events to handle.
* See e.g. include/zephyr/net/net_event.h for some NET_EVENT_xxx values.
*/
#define EVENT_IFACE_SET (NET_EVENT_IF_xxx | NET_EVENT_IF_yyy)
#define EVENT_IPV4_SET (NET_EVENT_IPV4_xxx | NET_EVENT_IPV4_yyy)
struct net_mgmt_event_callback iface_callback;
struct net_mgmt_event_callback ipv4_callback;
void callback_handler(struct net_mgmt_event_callback *cb,
uint64_t mgmt_event,
struct net_if *iface)
{
if (mgmt_event == NET_EVENT_IF_xxx) {
/* Handle NET_EVENT_IF_xxx */
} else if (mgmt_event == NET_EVENT_IF_yyy) {
/* Handle NET_EVENT_IF_yyy */
} else if (mgmt_event == NET_EVENT_IPV4_xxx) {
/* Handle NET_EVENT_IPV4_xxx */
} else if (mgmt_event == NET_EVENT_IPV4_yyy) {
/* Handle NET_EVENT_IPV4_yyy */
} else {
/* Spurious (false positive) invocation. */
}
}
void register_cb(void)
{
net_mgmt_init_event_callback(&iface_callback, callback_handler,
EVENT_IFACE_SET);
net_mgmt_init_event_callback(&ipv4_callback, callback_handler,
EVENT_IPV4_SET);
net_mgmt_add_event_callback(&iface_callback);
net_mgmt_add_event_callback(&ipv4_callback);
}
或者类似地使用 NET_MGMT_REGISTER_EVENT_HANDLER。
备注
info 和 info_length 参数只有在启用 CONFIG_NET_MGMT_EVENT_INFO 时才能使用,否则它们为 NULL 和零。
/*
* Set of events to handle.
*/
#define EVENT_IFACE_SET (NET_EVENT_IF_xxx | NET_EVENT_IF_yyy)
#define EVENT_IPV4_SET (NET_EVENT_IPV4_xxx | NET_EVENT_IPV4_yyy)
static void event_handler(uint64_t mgmt_event, struct net_if *iface,
void *info, size_t info_length,
void *user_data)
{
if (mgmt_event == NET_EVENT_IF_xxx) {
/* Handle NET_EVENT_IF_xxx */
} else if (mgmt_event == NET_EVENT_IF_yyy) {
/* Handle NET_EVENT_IF_yyy */
} else if (mgmt_event == NET_EVENT_IPV4_xxx) {
/* Handle NET_EVENT_IPV4_xxx */
} else if (mgmt_event == NET_EVENT_IPV4_yyy) {
/* Handle NET_EVENT_IPV4_yyy */
} else {
/* Spurious (false positive) invocation. */
}
}
NET_MGMT_REGISTER_EVENT_HANDLER(iface_event_handler, EVENT_IFACE_SET,
event_handler, NULL);
NET_MGMT_REGISTER_EVENT_HANDLER(ipv4_event_handler, EVENT_IPV4_SET,
event_handler, NULL);
可监听的通用核心事件见 include/zephyr/net/net_event.h。
定义网络管理过程
可以为自己的协议栈实现提供额外的管理过程:定义一个处理程序,并将其与关联的 mgmt_request 代码一起注册。
管理请求代码定义在相关位置,具体取决于所针对的层;如果目标是 L2 层,则还取决于具体技术。例如,所有 IP 层管理请求代码都可以在 include/zephyr/net/net_event.h 头文件中找到;而对于 L2 技术(比如以太网),这些代码则位于 include/zephyr/net/ethernet.h。
定义采用该签名的处理程序:
static int your_handler(uint64_t mgmt_event, struct net_if *iface,
void *data, size_t len);
然后将其与关联的 mgmt_request 代码一起注册:
NET_MGMT_REGISTER_REQUEST_HANDLER(<mgmt_request code>, your_handler);
此后可以使用以下方式调用这个新的管理过程:
net_mgmt(<mgmt_request code>, ...);
发出网络事件信号
可以使用 net_mgmt_event_notify() 函数并提供网络事件代码来发出特定网络事件的信号,详情见 include/zephyr/net/net_mgmt.h。与管理请求代码类似,事件代码也可以在特定 L2 技术的管理头文件中找到;例如,如果要监听 802.15.4 L2 的事件,include/zephyr/net/ieee802154_mgmt.h 就是合适的位置。