/* * common.h - common code header * * Data and functions shared by ioctl and netlink implementation. */ #include "internal.h" #include "json_print.h" #include "common.h" #ifndef HAVE_NETIF_MSG enum { NETIF_MSG_DRV = 0x0001, NETIF_MSG_PROBE = 0x0002, NETIF_MSG_LINK = 0x0004, NETIF_MSG_TIMER = 0x0008, NETIF_MSG_IFDOWN = 0x0010, NETIF_MSG_IFUP = 0x0020, NETIF_MSG_RX_ERR = 0x0040, NETIF_MSG_TX_ERR = 0x0080, NETIF_MSG_TX_QUEUED = 0x0100, NETIF_MSG_INTR = 0x0200, NETIF_MSG_TX_DONE = 0x0400, NETIF_MSG_RX_STATUS = 0x0800, NETIF_MSG_PKTDATA = 0x1000, NETIF_MSG_HW = 0x2000, NETIF_MSG_WOL = 0x4000, }; #endif const struct flag_info flags_msglvl[] = { { "drv", NETIF_MSG_DRV }, { "probe", NETIF_MSG_PROBE }, { "link", NETIF_MSG_LINK }, { "timer", NETIF_MSG_TIMER }, { "ifdown", NETIF_MSG_IFDOWN }, { "ifup", NETIF_MSG_IFUP }, { "rx_err", NETIF_MSG_RX_ERR }, { "tx_err", NETIF_MSG_TX_ERR }, { "tx_queued", NETIF_MSG_TX_QUEUED }, { "intr", NETIF_MSG_INTR }, { "tx_done", NETIF_MSG_TX_DONE }, { "rx_status", NETIF_MSG_RX_STATUS }, { "pktdata", NETIF_MSG_PKTDATA }, { "hw", NETIF_MSG_HW }, { "wol", NETIF_MSG_WOL }, {} }; const unsigned int n_flags_msglvl = ARRAY_SIZE(flags_msglvl) - 1; const struct off_flag_def off_flag_def[] = { { "rx", "rx-checksumming", "rx-checksum", ETHTOOL_GRXCSUM, ETHTOOL_SRXCSUM, ETH_FLAG_RXCSUM, 0 }, { "tx", "tx-checksumming", "tx-checksum-*", ETHTOOL_GTXCSUM, ETHTOOL_STXCSUM, ETH_FLAG_TXCSUM, 0 }, { "sg", "scatter-gather", "tx-scatter-gather*", ETHTOOL_GSG, ETHTOOL_SSG, ETH_FLAG_SG, 0 }, { "tso", "tcp-segmentation-offload", "tx-tcp*-segmentation", ETHTOOL_GTSO, ETHTOOL_STSO, ETH_FLAG_TSO, 0 }, { "ufo", "udp-fragmentation-offload", "tx-udp-fragmentation", ETHTOOL_GUFO, ETHTOOL_SUFO, ETH_FLAG_UFO, 0 }, { "gso", "generic-segmentation-offload", "tx-generic-segmentation", ETHTOOL_GGSO, ETHTOOL_SGSO, ETH_FLAG_GSO, 0 }, { "gro", "generic-receive-offload", "rx-gro", ETHTOOL_GGRO, ETHTOOL_SGRO, ETH_FLAG_GRO, 0 }, { "lro", "large-receive-offload", "rx-lro", 0, 0, ETH_FLAG_LRO, KERNEL_VERSION(2,6,24) }, { "rxvlan", "rx-vlan-offload", "rx-vlan-hw-parse", 0, 0, ETH_FLAG_RXVLAN, KERNEL_VERSION(2,6,37) }, { "txvlan", "tx-vlan-offload", "tx-vlan-hw-insert", 0, 0, ETH_FLAG_TXVLAN, KERNEL_VERSION(2,6,37) }, { "ntuple", "ntuple-filters", "rx-ntuple-filter", 0, 0, ETH_FLAG_NTUPLE, 0 }, { "rxhash", "receive-hashing", "rx-hashing", 0, 0, ETH_FLAG_RXHASH, 0 }, }; void print_flags(const struct flag_info *info, unsigned int n_info, u32 value) { const char *sep = ""; while (n_info) { if (value & info->value) { printf("%s%s", sep, info->name); sep = " "; value &= ~info->value; } ++info; --n_info; } /* Print any unrecognised flags in hex */ if (value) printf("%s%#x", sep, value); } static char *unparse_wolopts(int wolopts) { static char buf[16]; char *p = buf; memset(buf, 0, sizeof(buf)); if (wolopts) { if (wolopts & WAKE_PHY) *p++ = 'p'; if (wolopts & WAKE_UCAST) *p++ = 'u'; if (wolopts & WAKE_MCAST) *p++ = 'm'; if (wolopts & WAKE_BCAST) *p++ = 'b'; if (wolopts & WAKE_ARP) *p++ = 'a'; if (wolopts & WAKE_MAGIC) *p++ = 'g'; if (wolopts & WAKE_MAGICSECURE) *p++ = 's'; if (wolopts & WAKE_FILTER) *p++ = 'f'; } else { *p = 'd'; } return buf; } int dump_wol(struct ethtool_wolinfo *wol) { print_string(PRINT_ANY, "supports-wake-on", " Supports Wake-on: %s\n", unparse_wolopts(wol->supported)); print_string(PRINT_ANY, "wake-on", " Wake-on: %s\n", unparse_wolopts(wol->wolopts)); if (wol->supported & WAKE_MAGICSECURE) { int i; int delim = 0; open_json_array("secureon-password", ""); if (!is_json_context()) fprintf(stdout, " SecureOn password: "); for (i = 0; i < SOPASS_MAX; i++) { __u8 sopass = wol->sopass[i]; if (!is_json_context()) fprintf(stdout, "%s%02x", delim ? ":" : "", sopass); else print_hex(PRINT_JSON, NULL, "%02u", sopass); delim = 1; } close_json_array("\n"); } return 0; } void dump_mdix(u8 mdix, u8 mdix_ctrl) { bool mdi_x = false; bool mdi_x_forced = false; bool mdi_x_auto = false; if (mdix_ctrl == ETH_TP_MDI) { mdi_x = false; mdi_x_forced = true; } else if (mdix_ctrl == ETH_TP_MDI_X) { mdi_x = true; mdi_x_forced = true; } else { switch (mdix) { case ETH_TP_MDI_X: mdi_x = true; break; default: print_string(PRINT_FP, NULL, "\tMDI-X: %s\n", "Unknown"); return; } if (mdix_ctrl == ETH_TP_MDI_AUTO) mdi_x_auto = true; } if (is_json_context()) { print_bool(PRINT_JSON, "mdi-x", NULL, mdi_x); print_bool(PRINT_JSON, "mdi-x-forced", NULL, mdi_x_forced); print_bool(PRINT_JSON, "mdi-x-auto", NULL, mdi_x_auto); } else { fprintf(stdout, " MDI-X: "); if (mdi_x_forced) { if (mdi_x) fprintf(stdout, "on (forced)\n"); else fprintf(stdout, "off (forced)\n"); } else { if (mdi_x) fprintf(stdout, "on"); else fprintf(stdout, "off"); if (mdi_x_auto) fprintf(stdout, " (auto)"); fprintf(stdout, "\n"); } } } void print_indir_table(struct cmd_context *ctx, u64 ring_count, u32 indir_size, u32 *indir) { u32 i; printf("RX flow hash indirection table for %s with %llu RX ring(s):\n", ctx->devname, ring_count); if (!indir_size) printf("Operation not supported\n"); for (i = 0; i < indir_size; i++) { if (i % 8 == 0) printf("%5u: ", i); printf(" %5u", indir[i]); if (i % 8 == 7 || i == indir_size - 1) fputc('\n', stdout); } } void print_rss_hkey(u8 *hkey, u32 hkey_size) { u32 i; printf("RSS hash key:\n"); if (!hkey_size || !hkey) printf("Operation not supported\n"); for (i = 0; i < hkey_size; i++) { if (i == (hkey_size - 1)) printf("%02x\n", hkey[i]); else printf("%02x:", hkey[i]); } }