Skip to content

Commit

Permalink
tap_manager: work around flexible array members in uapi
Browse files Browse the repository at this point in the history
Recently the kernel replaced depracted zero-length arrays with flexible
arrays [1]. Unfortunately this causes the compilation to fail, since now
G++ rejects anything in structs behind the flexible array member:

Feb 16 11:42:33 | In file included from ../git/src/netlink/tap_manager.cc:11:
Feb 16 11:42:33 | /tmp/generic-x86-64/work/corei7-64-poky-linux/baseboxd/2.1.0-r0/recipe-sysroot/usr/include/linux/ethtool.h: In member function 'virtual int basebox::tap_manager::set_port_speed(std::string, uint32_t, uint8_t)':
Feb 16 11:42:33 | /tmp/generic-x86-64/work/corei7-64-poky-linux/baseboxd/2.1.0-r0/recipe-sysroot/usr/include/linux/ethtool.h:2199:17: error: flexible array member 'ethtool_link_settings::link_mode_masks' not at end of 'struct basebox::tap_manager::set_port_speed(std::string, uint32_t, uint8_t)::<unnamed>'
Feb 16 11:42:33 |  2199 |         __u32   link_mode_masks[];
Feb 16 11:42:33 |       |                 ^~~~~~~~~~~~~~~
Feb 16 11:42:33 | ../git/src/netlink/tap_manager.cc:394:11: note: next member '__u32 basebox::tap_manager::set_port_speed(std::string, uint32_t, uint8_t)::<unnamed struct>::link_mode_data [381]' declared here
Feb 16 11:42:33 |   394 |     __u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
Feb 16 11:42:33 |       |           ^~~~~~~~~~~~~~
Feb 16 11:42:33 | ../git/src/netlink/tap_manager.cc:392:10: note: in the definition of 'struct basebox::tap_manager::set_port_speed(std::string, uint32_t, uint8_t)::<unnamed>'
Feb 16 11:42:33 |   392 |   struct {
Feb 16 11:42:33 |       |          ^

Work around this by switching the order of the elements in our own
struct so that the flexible array member is last, but the struct still
is sized correctly. Then use a ethtool_link_settings pointer pointing to
the beginning of this struct for any further accesses.

[1] torvalds/linux@94dfc73

Signed-off-by: Jonas Gorski <[email protected]>
  • Loading branch information
KanjiMonster committed Feb 19, 2024
1 parent ad9ca1a commit b33d5c3
Showing 1 changed file with 16 additions and 14 deletions.
30 changes: 16 additions & 14 deletions src/netlink/tap_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -390,31 +390,33 @@ int tap_manager::set_port_speed(const std::string name, uint32_t speed,
// mode bitmaps.

struct {
struct ethtool_link_settings req;
__u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
} link_settings;
struct ethtool_link_settings req;
} link_settings_request;
auto *link_settings =
reinterpret_cast<struct ethtool_link_settings *>(&link_settings_request);

memset(&link_settings, 0, sizeof(link_settings));
link_settings.req.cmd = ETHTOOL_GLINKSETTINGS;
memset(&link_settings_request, 0, sizeof(link_settings_request));
link_settings->cmd = ETHTOOL_GLINKSETTINGS;

ifr.ifr_data = reinterpret_cast<char *>(&link_settings);
ifr.ifr_data = reinterpret_cast<char *>(link_settings);
int error = ioctl(sockFd, SIOCETHTOOL, static_cast<void *>(&ifr));
if (error < 0) {
LOG(ERROR) << __FUNCTION__ << " handshake failed error=" << error;
close(sockFd);
return error;
}

if (link_settings.req.link_mode_masks_nwords >= 0 ||
link_settings.req.cmd != ETHTOOL_GLINKSETTINGS) {
if (link_settings->link_mode_masks_nwords >= 0 ||
link_settings->cmd != ETHTOOL_GLINKSETTINGS) {
close(sockFd);
return -EOPNOTSUPP;
}

link_settings.req.link_mode_masks_nwords =
-link_settings.req.link_mode_masks_nwords;
link_settings->link_mode_masks_nwords =
-link_settings->link_mode_masks_nwords;

ifr.ifr_data = reinterpret_cast<char *>(&link_settings);
ifr.ifr_data = reinterpret_cast<char *>(link_settings);
error = ioctl(sockFd, SIOCETHTOOL, static_cast<void *>(&ifr));
if (error < 0) {
LOG(ERROR) << __FUNCTION__ << " failed to get port= " << name
Expand All @@ -423,11 +425,11 @@ int tap_manager::set_port_speed(const std::string name, uint32_t speed,
return error;
}

link_settings.req.duplex = duplex;
link_settings.req.speed = ETHTOOL_SPEED(speed);
link_settings.req.cmd = ETHTOOL_SLINKSETTINGS;
link_settings->duplex = duplex;
link_settings->speed = ETHTOOL_SPEED(speed);
link_settings->cmd = ETHTOOL_SLINKSETTINGS;

ifr.ifr_data = reinterpret_cast<char *>(&link_settings);
ifr.ifr_data = reinterpret_cast<char *>(link_settings);
error = ioctl(sockFd, SIOCETHTOOL, static_cast<void *>(&ifr));
if (error < 0) {
LOG(ERROR) << __FUNCTION__ << " failed to set port= " << name
Expand Down

0 comments on commit b33d5c3

Please sign in to comment.