1 /*
2 * common.h - common code header
3 *
4 * Data and functions shared by ioctl and netlink implementation.
5 */
6
7 #include "internal.h"
8 #include "json_print.h"
9 #include "common.h"
10
11 #ifndef HAVE_NETIF_MSG
12 enum {
13 NETIF_MSG_DRV = 0x0001,
14 NETIF_MSG_PROBE = 0x0002,
15 NETIF_MSG_LINK = 0x0004,
16 NETIF_MSG_TIMER = 0x0008,
17 NETIF_MSG_IFDOWN = 0x0010,
18 NETIF_MSG_IFUP = 0x0020,
19 NETIF_MSG_RX_ERR = 0x0040,
20 NETIF_MSG_TX_ERR = 0x0080,
21 NETIF_MSG_TX_QUEUED = 0x0100,
22 NETIF_MSG_INTR = 0x0200,
23 NETIF_MSG_TX_DONE = 0x0400,
24 NETIF_MSG_RX_STATUS = 0x0800,
25 NETIF_MSG_PKTDATA = 0x1000,
26 NETIF_MSG_HW = 0x2000,
27 NETIF_MSG_WOL = 0x4000,
28 };
29 #endif
30
31 const struct flag_info flags_msglvl[] = {
32 { "drv", NETIF_MSG_DRV },
33 { "probe", NETIF_MSG_PROBE },
34 { "link", NETIF_MSG_LINK },
35 { "timer", NETIF_MSG_TIMER },
36 { "ifdown", NETIF_MSG_IFDOWN },
37 { "ifup", NETIF_MSG_IFUP },
38 { "rx_err", NETIF_MSG_RX_ERR },
39 { "tx_err", NETIF_MSG_TX_ERR },
40 { "tx_queued", NETIF_MSG_TX_QUEUED },
41 { "intr", NETIF_MSG_INTR },
42 { "tx_done", NETIF_MSG_TX_DONE },
43 { "rx_status", NETIF_MSG_RX_STATUS },
44 { "pktdata", NETIF_MSG_PKTDATA },
45 { "hw", NETIF_MSG_HW },
46 { "wol", NETIF_MSG_WOL },
47 {}
48 };
49 const unsigned int n_flags_msglvl = ARRAY_SIZE(flags_msglvl) - 1;
50
51 const struct off_flag_def off_flag_def[] = {
52 { "rx", "rx-checksumming", "rx-checksum",
53 ETHTOOL_GRXCSUM, ETHTOOL_SRXCSUM, ETH_FLAG_RXCSUM, 0 },
54 { "tx", "tx-checksumming", "tx-checksum-*",
55 ETHTOOL_GTXCSUM, ETHTOOL_STXCSUM, ETH_FLAG_TXCSUM, 0 },
56 { "sg", "scatter-gather", "tx-scatter-gather*",
57 ETHTOOL_GSG, ETHTOOL_SSG, ETH_FLAG_SG, 0 },
58 { "tso", "tcp-segmentation-offload", "tx-tcp*-segmentation",
59 ETHTOOL_GTSO, ETHTOOL_STSO, ETH_FLAG_TSO, 0 },
60 { "ufo", "udp-fragmentation-offload", "tx-udp-fragmentation",
61 ETHTOOL_GUFO, ETHTOOL_SUFO, ETH_FLAG_UFO, 0 },
62 { "gso", "generic-segmentation-offload", "tx-generic-segmentation",
63 ETHTOOL_GGSO, ETHTOOL_SGSO, ETH_FLAG_GSO, 0 },
64 { "gro", "generic-receive-offload", "rx-gro",
65 ETHTOOL_GGRO, ETHTOOL_SGRO, ETH_FLAG_GRO, 0 },
66 { "lro", "large-receive-offload", "rx-lro",
67 0, 0, ETH_FLAG_LRO,
68 KERNEL_VERSION(2,6,24) },
69 { "rxvlan", "rx-vlan-offload", "rx-vlan-hw-parse",
70 0, 0, ETH_FLAG_RXVLAN,
71 KERNEL_VERSION(2,6,37) },
72 { "txvlan", "tx-vlan-offload", "tx-vlan-hw-insert",
73 0, 0, ETH_FLAG_TXVLAN,
74 KERNEL_VERSION(2,6,37) },
75 { "ntuple", "ntuple-filters", "rx-ntuple-filter",
76 0, 0, ETH_FLAG_NTUPLE, 0 },
77 { "rxhash", "receive-hashing", "rx-hashing",
78 0, 0, ETH_FLAG_RXHASH, 0 },
79 };
80
print_flags(const struct flag_info * info,unsigned int n_info,u32 value)81 void print_flags(const struct flag_info *info, unsigned int n_info, u32 value)
82 {
83 const char *sep = "";
84
85 while (n_info) {
86 if (value & info->value) {
87 printf("%s%s", sep, info->name);
88 sep = " ";
89 value &= ~info->value;
90 }
91 ++info;
92 --n_info;
93 }
94
95 /* Print any unrecognised flags in hex */
96 if (value)
97 printf("%s%#x", sep, value);
98 }
99
unparse_wolopts(int wolopts)100 static char *unparse_wolopts(int wolopts)
101 {
102 static char buf[16];
103 char *p = buf;
104
105 memset(buf, 0, sizeof(buf));
106
107 if (wolopts) {
108 if (wolopts & WAKE_PHY)
109 *p++ = 'p';
110 if (wolopts & WAKE_UCAST)
111 *p++ = 'u';
112 if (wolopts & WAKE_MCAST)
113 *p++ = 'm';
114 if (wolopts & WAKE_BCAST)
115 *p++ = 'b';
116 if (wolopts & WAKE_ARP)
117 *p++ = 'a';
118 if (wolopts & WAKE_MAGIC)
119 *p++ = 'g';
120 if (wolopts & WAKE_MAGICSECURE)
121 *p++ = 's';
122 if (wolopts & WAKE_FILTER)
123 *p++ = 'f';
124 } else {
125 *p = 'd';
126 }
127
128 return buf;
129 }
130
dump_wol(struct ethtool_wolinfo * wol)131 int dump_wol(struct ethtool_wolinfo *wol)
132 {
133 print_string(PRINT_ANY, "supports-wake-on",
134 " Supports Wake-on: %s\n", unparse_wolopts(wol->supported));
135 print_string(PRINT_ANY, "wake-on",
136 " Wake-on: %s\n", unparse_wolopts(wol->wolopts));
137
138 if (wol->supported & WAKE_MAGICSECURE) {
139 int i;
140 int delim = 0;
141
142 open_json_array("secureon-password", "");
143 if (!is_json_context())
144 fprintf(stdout, " SecureOn password: ");
145 for (i = 0; i < SOPASS_MAX; i++) {
146 __u8 sopass = wol->sopass[i];
147
148 if (!is_json_context())
149 fprintf(stdout, "%s%02x", delim ? ":" : "", sopass);
150 else
151 print_hex(PRINT_JSON, NULL, "%02u", sopass);
152 delim = 1;
153 }
154 close_json_array("\n");
155 }
156
157 return 0;
158 }
159
dump_mdix(u8 mdix,u8 mdix_ctrl)160 void dump_mdix(u8 mdix, u8 mdix_ctrl)
161 {
162 bool mdi_x = false;
163 bool mdi_x_forced = false;
164 bool mdi_x_auto = false;
165
166 if (mdix_ctrl == ETH_TP_MDI) {
167 mdi_x = false;
168 mdi_x_forced = true;
169 } else if (mdix_ctrl == ETH_TP_MDI_X) {
170 mdi_x = true;
171 mdi_x_forced = true;
172 } else {
173 switch (mdix) {
174 case ETH_TP_MDI_X:
175 mdi_x = true;
176 break;
177 default:
178 print_string(PRINT_FP, NULL, "\tMDI-X: %s\n", "Unknown");
179 return;
180 }
181 if (mdix_ctrl == ETH_TP_MDI_AUTO)
182 mdi_x_auto = true;
183 }
184
185 if (is_json_context()) {
186 print_bool(PRINT_JSON, "mdi-x", NULL, mdi_x);
187 print_bool(PRINT_JSON, "mdi-x-forced", NULL, mdi_x_forced);
188 print_bool(PRINT_JSON, "mdi-x-auto", NULL, mdi_x_auto);
189 } else {
190 fprintf(stdout, " MDI-X: ");
191 if (mdi_x_forced) {
192 if (mdi_x)
193 fprintf(stdout, "on (forced)\n");
194 else
195 fprintf(stdout, "off (forced)\n");
196 } else {
197 if (mdi_x)
198 fprintf(stdout, "on");
199 else
200 fprintf(stdout, "off");
201
202 if (mdi_x_auto)
203 fprintf(stdout, " (auto)");
204 fprintf(stdout, "\n");
205 }
206 }
207 }
208
print_indir_table(struct cmd_context * ctx,u64 ring_count,u32 indir_size,u32 * indir)209 void print_indir_table(struct cmd_context *ctx, u64 ring_count,
210 u32 indir_size, u32 *indir)
211 {
212 u32 i;
213
214 printf("RX flow hash indirection table for %s with %llu RX ring(s):\n",
215 ctx->devname, ring_count);
216
217 if (!indir_size)
218 printf("Operation not supported\n");
219
220 for (i = 0; i < indir_size; i++) {
221 if (i % 8 == 0)
222 printf("%5u: ", i);
223 printf(" %5u", indir[i]);
224 if (i % 8 == 7 || i == indir_size - 1)
225 fputc('\n', stdout);
226 }
227 }
228
print_rss_hkey(u8 * hkey,u32 hkey_size)229 void print_rss_hkey(u8 *hkey, u32 hkey_size)
230 {
231 u32 i;
232
233 printf("RSS hash key:\n");
234 if (!hkey_size || !hkey)
235 printf("Operation not supported\n");
236
237 for (i = 0; i < hkey_size; i++) {
238 if (i == (hkey_size - 1))
239 printf("%02x\n", hkey[i]);
240 else
241 printf("%02x:", hkey[i]);
242 }
243 }
244