~ubuntu-branches/ubuntu/trusty/ethtool/trusty-proposed

« back to all changes in this revision

Viewing changes to ethtool.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings
  • Date: 2011-08-21 00:21:09 UTC
  • mfrom: (1.3.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110821002109-serypa8yk8yazy8b
Tags: 1:3.0-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <stdlib.h>
29
29
#include <sys/stat.h>
30
30
#include <stdio.h>
 
31
#include <stddef.h>
31
32
#include <errno.h>
32
33
#include <sys/utsname.h>
33
34
#include <limits.h>
96
97
static int do_grxclsrule(int fd, struct ifreq *ifr);
97
98
static int do_flash(int fd, struct ifreq *ifr);
98
99
static int do_permaddr(int fd, struct ifreq *ifr);
 
100
static int do_getfwdump(int fd, struct ifreq *ifr);
 
101
static int do_setfwdump(int fd, struct ifreq *ifr);
99
102
 
100
103
static int send_ioctl(int fd, struct ifreq *ifr);
101
104
 
128
131
        MODE_GCLSRULE,
129
132
        MODE_FLASHDEV,
130
133
        MODE_PERMADDR,
 
134
        MODE_SET_DUMP,
 
135
        MODE_GET_DUMP,
131
136
} mode = MODE_GSET;
132
137
 
133
138
static struct option {
255
260
                "               [ rule %d ]\n"},
256
261
    { "-P", "--show-permaddr", MODE_PERMADDR,
257
262
                "Show permanent hardware address" },
 
263
    { "-w", "--get-dump", MODE_GET_DUMP,
 
264
                "Get dump flag, data",
 
265
                "               [ data FILENAME ]\n" },
 
266
    { "-W", "--set-dump", MODE_SET_DUMP,
 
267
                "Set dump flag of the device",
 
268
                "               N\n"},
258
269
    { "-h", "--help", MODE_HELP, "Show this help" },
259
270
    { NULL, "--version", MODE_VERSION, "Show version number" },
260
271
    {}
365
376
static char *gregs_dump_file = NULL;
366
377
static int geeprom_changed = 0;
367
378
static int geeprom_dump_raw = 0;
368
 
static s32 geeprom_offset = 0;
369
 
static s32 geeprom_length = -1;
 
379
static u32 geeprom_offset = 0;
 
380
static u32 geeprom_length = -1;
370
381
static int seeprom_changed = 0;
371
 
static s32 seeprom_magic = 0;
372
 
static s32 seeprom_length = -1;
373
 
static s32 seeprom_offset = 0;
374
 
static s32 seeprom_value = EOF;
 
382
static u32 seeprom_magic = 0;
 
383
static u32 seeprom_length = -1;
 
384
static u32 seeprom_offset = 0;
 
385
static u8 seeprom_value = 0;
 
386
static int seeprom_value_seen = 0;
375
387
static int rx_fhash_get = 0;
376
388
static int rx_fhash_set = 0;
377
389
static u32 rx_fhash_val = 0;
385
397
static int msglvl_changed;
386
398
static u32 msglvl_wanted = 0;
387
399
static u32 msglvl_mask = 0;
 
400
static u32 dump_flag;
 
401
static char *dump_file = NULL;
388
402
 
389
403
static int rx_class_rule_get = -1;
390
404
static int rx_class_rule_del = -1;
400
414
        CMDL_NONE,
401
415
        CMDL_BOOL,
402
416
        CMDL_S32,
 
417
        CMDL_U8,
403
418
        CMDL_U16,
404
419
        CMDL_U32,
405
420
        CMDL_U64,
433
448
};
434
449
 
435
450
static struct cmdline_info cmdline_geeprom[] = {
436
 
        { "offset", CMDL_S32, &geeprom_offset, NULL },
437
 
        { "length", CMDL_S32, &geeprom_length, NULL },
 
451
        { "offset", CMDL_U32, &geeprom_offset, NULL },
 
452
        { "length", CMDL_U32, &geeprom_length, NULL },
438
453
        { "raw", CMDL_BOOL, &geeprom_dump_raw, NULL },
439
454
};
440
455
 
