Make netlink socket available unconditionally, not just for rte_flow. Use netlink for get/set operations on link flags, MAC, and MTU when available. Fall back to ioctl if netlink socket creation fails.
Signed-off-by: Robin Jarry <[email protected]> --- drivers/net/tap/rte_eth_tap.c | 143 ++++++++++++++++++++++++++++------ drivers/net/tap/rte_eth_tap.h | 2 +- 2 files changed, 122 insertions(+), 23 deletions(-) diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 5b98e381b424..b53c85746056 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -774,6 +774,89 @@ tap_ctrl_req2str(unsigned long request) return "UNKNOWN"; } +static int +tap_nl_ctrl(struct pmd_internals *pmd, unsigned long request, + struct ifreq *ifr, int set, enum ctrl_mode mode) +{ + bool remote = pmd->remote_if_index && (mode == REMOTE_ONLY || mode == LOCAL_AND_REMOTE); + struct rte_ether_addr *mac; + int ret = 0; + + switch (request) { + case SIOCSIFFLAGS: + if (mode == LOCAL_ONLY || mode == LOCAL_AND_REMOTE) { + ret = tap_nl_set_link_flags(pmd->nlsk_fd, pmd->if_index, + ifr->ifr_flags, set); + if (ret < 0) + return ret; + } + if (remote) + ret = tap_nl_set_link_flags(pmd->nlsk_fd, pmd->remote_if_index, + ifr->ifr_flags, set); + break; + + case SIOCGIFFLAGS: + if (mode == REMOTE_ONLY && pmd->remote_if_index) { + unsigned int flags = 0; + ret = tap_nl_get_link_flags(pmd->nlsk_fd, pmd->remote_if_index, &flags); + if (ret == 0) + ifr->ifr_flags = flags; + } else { + unsigned int flags = 0; + ret = tap_nl_get_link_flags(pmd->nlsk_fd, pmd->if_index, &flags); + if (ret == 0) + ifr->ifr_flags = flags; + } + break; + + case SIOCGIFHWADDR: + mac = (struct rte_ether_addr *)ifr->ifr_hwaddr.sa_data; + if (mode == REMOTE_ONLY && pmd->remote_if_index) { + ret = tap_nl_get_link_mac(pmd->nlsk_fd, pmd->remote_if_index, mac); + if (ret == 0) + ifr->ifr_hwaddr.sa_family = AF_LOCAL; + } else { + ret = tap_nl_get_link_mac(pmd->nlsk_fd, pmd->if_index, mac); + if (ret == 0) + ifr->ifr_hwaddr.sa_family = AF_LOCAL; + } + break; + + case SIOCSIFHWADDR: + mac = (struct rte_ether_addr *)ifr->ifr_hwaddr.sa_data; + if (mode == LOCAL_ONLY || mode == LOCAL_AND_REMOTE) { + ret = tap_nl_set_link_mac(pmd->nlsk_fd, pmd->if_index, mac); + if (ret < 0) + return ret; + } + if (remote) + ret = tap_nl_set_link_mac(pmd->nlsk_fd, pmd->remote_if_index, mac); + break; + + case SIOCSIFMTU: + if (mode == LOCAL_ONLY || mode == LOCAL_AND_REMOTE) { + ret = tap_nl_set_link_mtu(pmd->nlsk_fd, pmd->if_index, ifr->ifr_mtu); + if (ret < 0) + return ret; + } + if (remote) + ret = tap_nl_set_link_mtu(pmd->nlsk_fd, pmd->remote_if_index, ifr->ifr_mtu); + break; + + default: + TAP_LOG(WARNING, "%s: unsupported netlink request", pmd->name); + return -EINVAL; + } + + if (ret < 0) { + TAP_LOG(DEBUG, "%s: netlink %s failed: %s(%d)", pmd->name, + tap_ctrl_req2str(request), strerror(errno), errno); + return -errno; + } + + return 0; +} + static int tap_ioctl(struct pmd_internals *pmd, unsigned long request, struct ifreq *ifr, int set, enum ctrl_mode mode) @@ -782,8 +865,6 @@ tap_ioctl(struct pmd_internals *pmd, unsigned long request, int remote = pmd->remote_if_index && (mode == REMOTE_ONLY || mode == LOCAL_AND_REMOTE); - if (!pmd->remote_if_index && mode == REMOTE_ONLY) - return 0; /* * If there is a remote netdevice, apply ioctl on it, then apply it on * the tap netdevice. @@ -829,6 +910,14 @@ static int tap_ctrl(struct pmd_internals *pmd, unsigned long request, struct ifreq *ifr, int set, enum ctrl_mode mode) { + if (!pmd->remote_if_index && mode == REMOTE_ONLY) + return 0; + + /* Use netlink if available */ + if (pmd->nlsk_fd >= 0 && pmd->if_index > 0) + return tap_nl_ctrl(pmd, request, ifr, set, mode); + + /* Otherwise, fall back to ioctl */ return tap_ioctl(pmd, request, ifr, set, mode); } @@ -1138,12 +1227,15 @@ tap_dev_close(struct rte_eth_dev *dev) if (internals->nlsk_fd != -1) { tap_flow_flush(dev, NULL); tap_flow_implicit_flush(internals, NULL); - tap_nl_final(internals->nlsk_fd); - internals->nlsk_fd = -1; tap_flow_bpf_destroy(internals); } #endif + if (internals->nlsk_fd != -1) { + tap_nl_final(internals->nlsk_fd); + internals->nlsk_fd = -1; + } + for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) { struct rx_queue *rxq = &internals->rxq[i]; @@ -1953,10 +2045,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, strlcpy(pmd->name, tap_name, sizeof(pmd->name)); pmd->type = type; pmd->ka_fd = -1; - -#ifdef HAVE_TCA_FLOWER pmd->nlsk_fd = -1; -#endif pmd->gso_ctx_mp = NULL; pmd->ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0); @@ -2035,26 +2124,38 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, /* Make network device persist after application exit */ pmd->persist = persist; -#ifdef HAVE_TCA_FLOWER /* - * Set up everything related to rte_flow: - * - netlink socket - * - tap / remote if_index - * - mandatory QDISCs - * - rte_flow actual/implicit lists - * - implicit rules + * Try to create netlink socket for better interface control. + * This provides ifindex-based operations and is more namespace-safe. + * Fall back to ioctl if netlink is not available. */ pmd->nlsk_fd = tap_nl_init(0); if (pmd->nlsk_fd == -1) { - TAP_LOG(WARNING, "%s: failed to create netlink socket.", + TAP_LOG(INFO, "%s: netlink unavailable, using ioctl fallback.", + pmd->name); + } else { + pmd->if_index = if_nametoindex(pmd->name); + if (!pmd->if_index) { + TAP_LOG(WARNING, "%s: failed to get if_index.", + pmd->name); + close(pmd->nlsk_fd); + pmd->nlsk_fd = -1; + } + } + +#ifdef HAVE_TCA_FLOWER + /* + * Set up everything related to rte_flow: + * - mandatory QDISCs (requires netlink) + * - rte_flow actual/implicit lists + * - implicit rules + */ + if (pmd->nlsk_fd == -1) { + TAP_LOG(WARNING, "%s: rte_flow requires netlink support.", pmd->name); goto disable_rte_flow; } - pmd->if_index = if_nametoindex(pmd->name); - if (!pmd->if_index) { - TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name); - goto disable_rte_flow; - } + if (qdisc_create_multiq(pmd->nlsk_fd, pmd->if_index) < 0) { TAP_LOG(ERR, "%s: failed to create multiq qdisc.", pmd->name); @@ -2141,10 +2242,8 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name, #endif error_exit: -#ifdef HAVE_TCA_FLOWER if (pmd->nlsk_fd != -1) close(pmd->nlsk_fd); -#endif if (pmd->ka_fd != -1) close(pmd->ka_fd); if (pmd->ioctl_sock != -1) diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index ce4322ad046e..bb5aa8966bb0 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -77,9 +77,9 @@ struct pmd_internals { int remote_if_index; /* remote netdevice IF_INDEX */ int if_index; /* IF_INDEX for the port */ int ioctl_sock; /* socket for ioctl calls */ + int nlsk_fd; /* Netlink socket fd */ #ifdef HAVE_TCA_FLOWER - int nlsk_fd; /* Netlink socket fd */ int flow_isolate; /* 1 if flow isolation is enabled */ struct tap_rss *rss; /* BPF program */ -- 2.51.0

