2 * et driver ioctl swiss army knife command.
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: et.c 393340 2013-03-27 06:10:49Z $
23 #include <sys/param.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/sysctl.h>
29 #include <netinet/in.h>
36 #include <proto/ethernet.h>
38 typedef u_int64_t u64
;
39 typedef u_int32_t u32
;
40 typedef u_int16_t u16
;
42 #include <linux/sockios.h>
43 #include <linux/ethtool.h>
45 static void usage(char *av0
);
46 static void syserr(char *s
);
47 static void et_find(int s
, struct ifreq
*ifr
);
48 static int et_check(int s
, struct ifreq
*ifr
);
57 main(int ac
, char *av
[])
59 char *interface
= NULL
;
73 if (av
[1][0] == '-') {
74 if ((av
[1][1] != 'a') && (av
[1][1] != 'i'))
82 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
86 strncpy(ifr
.ifr_name
, interface
, sizeof (ifr
.ifr_name
));
91 fprintf(stderr
, "et interface not found\n");
95 if (strcmp(av
[optind
], "up") == 0) {
96 if (ioctl(s
, SIOCSETCUP
, (caddr_t
)&ifr
) < 0)
98 } else if (strcmp(av
[optind
], "down") == 0) {
99 if (ioctl(s
, SIOCSETCDOWN
, (caddr_t
)&ifr
) < 0)
101 } else if (strcmp(av
[optind
], "loop") == 0) {
102 if (optind
>= (ac
-1))
104 arg
= atoi(av
[optind
+ 1]);
105 ifr
.ifr_data
= (caddr_t
) &arg
;
106 if (ioctl(s
, SIOCSETCLOOP
, (caddr_t
)&ifr
) < 0)
108 } else if ((strcmp(av
[optind
], "dump") == 0) && (ac
== 2)) {
110 if (ioctl(s
, SIOCGETCDUMP
, (caddr_t
)&ifr
) < 0)
113 } else if (strcmp(av
[optind
], "msglevel") == 0) {
114 if (optind
>= (ac
-1))
116 arg
= strtol(av
[optind
+ 1], &endptr
, 0);
117 ifr
.ifr_data
= (caddr_t
) &arg
;
118 if (ioctl(s
, SIOCSETCSETMSGLEVEL
, (caddr_t
)&ifr
) < 0)
119 syserr("etcsetmsglevel");
120 } else if (strcmp(av
[optind
], "promisc") == 0) {
121 if (optind
>= (ac
-1))
123 arg
= atoi(av
[optind
+ 1]);
124 ifr
.ifr_data
= (caddr_t
) &arg
;
125 if (ioctl(s
, SIOCSETCPROMISC
, (caddr_t
)&ifr
) < 0)
126 syserr("etcpromisc");
127 } else if (strcmp(av
[optind
], "qos") == 0) {
128 if (optind
>= (ac
-1))
130 arg
= atoi(av
[optind
+ 1]);
131 ifr
.ifr_data
= (caddr_t
) &arg
;
132 if (ioctl(s
, SIOCSETCQOS
, (caddr_t
)&ifr
) < 0)
134 } else if (strcmp(av
[optind
], "speed") == 0) {
135 if (optind
>= (ac
-1))
137 if (strcmp(av
[optind
+1], "auto") == 0)
139 else if (strcmp(av
[optind
+1], "10half") == 0)
141 else if (strcmp(av
[optind
+1], "10full") == 0)
143 else if (strcmp(av
[optind
+1], "100half") == 0)
145 else if (strcmp(av
[optind
+1], "100full") == 0)
147 else if (strcmp(av
[optind
+1], "1000full") == 0)
152 ifr
.ifr_data
= (caddr_t
) &arg
;
153 if (ioctl(s
, SIOCSETCSPEED
, (caddr_t
)&ifr
) < 0)
156 else if (strcmp(av
[optind
], "phyrd") == 0) {
159 if ((ac
< (optind
+ 2)) || (ac
> (optind
+ 3))) {
161 } else if (ac
== (optind
+ 3)) {
162 /* PHY address provided */
163 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0) << 16;;
164 vecarg
[0] |= strtoul(av
[optind
+ 2], NULL
, 0) & 0xffff;
165 cmd
= SIOCGETCPHYRD2
;
167 /* "My" PHY address implied */
168 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0);
171 ifr
.ifr_data
= (caddr_t
) vecarg
;
172 if (ioctl(s
, cmd
, (caddr_t
)&ifr
) < 0)
175 printf("0x%04x\n", vecarg
[1]);
176 } else if (strcmp(av
[optind
], "phywr") == 0) {
179 if ((ac
< (optind
+ 3)) || (ac
> (optind
+ 4))) {
181 } else if (ac
== (optind
+ 4)) {
182 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0) << 16;;
183 vecarg
[0] |= strtoul(av
[optind
+ 2], NULL
, 0) & 0xffff;
184 vecarg
[1] = strtoul(av
[optind
+ 3], NULL
, 0);
185 cmd
= SIOCSETCPHYWR2
;
187 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0);
188 vecarg
[1] = strtoul(av
[optind
+ 2], NULL
, 0);
191 ifr
.ifr_data
= (caddr_t
) vecarg
;
192 if (ioctl(s
, cmd
, (caddr_t
)&ifr
) < 0)
194 } else if (strcmp(av
[optind
], "robord") == 0) {
195 if (ac
!= (optind
+ 3))
198 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0) << 16;;
199 vecarg
[0] |= strtoul(av
[optind
+ 2], NULL
, 0) & 0xffff;
201 ifr
.ifr_data
= (caddr_t
) vecarg
;
202 if (ioctl(s
, SIOCGETCROBORD
, (caddr_t
)&ifr
) < 0)
205 printf("0x%08x\n", vecarg
[1]);
206 } else if (strcmp(av
[optind
], "robowr") == 0) {
207 if (ac
!= (optind
+ 4))
210 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0) << 16;;
211 vecarg
[0] |= strtoul(av
[optind
+ 2], NULL
, 0) & 0xffff;
212 vecarg
[1] = strtoul(av
[optind
+ 3], NULL
, 0);
214 ifr
.ifr_data
= (caddr_t
) vecarg
;
215 if (ioctl(s
, SIOCSETCROBOWR
, (caddr_t
)&ifr
) < 0)
217 } else if (strcmp(av
[optind
], "clear_dump") == 0) {
218 if ((ac
> (optind
+ 2)))
222 var
.cmd
= IOV_ET_CLEAR_DUMP
;
224 ifr
.ifr_data
= (caddr_t
) &var
;
225 if (ioctl(s
, SIOCSETGETVAR
, (caddr_t
)&ifr
) < 0)
226 syserr("etccleardump");
227 } else if ((strcmp(av
[optind
], "pktc") == 0) ||
228 (strcmp(av
[optind
], "pktcbnd") == 0)) {
229 /* Get pktc or pktcbnd */
230 if (ac
== (optind
+ 1))
234 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0);
236 var
.len
= sizeof(int);
237 var
.cmd
= strcmp(av
[optind
], "pktc") == 0 ? IOV_PKTC
: IOV_PKTCBND
;
240 ifr
.ifr_data
= (caddr_t
)&var
;
241 if (ioctl(s
, SIOCSETGETVAR
, (caddr_t
)&ifr
) < 0)
245 printf("%d\n", vecarg
[0]);
246 } else if ((strcmp(av
[optind
], "counters") == 0)) {
247 if (ac
== (optind
+ 1))
252 var
.cmd
= IOV_COUNTERS
;
254 var
.len
= sizeof(buf
);
256 ifr
.ifr_data
= (caddr_t
)&var
;
257 if (ioctl(s
, SIOCSETGETVAR
, (caddr_t
)&ifr
) < 0)
261 } else if ((strcmp(av
[optind
], "dump") == 0) && (ac
> 2)) {
262 if (strcmp(av
[optind
+ 1], "ctf") == 0) {
263 if (ac
== (optind
+ 2))
268 var
.cmd
= IOV_DUMP_CTF
;
270 var
.len
= sizeof(buf
);
272 ifr
.ifr_data
= (caddr_t
)&var
;
273 if (ioctl(s
, SIOCSETGETVAR
, (caddr_t
)&ifr
) < 0)
277 } else if (strcmp(av
[optind
+ 1], "ctrace") == 0) {
278 if (ac
== (optind
+ 2))
281 syserr("dump ctrace");
283 var
.cmd
= IOV_DUMP_CTRACE
;
285 var
.len
= sizeof(buf
);
287 ifr
.ifr_data
= (caddr_t
)&var
;
288 if (ioctl(s
, SIOCSETGETVAR
, (caddr_t
)&ifr
) < 0)
289 syserr("dump ctrace");
294 if (strcmp(av
[optind
], "switch_mode") == 0) {
298 if (ac
== (optind
+ 1)) {
302 } else if (ac
== (optind
+ 2)) {
304 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0);
305 all
= (int)(vecarg
[0] == VECLEN
);
307 if (ac
!= (optind
+ 3))
310 vecarg
[0] = strtoul(av
[optind
+ 1], NULL
, 0);
311 vecarg
[1] = strtoul(av
[optind
+ 2], NULL
, 0);
318 var
.len
= VECLEN
* sizeof(int);
319 var
.cmd
= IOV_ET_POWER_SAVE_MODE
;
322 ifr
.ifr_data
= (caddr_t
) &var
;
323 if (ioctl(s
, SIOCSETGETVAR
, (caddr_t
)&ifr
) < 0)
324 syserr("etcswitchmode");
328 printf("phy power save mode for all phys:"
329 " %d %d %d %d %d \n",
330 vecarg
[0], vecarg
[1], vecarg
[2],
331 vecarg
[3], vecarg
[4]);
333 printf("phy power save mode for phy %d mode %d\n",
334 vecarg
[0], vecarg
[1]);
347 fprintf(stderr
, "usage: %s [ [ -a | -i ] interface ] and one of:\n"
353 "\tmsglevel <bitvec> (error=1, trace=2, prhdr=4, prpkt=8)\n"
354 "\tpromisc <0 or 1>\n"
356 "\tspeed <auto, 10half, 10full, 100half, 100full, 1000full>\n"
357 "\tphyrd [<phyaddr>] <reg>\n"
358 "\tphywr [<phyaddr>] <reg> <val>\n"
359 "\trobord <page> <reg>\n"
360 "\trobowr <page> <reg> <val>\n"
361 "\tswitch_mode <phy> <mode> (mode normal=0, auto=1, manual=2, both=3)\n"
370 et_find(int s
, struct ifreq
*ifr
)
372 char proc_net_dev
[] = "/proc/net/dev";
374 char buf
[512], *c
, *name
;
376 ifr
->ifr_name
[0] = '\0';
378 /* eat first two lines */
379 if (!(fp
= fopen(proc_net_dev
, "r")) ||
380 !fgets(buf
, sizeof(buf
), fp
) ||
381 !fgets(buf
, sizeof(buf
), fp
))
384 while (fgets(buf
, sizeof(buf
), fp
)) {
388 if (!(name
= strsep(&c
, ":")))
390 strncpy(ifr
->ifr_name
, name
, IFNAMSIZ
);
391 if (et_check(s
, ifr
) == 0)
393 ifr
->ifr_name
[0] = '\0';
400 et_check(int s
, struct ifreq
*ifr
)
402 struct ethtool_drvinfo info
;
404 memset(&info
, 0, sizeof(info
));
405 info
.cmd
= ETHTOOL_GDRVINFO
;
406 ifr
->ifr_data
= (caddr_t
)&info
;
407 if (ioctl(s
, SIOCETHTOOL
, (caddr_t
)ifr
) < 0) {
408 /* print a good diagnostic if not superuser */
410 syserr("siocethtool");
414 if (!strncmp(info
.driver
, "et", 2))
416 else if (!strncmp(info
.driver
, "bcm57", 5))