441
456
static struct cmdline_info cmdline_seeprom[] = {
442
 
        { "magic", CMDL_S32, &seeprom_magic, NULL },
443
 
        { "offset", CMDL_S32, &seeprom_offset, NULL },
444
 
        { "length", CMDL_S32, &seeprom_length, NULL },
445
 
        { "value", CMDL_S32, &seeprom_value, NULL },
 
457
        { "magic", CMDL_U32, &seeprom_magic, NULL },
 
458
        { "offset", CMDL_U32, &seeprom_offset, NULL },
 
459
        { "length", CMDL_U32, &seeprom_length, NULL },
 
460
        { "value", CMDL_U8, &seeprom_value, NULL,
 
461
          0, &seeprom_value_seen },
446
462
};
447
463
 
448
464
static struct cmdline_info cmdline_offload[] = {
614
630
                                                           0x7fffffff);
615
631
                                        break;
616
632
                                }
 
633
                                case CMDL_U8: {
 
634
                                        u8 *p = info[idx].wanted_val;
 
635
                                        *p = get_uint_range(argp[i], 0, 0xff);
 
636
                                        break;
 
637
                                }
617
638
                                case CMDL_U16: {
618
639
                                        u16 *p = info[idx].wanted_val;
619
640
                                        *p = get_uint_range(argp[i], 0, 0xffff);
777
798
                            (mode == MODE_GCLSRULE) ||
778
799
                            (mode == MODE_PHYS_ID) ||
779
800
                            (mode == MODE_FLASHDEV) ||
780
 
                            (mode == MODE_PERMADDR)) {
 
801
                            (mode == MODE_PERMADDR) ||
 
802
                            (mode == MODE_SET_DUMP) ||
 
803
                            (mode == MODE_GET_DUMP)) {
781
804
                                devname = argp[i];
782
805
                                break;
783
806
                        }
799
822
                                flash_file = argp[i];
800
823
                                flash = 1;
801
824
                                break;
 
825
                        } else if (mode == MODE_SET_DUMP) {
 
826
                                dump_flag = get_u32(argp[i], 0);
 
827
                                break;
802
828
                        }
803
829
                        /* fallthrough */
804
830
                default:
974
1000
                                }
975
1001
                                break;
976
1002
                        }
 
1003
                        if (mode == MODE_GET_DUMP) {
 
1004
                                if (argc != i + 2) {
 
1005
                                        exit_bad_args();
 
1006
                                        break;
 
1007
                                }
 
1008
                                if (!strcmp(argp[i++], "data"))
 
1009
                                        dump_flag = ETHTOOL_GET_DUMP_DATA;
 
1010
                                else {
 
1011
                                        exit_bad_args();
 
1012
                                        break;
 
1013
                                }
 
1014
                                dump_file = argp[i];
 
1015
                                i = argc;
 
1016
                                break;
 
1017
                        }
977
1018
                        if (mode != MODE_SSET)
978
1019
                                exit_bad_args();
979
1020
                        if (!strcmp(argp[i], "speed")) {
1132
1173
                exit_bad_args();
1133
1174
}
1134
1175
 
 
1176
static void dump_link_caps(const char *prefix, const char *an_prefix, u32 mask);
 
1177
 
