You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Linux下用ioctl/Netlink系统调用在C语言中创建veth对

结论:完全可以实现

Linux上的ip link命令底层就是通过Netlink系统调用实现的,所以用C语言直接调用Netlink接口完全能创建veth设备对;另外也可以用ioctl方式,但Netlink是更现代、更灵活的标准方案,推荐优先使用。

Netlink实现示例代码

以下是一个完整的C语言示例,通过Netlink创建指定名称的veth设备对:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_link.h>

#define NLMSG_TAIL(nmsg) ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))

static int add_veth_pair(const char *name1, const char *name2) {
    int sockfd;
    struct sockaddr_nl sa;
    struct nlmsghdr *nlh;
    struct ifinfomsg *ifm;
    struct rtattr *rta;
    char buf[4096];
    int ret;

    // 创建Netlink套接字
    sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sockfd < 0) {
        perror("socket");
        return -1;
    }

    memset(&sa, 0, sizeof(sa));
    sa.nl_family = AF_NETLINK;
    sa.nl_pid = getpid();
    sa.nl_groups = 0;

    if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        perror("bind");
        close(sockfd);
        return -1;
    }

    // 构建Netlink消息
    nlh = (struct nlmsghdr *)buf;
    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nlh->nlmsg_type = RTM_NEWLINK;
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
    nlh->nlmsg_seq = 1;
    nlh->nlmsg_pid = getpid();

    ifm = NLMSG_DATA(nlh);
    ifm->ifi_family = AF_UNSPEC;
    ifm->ifi_type = ARPHRD_ETHER;
    ifm->ifi_index = 0;
    ifm->ifi_flags = IFF_UP | IFF_RUNNING | IFF_NOARP;
    ifm->ifi_change = 0;

    // 添加主设备名称属性
    rta = NLMSG_TAIL(nlh);
    rta->rta_type = IFLA_IFNAME;
    rta->rta_len = RTA_LENGTH(strlen(name1) + 1);
    strcpy(RTA_DATA(rta), name1);
    nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + RTA_ALIGN(rta->rta_len);

    // 添加veth peer关联属性
    rta = NLMSG_TAIL(nlh);
    rta->rta_type = IFLA_LINKINFO;
    rta->rta_len = RTA_LENGTH(sizeof(struct ifinfomsg));
    nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + RTA_ALIGN(rta->rta_len);

    struct rtattr *nest = RTA_DATA(rta);
    nest->rta_type = IFLA_INFO_KIND;
    nest->rta_len = RTA_LENGTH(strlen("veth") + 1);
    strcpy(RTA_DATA(nest), "veth");
    rta->rta_len += RTA_ALIGN(nest->rta_len);

    nest = (struct rtattr *)((char *)nest + RTA_ALIGN(nest->rta_len));
    nest->rta_type = IFLA_INFO_DATA;
    nest->rta_len = RTA_LENGTH(sizeof(struct rtattr));
    rta->rta_len += RTA_ALIGN(nest->rta_len);

    struct rtattr *peer = RTA_DATA(nest);
    peer->rta_type = VETH_INFO_PEER;
    peer->rta_len = RTA_LENGTH(sizeof(struct ifinfomsg));
    nest->rta_len += RTA_ALIGN(peer->rta_len);

    struct ifinfomsg *peer_ifm = RTA_DATA(peer);
    peer_ifm->ifi_family = AF_UNSPEC;
    peer_ifm->ifi_type = ARPHRD_ETHER;
    peer_ifm->ifi_index = 0;
    peer_ifm->ifi_flags = IFF_UP | IFF_RUNNING | IFF_NOARP;
    peer_ifm->ifi_change = 0;

    struct rtattr *peer_rta = (struct rtattr *)((char *)peer_ifm + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
    peer_rta->rta_type = IFLA_IFNAME;
    peer_rta->rta_len = RTA_LENGTH(strlen(name2) + 1);
    strcpy(RTA_DATA(peer_rta), name2);
    peer->rta_len += RTA_ALIGN(peer_rta->rta_len);

    // 发送Netlink请求
    ret = send(sockfd, nlh, nlh->nlmsg_len, 0);
    if (ret < 0) {
        perror("send");
        close(sockfd);
        return -1;
    }

    // 接收内核响应
    ret = recv(sockfd, buf, sizeof(buf), 0);
    if (ret < 0) {
        perror("recv");
        close(sockfd);
        return -1;
    }

    close(sockfd);
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <veth-name1> <veth-name2>\n", argv[0]);
        return 1;
    }

    if (add_veth_pair(argv[1], argv[2]) != 0) {
        fprintf(stderr, "Failed to create veth pair\n");
        return 1;
    }

    printf("Veth pair %s <-> %s created successfully\n", argv[1], argv[2]);
    return 0;
}

编译命令:gcc veth_create.c -o veth_create,运行需要root权限:sudo ./veth_create veth1 veth2。

关于ioctl的说明

ioctl也可以实现veth设备对的创建,但流程更繁琐:需要先创建两个独立的网络设备,再通过SIOCIFLINK等命令手动关联它们,而且这种方式属于较旧的接口,无法灵活处理复杂的设备属性配置,因此实际开发中很少使用。

内容的提问来源于stack exchange,提问作者Shriram S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:43:15