@@ -120,6 +120,8 @@ static char *unparse_wolopts(int wolopts)
*p++ = 's';
if (wolopts & WAKE_FILTER)
*p++ = 'f';
+ if (wolopts & WAKE_MDA)
+ *p++ = 'e';
} else {
*p = 'd';
}
@@ -129,13 +131,13 @@ static char *unparse_wolopts(int wolopts)
int dump_wol(struct ethtool_wolinfo *wol)
{
+ int i;
+ int delim = 0;
fprintf(stdout, " Supports Wake-on: %s\n",
unparse_wolopts(wol->supported));
fprintf(stdout, " Wake-on: %s\n",
unparse_wolopts(wol->wolopts));
if (wol->supported & WAKE_MAGICSECURE) {
- int i;
- int delim = 0;
fprintf(stdout, " SecureOn password: ");
for (i = 0; i < SOPASS_MAX; i++) {
@@ -145,6 +147,16 @@ int dump_wol(struct ethtool_wolinfo *wol)
}
fprintf(stdout, "\n");
}
+ delim = 0;
+ if (wol->supported & WAKE_MDA) {
+ fprintf(stdout, " Destination MAC: ");
+ for (i = 0; i < ETH_ALEN; i++) {
+ fprintf(stdout, "%s%02x", delim ? ":" : "",
+ wol->mac_da[i]);
+ delim = 1;
+ }
+ fprintf(stdout, "\n");
+ }
return 0;
}
@@ -62,7 +62,7 @@
.\"
.\" \(*WO - wol flags
.\"
-.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBf|\fBd\fP...
+.ds WO \fBp\fP|\fBu\fP|\fBm\fP|\fBb\fP|\fBa\fP|\fBg\fP|\fBs\fP|\fBf|\fBe|\fBd\fP...
.\"
.\" \(*FL - flow type values
.\"
@@ -281,7 +281,7 @@ ethtool \- query or control network driver and hardware settings
.B2 xcvr internal external
.RB [ wol \ \fIN\fP[\fB/\fP\fIM\fP]
.RB | \ wol \ \*(WO]
-.RB [ sopass \ \*(MA]
+.RB [ sopass \ \*(MA | mac-da \ \*(MA ]
.RB [ master-slave \ \*(MS]
.RB [ msglvl
.IR N\fP[/\fIM\fP] \ |
@@ -949,14 +949,21 @@ a Wake on ARP
g Wake on MagicPacket\[tm]
s Enable SecureOn\[tm] password for MagicPacket\[tm]
f Wake on filter(s)
+e Wake on specific MAC destination address
d T{
Disable (wake on nothing). This option clears all previous options.
T}
.TE
.TP
.B sopass \*(MA
-Sets the SecureOn\[tm] password. The argument to this option must be 6
-bytes in Ethernet MAC hex format (\*(MA).
+Sets the secureon\[tm] password. The argument to this option must be 6
+bytes in ethernet mac hex format (\*(MA).
+.PP
+.TE
+.TP
+.B mac-da \*(MA
+Sets the destination MAC address to match against. The argument to this option
+must be 6 bytes in ethernet mac hex format (\*(MA).
.PP
.BI msglvl \ N
.br
@@ -973,6 +973,9 @@ static int parse_wolopts(char *optstr, u32 *data)
case 'f':
*data |= WAKE_FILTER;
break;
+ case 'e':
+ *data |= WAKE_MDA;
+ break;
case 'd':
*data = 0;
break;
@@ -2971,8 +2974,8 @@ static int do_sset(struct cmd_context *ctx)
int gset_changed = 0; /* did anything in GSET change? */
u32 wol_wanted = 0;
int wol_change = 0;
- u8 sopass_wanted[SOPASS_MAX];
- int sopass_change = 0;
+ u8 sopass_wanted[SOPASS_MAX], mda_wanted[ETH_ALEN];
+ int sopass_change = 0, mda_change = 0;
int gwol_changed = 0; /* did anything in GWOL change? */
int msglvl_changed = 0;
u32 msglvl_wanted = 0;
@@ -3093,6 +3096,13 @@ static int do_sset(struct cmd_context *ctx)
exit_bad_args();
get_mac_addr(argp[i], sopass_wanted);
sopass_change = 1;
+ } else if (!strcmp(argp[i], "mac-da")) {
+ gwol_changed = 1;
+ i++;
+ if (i >= argc)
+ exit_bad_args();
+ get_mac_addr(argp[i], mda_wanted);
+ mda_change = 1;
} else if (!strcmp(argp[i], "msglvl")) {
i++;
if (i >= argc)
@@ -3295,14 +3305,18 @@ static int do_sset(struct cmd_context *ctx)
if (err < 0) {
perror("Cannot get current wake-on-lan settings");
} else {
+ int i;
/* Change everything the user specified. */
if (wol_change)
wol.wolopts = wol_wanted;
if (sopass_change) {
- int i;
for (i = 0; i < SOPASS_MAX; i++)
wol.sopass[i] = sopass_wanted[i];
}
+ if (mda_change) {
+ for (i = 0; i < ETH_ALEN; i++)
+ wol.mac_da[i] = mda_wanted[i];
+ }
/* Try to perform the update. */
wol.cmd = ETHTOOL_SWOL;
@@ -3315,6 +3329,8 @@ static int do_sset(struct cmd_context *ctx)
fprintf(stderr, " not setting wol\n");
if (sopass_change)
fprintf(stderr, " not setting sopass\n");
+ if (mda_change)
+ fprintf(stderr, " not setting mac-da\n");
}
}
@@ -5669,8 +5685,8 @@ static const struct option args[] = {
" [ advertise %x[/%x] | mode on|off ... [--] ]\n"
" [ phyad %d ]\n"
" [ xcvr internal|external ]\n"
- " [ wol %d[/%d] | p|u|m|b|a|g|s|f|d... ]\n"
- " [ sopass %x:%x:%x:%x:%x:%x ]\n"
+ " [ wol %d[/%d] | p|u|m|b|a|g|s|f|e|d... ]\n"
+ " [ sopass %x:%x:%x:%x:%x:%x | mac-da %x:%x:%x:%x:%x:%x ]\n"
" [ msglvl %d[/%d] | type on|off ... [--] ]\n"
" [ master-slave preferred-master|preferred-slave|forced-master|forced-slave ]\n"
},
@@ -120,6 +120,7 @@ static const struct pretty_nla_desc __wol_desc[] = {
NLATTR_DESC_NESTED(ETHTOOL_A_WOL_HEADER, header),
NLATTR_DESC_NESTED(ETHTOOL_A_WOL_MODES, bitset),
NLATTR_DESC_BINARY(ETHTOOL_A_WOL_SOPASS),
+ NLATTR_DESC_BINARY(ETHTOOL_A_WOL_MAC_DA),
};
static const struct pretty_nla_desc __features_desc[] = {
@@ -810,6 +810,7 @@ int wol_reply_cb(const struct nlmsghdr *nlhdr, void *data)
DECLARE_ATTR_TB_INFO(tb);
struct nl_context *nlctx = data;
struct ethtool_wolinfo wol = {};
+ unsigned int len;
int ret;
if (nlctx->is_dump || nlctx->is_monitor)
@@ -824,8 +825,6 @@ int wol_reply_cb(const struct nlmsghdr *nlhdr, void *data)
if (tb[ETHTOOL_A_WOL_MODES])
walk_bitset(tb[ETHTOOL_A_WOL_MODES], NULL, wol_modes_cb, &wol);
if (tb[ETHTOOL_A_WOL_SOPASS]) {
- unsigned int len;
-
len = mnl_attr_get_payload_len(tb[ETHTOOL_A_WOL_SOPASS]);
if (len != SOPASS_MAX)
fprintf(stderr, "invalid SecureOn password length %u (should be %u)\n",
@@ -835,6 +834,16 @@ int wol_reply_cb(const struct nlmsghdr *nlhdr, void *data)
mnl_attr_get_payload(tb[ETHTOOL_A_WOL_SOPASS]),
SOPASS_MAX);
}
+ if (tb[ETHTOOL_A_WOL_MAC_DA]) {
+ len = mnl_attr_get_payload_len(tb[ETHTOOL_A_WOL_SOPASS]);
+ if (len != ETH_ALEN)
+ fprintf(stderr, "invalid destinatino MAC address length %u (should be %u)\n",
+ len, ETH_ALEN);
+ else
+ memcpy(wol.mac_da,
+ mnl_attr_get_payload(tb[ETHTOOL_A_WOL_MAC_DA]),
+ ETH_ALEN);
+ }
print_banner(nlctx);
dump_wol(&wol);
@@ -1050,10 +1059,11 @@ enum {
WAKE_MAGIC_BIT = 5,
WAKE_MAGICSECURE_BIT = 6,
WAKE_FILTER_BIT = 7,
+ WAKE_MDA_BIT = 8,
};
#define WAKE_ALL (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_ARP | \
- WAKE_MAGIC | WAKE_MAGICSECURE)
+ WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_MDA)
static const struct lookup_entry_u8 port_values[] = {
{ .arg = "tp", .val = PORT_TP },
@@ -1112,6 +1122,7 @@ char wol_bit_chars[WOL_MODE_COUNT] = {
[WAKE_MAGIC_BIT] = 'g',
[WAKE_MAGICSECURE_BIT] = 's',
[WAKE_FILTER_BIT] = 'f',
+ [WAKE_MDA_BIT] = 'e',
};
const struct char_bitset_parser_data wol_parser_data = {
@@ -1224,6 +1235,14 @@ static const struct param_parser sset_params[] = {
.handler_data = &sopass_parser_data,
.min_argc = 1,
},
+ {
+ .arg = "mac-da",
+ .group = ETHTOOL_MSG_WOL_SET,
+ .type = ETHTOOL_A_WOL_MAC_DA,
+ .handler = nl_parse_byte_str,
+ .handler_data = &sopass_parser_data,
+ .min_argc = 1,
+ },
{
.arg = "msglvl",
.group = ETHTOOL_MSG_DEBUG_SET,
@@ -74,6 +74,10 @@ static struct test_case {
{ 1, "--change devname sopass 01:23:45:67:89:" },
{ 1, "-s devname sopass 01:23:45:67:89" },
{ 1, "--change devname sopass" },
+ { 0, "-s devname mac-da 01:23:45:67:89:ab" },
+ { 1, "--change devname mac-da 01:23:45:67:89:" },
+ { 1, "-s devname mac-da 01:23:45:67:89" },
+ { 1, "--change devname mac-da" },
{ 0, "-s devname msglvl 1" },
{ 1, "--change devname msglvl" },
{ 0, "-s devname msglvl hw on rx_status off" },
Allow waking-up from a specific MAC destination address, this is particularly useful with a number of Ethernet PHYs that have limited buffering and packet matching abilities. Example: ethtool -s eth0 wol e mac-da 01:00:5e:00:00:fb Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com> --- common.c | 16 ++++++++++++++-- ethtool.8.in | 15 +++++++++++---- ethtool.c | 26 +++++++++++++++++++++----- netlink/desc-ethtool.c | 1 + netlink/settings.c | 25 ++++++++++++++++++++++--- test-cmdline.c | 4 ++++ 6 files changed, 73 insertions(+), 14 deletions(-)