1135
1178
static void dump_supported(struct ethtool_cmd *ep)
1136
1179
{
1137
 
        u_int32_t mask = ep->supported;
1138
 
        int did1;
 
1180
        u32 mask = ep->supported;
1139
1181
 
1140
1182
        fprintf(stdout, "       Supported ports: [ ");
1141
1183
        if (mask & SUPPORTED_TP)
1150
1192
                fprintf(stdout, "FIBRE ");
1151
1193
        fprintf(stdout, "]\n");
1152
1194
 
1153
 
        fprintf(stdout, "       Supported link modes:   ");
1154
 
        did1 = 0;
1155
 
        if (mask & SUPPORTED_10baseT_Half) {
1156
 
                did1++; fprintf(stdout, "10baseT/Half ");
1157
 
        }
1158
 
        if (mask & SUPPORTED_10baseT_Full) {
1159
 
                did1++; fprintf(stdout, "10baseT/Full ");
1160
 
        }
1161
 
        if (did1 && (mask & (SUPPORTED_100baseT_Half|SUPPORTED_100baseT_Full))) {
1162
 
                fprintf(stdout, "\n");
1163
 
                fprintf(stdout, "                               ");
1164
 
        }
1165
 
        if (mask & SUPPORTED_100baseT_Half) {
1166
 
                did1++; fprintf(stdout, "100baseT/Half ");
1167
 
        }
1168
 
        if (mask & SUPPORTED_100baseT_Full) {
1169
 
                did1++; fprintf(stdout, "100baseT/Full ");
1170
 
        }
1171
 
        if (did1 && (mask & (SUPPORTED_1000baseT_Half|SUPPORTED_1000baseT_Full))) {
1172
 
                fprintf(stdout, "\n");
1173
 
                fprintf(stdout, "                               ");
1174
 
        }
1175
 
        if (mask & SUPPORTED_1000baseT_Half) {
1176
 
                did1++; fprintf(stdout, "1000baseT/Half ");
1177
 
        }
1178
 
        if (mask & SUPPORTED_1000baseT_Full) {
1179
 
                did1++; fprintf(stdout, "1000baseT/Full ");
1180
 
        }
1181
 
        if (did1 && (mask & SUPPORTED_2500baseX_Full)) {
1182
 
                fprintf(stdout, "\n");
1183
 
                fprintf(stdout, "                               ");
1184
 
        }
1185
 
        if (mask & SUPPORTED_2500baseX_Full) {
1186
 
                did1++; fprintf(stdout, "2500baseX/Full ");
1187
 
        }
1188
 
        if (did1 && (mask & SUPPORTED_10000baseT_Full)) {
1189
 
                fprintf(stdout, "\n");
1190
 
                fprintf(stdout, "                               ");
1191
 
        }
1192
 
        if (mask & SUPPORTED_10000baseT_Full) {
1193
 
                did1++; fprintf(stdout, "10000baseT/Full ");
1194
 
        }
1195
 
        fprintf(stdout, "\n");
1196
 
 
1197
 
        fprintf(stdout, "       Supports auto-negotiation: ");
1198
 
        if (mask & SUPPORTED_Autoneg)
1199
 
                fprintf(stdout, "Yes\n");
1200
 
        else
1201
 
                fprintf(stdout, "No\n");
 
1195
        dump_link_caps("Supported", "Supports", mask);
1202
1196
}
1203
1197
 
1204
 
static void dump_advertised(struct ethtool_cmd *ep,
1205
 
                            const char *prefix, u_int32_t mask)
 
1198
/* Print link capability flags (supported, advertised or lp_advertised).
 
1199
 * Assumes that the corresponding SUPPORTED and ADVERTISED flags are equal.
 
1200
 */
 
1201
static void
 
