]>
git.proxmox.com Git - systemd.git/blob - src/udev/net/ethtool-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/ioctl.h>
24 #include <linux/ethtool.h>
25 #include <linux/sockios.h>
27 #include "conf-parser.h"
28 #include "ethtool-util.h"
30 #include "string-table.h"
34 static const char* const duplex_table
[_DUP_MAX
] = {
39 DEFINE_STRING_TABLE_LOOKUP(duplex
, Duplex
);
40 DEFINE_CONFIG_PARSE_ENUM(config_parse_duplex
, duplex
, Duplex
, "Failed to parse duplex setting");
42 static const char* const wol_table
[_WOL_MAX
] = {
44 [WOL_MAGIC
] = "magic",
48 DEFINE_STRING_TABLE_LOOKUP(wol
, WakeOnLan
);
49 DEFINE_CONFIG_PARSE_ENUM(config_parse_wol
, wol
, WakeOnLan
, "Failed to parse WakeOnLan setting");
51 int ethtool_connect(int *ret
) {
54 assert_return(ret
, -EINVAL
);
56 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
65 int ethtool_get_driver(int *fd
, const char *ifname
, char **ret
) {
66 struct ethtool_drvinfo ecmd
= {
67 .cmd
= ETHTOOL_GDRVINFO
70 .ifr_data
= (void*) &ecmd
76 r
= ethtool_connect(fd
);
78 return log_warning_errno(r
, "link_config: could not connect to ethtool: %m");
81 strscpy(ifr
.ifr_name
, IFNAMSIZ
, ifname
);
83 r
= ioctl(*fd
, SIOCETHTOOL
, &ifr
);
87 d
= strdup(ecmd
.driver
);
95 int ethtool_set_speed(int *fd
, const char *ifname
, unsigned int speed
, Duplex duplex
) {
96 struct ethtool_cmd ecmd
= {
100 .ifr_data
= (void*) &ecmd
102 bool need_update
= false;
105 if (speed
== 0 && duplex
== _DUP_INVALID
)
109 r
= ethtool_connect(fd
);
111 return log_warning_errno(r
, "link_config: could not connect to ethtool: %m");
114 strscpy(ifr
.ifr_name
, IFNAMSIZ
, ifname
);
116 r
= ioctl(*fd
, SIOCETHTOOL
, &ifr
);
120 if (ethtool_cmd_speed(&ecmd
) != speed
) {
121 ethtool_cmd_speed_set(&ecmd
, speed
);
127 if (ecmd
.duplex
!= DUPLEX_HALF
) {
128 ecmd
.duplex
= DUPLEX_HALF
;
133 if (ecmd
.duplex
!= DUPLEX_FULL
) {
134 ecmd
.duplex
= DUPLEX_FULL
;
143 ecmd
.cmd
= ETHTOOL_SSET
;
145 r
= ioctl(*fd
, SIOCETHTOOL
, &ifr
);
153 int ethtool_set_wol(int *fd
, const char *ifname
, WakeOnLan wol
) {
154 struct ethtool_wolinfo ecmd
= {
158 .ifr_data
= (void*) &ecmd
160 bool need_update
= false;
163 if (wol
== _WOL_INVALID
)
167 r
= ethtool_connect(fd
);
169 return log_warning_errno(r
, "link_config: could not connect to ethtool: %m");
172 strscpy(ifr
.ifr_name
, IFNAMSIZ
, ifname
);
174 r
= ioctl(*fd
, SIOCETHTOOL
, &ifr
);
180 if (ecmd
.wolopts
!= WAKE_PHY
) {
181 ecmd
.wolopts
= WAKE_PHY
;
186 if (ecmd
.wolopts
!= WAKE_MAGIC
) {
187 ecmd
.wolopts
= WAKE_MAGIC
;
192 if (ecmd
.wolopts
!= 0) {
202 ecmd
.cmd
= ETHTOOL_SWOL
;
204 r
= ioctl(*fd
, SIOCETHTOOL
, &ifr
);