int ni_ethtool_set_priv_flags(const char *ifname, ni_ethtool_t *ethtool, const ni_ethtool_priv_flags_t *pflags) { static const ni_ethtool_cmd_info_t NI_ETHTOOL_CMD_SPFLAGS = { ETHTOOL_SPFLAGS, "set priv-flags" }; struct ethtool_value ecmd; unsigned int i, bit; const char *name; ni_bool_t enabled; int ret; if (!pflags || !pflags->names.count) return 1; /* nothing to set */ if (!ethtool->priv_flags && (ret = ni_ethtool_get_priv_flags(ifname, ethtool)) < 0) return ret; if (!ethtool->priv_flags || !ethtool->priv_flags->names.count) return -EOPNOTSUPP; memset(&ecmd, 0, sizeof(ecmd)); ecmd.data = ethtool->priv_flags->bitmap; /* set every single bit separately in case one fails? */ for (i = 0; i < pflags->names.count; ++i) { name = pflags->names.data[i]; if (ni_string_empty(name)) continue; enabled = !!(pflags->bitmap & NI_BIT(i)); bit = ni_string_array_index(ðtool->priv_flags->names, name); if (bit == -1U) { ni_info("%s: unable to set unknown driver private flag '%s'", ifname, name); continue; } ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_IFCONFIG, "%s: setting driver private flag '%s' to %s", ifname, name, ni_format_boolean(enabled)); if (enabled) ecmd.data |= NI_BIT(bit); else ecmd.data &= ~NI_BIT(bit); } if (ecmd.data == ethtool->priv_flags->bitmap) return 0; ret = ni_ethtool_call(ifname, &NI_ETHTOOL_CMD_SPFLAGS, &ecmd, NULL); ni_ethtool_set_supported(ethtool, NI_ETHTOOL_SUPP_SET_PRIV_FLAGS, ret != -EOPNOTSUPP); if (ret < 0) return ret; return 0; }
/* * main system refresh and setup functions */ static ni_bool_t ni_ethtool_refresh(ni_netdev_t *dev) { ni_ethtool_t *ethtool; if (!dev || !(ethtool = ni_netdev_get_ethtool(dev))) return FALSE; if (!ethtool->driver_info) ni_ethtool_get_driver_info(dev->name, ethtool); ni_ethtool_get_priv_flags(dev->name, ethtool); return TRUE; }
/* * private-flags */ static int get_ethtool_priv_flags(const ni_netdev_ref_t *ref, ni_ethtool_t *ethtool, struct ethtool_args *args) { const ni_ethtool_priv_flags_t *pflags; const char *name; unsigned int n; (void)args; if (ni_ethtool_get_priv_flags(ref, ethtool) < 0 || !(pflags = ethtool->priv_flags)) return -1; printf("private-flags:\n"); for (n = 0; n < pflags->names.count; ++n) { name = pflags->names.data[n]; printf("\t%s: %s\n", name, pflags->bitmap & NI_BIT(n) ? "on" : "off"); } return 0; }