1202
dump_link_caps(const char *prefix, const char *an_prefix, u32 mask)
1206
1203
{
1207
 
        int indent = strlen(prefix) + 14;
 
1204
        int indent;
1208
1205
        int did1;
1209
1206
 
1210
 
        fprintf(stdout, "       %s link modes:  ", prefix);
 
1207
        /* Indent just like the separate functions used to */
 
1208
        indent = strlen(prefix) + 14;
 
1209
        if (indent < 24)
 
1210
                indent = 24;
 
1211
 
 
1212
        fprintf(stdout, "       %s link modes:%*s", prefix,
 
1213
                indent - (int)strlen(prefix) - 12, "");
1211
1214
        did1 = 0;
1212
1215
        if (mask & ADVERTISED_10baseT_Half) {
1213
1216
                did1++; fprintf(stdout, "10baseT/Half ");
1249
1252
        if (mask & ADVERTISED_10000baseT_Full) {
1250
1253
                did1++; fprintf(stdout, "10000baseT/Full ");
1251
1254
        }
 
1255
        if (did1 && (mask & ADVERTISED_20000baseMLD2_Full)) {
 
1256
                fprintf(stdout, "\n");
 
1257
                fprintf(stdout, "       %*s", indent, "");
 
1258
        }
 
1259
        if (mask & ADVERTISED_20000baseMLD2_Full) {
 
1260
                did1++; fprintf(stdout, "20000baseMLD2/Full ");
 
1261
        }
 
1262
        if (did1 && (mask & ADVERTISED_20000baseKR2_Full)) {
 
1263
                fprintf(stdout, "\n");
 
1264
                fprintf(stdout, "       %*s", indent, "");
 
1265
        }
 
1266
        if (mask & ADVERTISED_20000baseKR2_Full) {
 
1267
                did1++; fprintf(stdout, "20000baseKR2/Full ");
 
1268
        }
1252
1269
        if (did1 == 0)
1253
1270
                 fprintf(stdout, "Not reported");
1254
1271
        fprintf(stdout, "\n");
1266
1283
                        fprintf(stdout, "No\n");
1267
1284
        }
1268
1285
 
1269
 
        fprintf(stdout, "       %s auto-negotiation: ", prefix);
 
1286
        fprintf(stdout, "       %s auto-negotiation: ", an_prefix);
1270
1287
        if (mask & ADVERTISED_Autoneg)
1271
1288
                fprintf(stdout, "Yes\n");
1272
1289
        else
1278
1295
        u32 speed;
1279
1296
 
1280
1297
        dump_supported(ep);
1281
 
        dump_advertised(ep, "Advertised", ep->advertising);
 
1298
        dump_link_caps("Advertised", "Advertised", ep->advertising);
1282
1299
        if (ep->lp_advertising)
1283
 
                dump_advertised(ep, "Link partner advertised",
1284
 
                                ep->lp_advertising);
 
1300
                dump_link_caps("Link partner advertised",
 
1301
                               "Link partner advertised", ep->lp_advertising);
1285
1302
 
1286
1303
        fprintf(stdout, "       Speed: ");
1287
1304
        speed = ethtool_cmd_speed(ep);
1936
1953
                return do_flash(fd, &ifr);
1937
1954
        } else if (mode == MODE_PERMADDR) {
1938
1955
                return do_permaddr(fd, &ifr);
 
1956
        } else if (mode == MODE_GET_DUMP) {
 
1957
                return do_getfwdump(fd, &ifr);
 
1958
        } else if (mode == MODE_SET_DUMP) {
 
1959
                return do_setfwdump(fd, &ifr);
1939
1960
        }
1940
1961
 
1941
1962
        return 69;
2475
2496
                                         ADVERTISED_1000baseT_Half |
2476
2497
                                         ADVERTISED_1000baseT_Full |
2477
2498
                                         ADVERTISED_2500baseX_Full |
2478
 
                                         ADVERTISED_10000baseT_Full);
 
2499
                                         ADVERTISED_10000baseT_Full |
 
2500
                                         ADVERTISED_20000baseMLD2_Full |
 
2501
                                         ADVERTISED_20000baseKR2_Full);
2479
2502
                        } else if (advertising_wanted > 0) {
2480
2503
                                ecmd.advertising = advertising_wanted;
2481
2504
                        }
2626
2649
                return 74;
2627
2650
        }
2628
2651
 
2629
 
        if (geeprom_length <= 0)
 
2652
        if (geeprom_length == -1)
2630
2653
                geeprom_length = drvinfo.eedump_len;
2631
2654
 
2632
2655
        if (drvinfo.eedump_len < geeprom_offset + geeprom_length)
2667
2690
                return 74;
2668
2691
        }
2669
2692
 
2670
 
        if (seeprom_value != EOF)
 
2693
        if (seeprom_value_seen)
2671
2694
                seeprom_length = 1;
2672
2695
 
2673
 
        if (seeprom_length <= 0)
 
2696
        if (seeprom_length == -1)
2674
2697
                seeprom_length = drvinfo.eedump_len;
2675
2698
 
2676
2699
        if (drvinfo.eedump_len < seeprom_offset + seeprom_length)
