Linux rtnetlink:未调用RTM_NEWQDISC的适当函数

发布于 2025-02-08 10:56:34 字数 2282 浏览 1 评论 0 原文

我试图通过RTNETLINK插座创建一个新的QDisk,然后遵循如何做到这一点。

我的程序打开一个NetLink套接字,将A sockaddr_nl 绑定到套接字,并发送包含RTNETLINK数据的消息。我将NLMSGHDR的类型设置为 rtm_newqdisc 创建一个新的QDisk,但是在调试内核后,事实证明适当的函数( tc_modify_qdisc rtm_newqdisc 甚至都没有调用Sched/sch_api.c )。实际上,没有任何函数任何错误。因此,我想我的消息结构是错误或不完整的。我无法通过阅读manpage来弄清楚。有人知道这里的问题是什么?

#include <stdio.h>
#include <asm/types.h>
#include <sys/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

struct data {
  struct nlmsghdr nl;
  struct tcmsg tc;
  struct rtattr rt;
};

int main() {
  int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  if(fd == -1) {
      printf("Error in socket: %s\n", strerror(errno));
      return -1;
  }

  struct sockaddr_nl la;
  memset((void *)&la, 0, sizeof(struct sockaddr_nl));
  la.nl_family = AF_NETLINK;
  la.nl_pid = getpid();

  if(bind(fd, (struct sockaddr*)&la, sizeof(la)) == -1) {
    printf("Error in bind: %s\n", strerror(errno));
    return -1;
  }

  struct data d;
  memset((void *)&d, 0, sizeof(struct data));
  d.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
  d.nl.nlmsg_type = RTM_NEWQDISC;
  d.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP | NLM_F_CREATE | NLM_F_ACK;
  d.nl.nlmsg_seq = 0;
  d.nl.nlmsg_pid = 0;

  d.tc.tcm_family = 0;
  d.tc.tcm_ifindex = 0;
  d.tc.tcm_handle = 0;
  d.tc.tcm_parent = 0;
  d.tc.tcm_info = 0;

  d.rt.rta_type = TCA_UNSPEC;

  struct msghdr msg;
  memset((void *)&msg, 0, sizeof(struct msghdr));
  msg.msg_name = (void *)&la;
  msg.msg_namelen = sizeof(la);

  struct iovec iov;
  memset((void *)&iov, 0, sizeof(struct iovec));
  iov.iov_base = (void *)&d.nl;
  iov.iov_len = d.nl.nlmsg_len;

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  if(sendmsg(fd, &msg, 0) == -1) {
    printf("Error in sendmsg: %s\n", strerror(errno));
    return -1;
  }

  puts("success");
}

我的内核版本是5.17。先感谢您

I tried to create a new qdisk through rtnetlink sockets and followed the manpage on how to do so.

My program opens a netlink socket, binds a sockaddr_nl to the socket and sends a message containing the rtnetlink data. I set type of the nlmsghdr to RTM_NEWQDISC to create a new qdisk, but after debugging the kernel, it turns out that the appropriate function (tc_modify_qdisc, in net/sched/sch_api.c) for RTM_NEWQDISC isn't even called. In fact, no function returned any error. So I suppose my message structure is wrong or incomplete. I can't figure it out by just reading the manpage. Anyone knows whats the issue here?

#include <stdio.h>
#include <asm/types.h>
#include <sys/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

struct data {
  struct nlmsghdr nl;
  struct tcmsg tc;
  struct rtattr rt;
};

int main() {
  int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  if(fd == -1) {
      printf("Error in socket: %s\n", strerror(errno));
      return -1;
  }

  struct sockaddr_nl la;
  memset((void *)&la, 0, sizeof(struct sockaddr_nl));
  la.nl_family = AF_NETLINK;
  la.nl_pid = getpid();

  if(bind(fd, (struct sockaddr*)&la, sizeof(la)) == -1) {
    printf("Error in bind: %s\n", strerror(errno));
    return -1;
  }

  struct data d;
  memset((void *)&d, 0, sizeof(struct data));
  d.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
  d.nl.nlmsg_type = RTM_NEWQDISC;
  d.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP | NLM_F_CREATE | NLM_F_ACK;
  d.nl.nlmsg_seq = 0;
  d.nl.nlmsg_pid = 0;

  d.tc.tcm_family = 0;
  d.tc.tcm_ifindex = 0;
  d.tc.tcm_handle = 0;
  d.tc.tcm_parent = 0;
  d.tc.tcm_info = 0;

  d.rt.rta_type = TCA_UNSPEC;

  struct msghdr msg;
  memset((void *)&msg, 0, sizeof(struct msghdr));
  msg.msg_name = (void *)&la;
  msg.msg_namelen = sizeof(la);

  struct iovec iov;
  memset((void *)&iov, 0, sizeof(struct iovec));
  iov.iov_base = (void *)&d.nl;
  iov.iov_len = d.nl.nlmsg_len;

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  if(sendmsg(fd, &msg, 0) == -1) {
    printf("Error in sendmsg: %s\n", strerror(errno));
    return -1;
  }

  puts("success");
}

My kernel version is 5.17. Thank you in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文