2689
2712
        eeprom->data[0] = seeprom_value;
2690
2713
 
2691
2714
        /* Multi-byte write: read input from stdin */
2692
 
        if (seeprom_value == EOF)
 
2715
        if (!seeprom_value_seen)
2693
2716
                eeprom->len = fread(eeprom->data, 1, eeprom->len, stdin);
2694
2717
 
2695
2718
        ifr->ifr_data = (caddr_t)eeprom;
3242
3265
        return err ? 1 : 0;
3243
3266
}
3244
3267
 
 
3268
static int do_writefwdump(struct ethtool_dump *dump)
 
3269
{
 
3270
        int err = 0;
 
3271
        FILE *f;
 
3272
        size_t bytes;
 
3273
 
 
3274
        f = fopen(dump_file, "wb+");
 
3275
 
 
3276
        if (!f) {
 
3277
                fprintf(stderr, "Can't open file %s: %s\n",
 
3278
                        dump_file, strerror(errno));
 
3279
                return 1;
 
3280
        }
 
3281
        bytes = fwrite(dump->data, 1, dump->len, f);
 
3282
        if (bytes != dump->len) {
 
3283
                fprintf(stderr, "Can not write all of dump data\n");
 
3284
                err = 1;
 
3285
        }
 
3286
        if (fclose(f)) {
 
3287
                fprintf(stderr, "Can't close file %s: %s\n",
 
3288
                        dump_file, strerror(errno));
 
3289
                err = 1;
 
3290
        }
 
3291
        return err;
 
3292
}
 
3293
 
 
3294
static int do_getfwdump(int fd, struct ifreq *ifr)
 
3295
{
 
3296
        int err;
 
3297
        struct ethtool_dump edata;
 
3298
        struct ethtool_dump *data;
 
3299
 
 
3300
        edata.cmd = ETHTOOL_GET_DUMP_FLAG;
 
3301
 
 
3302
        ifr->ifr_data = (caddr_t) &edata;
 
3303
        err = send_ioctl(fd, ifr);
 
3304
        if (err < 0) {
 
3305
                perror("Can not get dump level\n");
 
3306
                return 1;
 
3307
        }
 
3308
        if (dump_flag != ETHTOOL_GET_DUMP_DATA) {
 
3309
                fprintf(stdout, "flag: %u, version: %u, length: %u\n",
 
3310
                        edata.flag, edata.version, edata.len);
 
3311
                return 0;
 
3312
        }
 
3313
        data = calloc(1, offsetof(struct ethtool_dump, data) + edata.len);
 
3314
        if (!data) {
 
3315
                perror("Can not allocate enough memory\n");
 
3316
                return 1;
 
3317
        }
 
3318
        data->cmd = ETHTOOL_GET_DUMP_DATA;
 
3319
        data->len = edata.len;
 
3320
        ifr->ifr_data = (caddr_t) data;
 
3321
        err = send_ioctl(fd, ifr);
 
3322
        if (err < 0) {
 
3323
                perror("Can not get dump data\n");
 
3324
                err = 1;
 
3325
                goto free;
 
3326
        }
 
3327
        err = do_writefwdump(data);
 
3328
free:
 
3329
        free(data);
 
3330
        return err;
 
3331
}
 
3332
 
 
3333
static int do_setfwdump(int fd, struct ifreq *ifr)
 
3334
{
 
3335
        int err;
 
3336
        struct ethtool_dump dump;
 
3337
 
 
3338
        dump.cmd = ETHTOOL_SET_DUMP;
 
3339
        dump.flag = dump_flag;
 
3340
        ifr->ifr_data = (caddr_t)&dump;
 
3341
        err = send_ioctl(fd, ifr);
 
3342
        if (err < 0) {
 
3343
                perror("Can not set dump level\n");
 
3344
                return 1;
 
3345
        }
 
3346
        return 0;
 
3347
}
 
3348
 
3245
3349
static int send_ioctl(int fd, struct ifreq *ifr)
3246
3350
{
3247
3351
        return ioctl(fd, SIOCETHTOOL, ifr);