libnl 3.0
/home/tgr/dev/libnl/lib/route/ethtool.c
00001 /*
00002  * lib/route/ethtool.c          Ethtool (link)
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup link
00014  * @defgroup ethtool Ethtool
00015  * @{
00016  */
00017 
00018 #include <netlink-local.h>
00019 #include <netlink/netlink.h>
00020 #include <netlink/attr.h>
00021 #include <netlink/utils.h>
00022 #include <netlink/object.h>
00023 #include <netlink/route/rtnl.h>
00024 #include <netlink/route/link.h>
00025 #include <netlink/route/ethtool.h>
00026 #include <netlink/route/link/api.h>
00027 
00028 /** @cond SKIP */
00029 #define ETHTOOL_ATTR_SETTINGS   0x0001
00030 #define ETHTOOL_ATTR_DRVINFO    0x0002
00031 /** @endcond */
00032 
00033 static int settings_parse(struct rtnl_link *link, struct nlattr *attr)
00034 {
00035         nla_memcpy(&link->l_ethtool.e_settings, attr, sizeof(struct ethtool_cmd));
00036         link->l_ethtool.e_mask |= ETHTOOL_ATTR_SETTINGS;
00037         return 0;
00038 }
00039 
00040 static struct {
00041         int (*parse)(struct rtnl_link *, struct nlattr *);
00042 } ethtool_ops[] = {
00043         [IFLA_ETHTOOL_SETTINGS] = {     .parse = settings_parse, },
00044 };
00045 
00046 static struct nla_policy ethtool_policy[IFLA_ETHTOOL_MAX+1] = {
00047         [IFLA_ETHTOOL_SETTINGS] = { .minlen = sizeof(struct ethtool_cmd) },
00048         [IFLA_ETHTOOL_DRVINFO]  = { .type = NLA_NESTED },
00049 };
00050 
00051 static int parse_attr(struct rtnl_link *link, struct nlattr *attr)
00052 {
00053         int type = nla_type(attr) - 1;
00054 
00055         if (type < 0 || type >= ARRAY_SIZE(ethtool_ops))
00056                 return -NLE_INVAL;
00057 
00058         if (ethtool_ops[type].parse)
00059                 return ethtool_ops[type].parse(link, attr);
00060         
00061         return 0;
00062 }
00063 
00064 int rtnl_ethtool_parse(struct rtnl_link *link, struct nlattr *attr)
00065 {
00066         int remaining, err;
00067         struct nlattr *a;
00068 
00069         err = nla_validate(nla_data(attr), nla_len(attr), IFLA_ETHTOOL_MAX,
00070                            ethtool_policy);
00071         if (err < 0)
00072                 return err;
00073 
00074         nla_for_each_nested(a, attr, remaining)
00075                 parse_attr(link, a);
00076 
00077         return 0;
00078 }
00079 
00080 void rtnl_ethtool_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
00081 {
00082         struct rtnl_ethtool *e = &link->l_ethtool;
00083 
00084         if (e->e_mask & ETHTOOL_ATTR_SETTINGS) {
00085                 struct ethtool_cmd *cmd = &e->e_settings;
00086                 char buf[256];
00087 
00088                 nl_dump_line(p, "    ethtool:\n");
00089                 nl_dump_line(p, "      supported: %s\n",
00090                         rtnl_ethtool_supported2str(cmd->supported, buf, sizeof(buf)));
00091                 nl_dump_line(p, "      advertising: %s\n",
00092                         rtnl_ethtool_supported2str(cmd->advertising, buf, sizeof(buf)));
00093 
00094                 nl_dump_line(p, "      duplex: %u\n", cmd->duplex);
00095 
00096                 nl_dump_line(p, "      connector: %s\n",
00097                         rtnl_ethtool_connector2str(cmd->port, buf, sizeof(buf)));
00098                 nl_dump_line(p, "      phy-address: %#x\n", cmd->phy_address);
00099                 nl_dump_line(p, "      transceiver: %s\n",
00100                         rtnl_ethtool_transceiver2str(cmd->transceiver, buf, sizeof(buf)));
00101 
00102                 nl_dump_line(p, "      autonegotiation: %s\n",
00103                         cmd->autoneg ? "enabled" : "disabled");
00104 
00105                 nl_dump_line(p, "      max-tx-pkts: %u\n", cmd->maxtxpkt);
00106                 nl_dump_line(p, "      max-rx-pkts: %u\n", cmd->maxrxpkt);
00107 
00108 #if 0
00109         __u16   speed;          /* The forced speed (lower bits) in
00110                                  * Mbps. Please use
00111                                  * ethtool_cmd_speed()/_set() to
00112                                  * access it */
00113         __u8    mdio_support;
00114         __u16   speed_hi;       /* The forced speed (upper
00115                                  * bits) in Mbps. Please use
00116                                  * ethtool_cmd_speed()/_set() to
00117                                  * access it */
00118         __u8    eth_tp_mdix;
00119         __u8    reserved2;
00120         __u32   lp_advertising; /* Features the link partner advertises */
00121         __u32   reserved[2];
00122 #endif
00123 
00124         }
00125 }
00126 
00127 static const struct trans_tbl ethtool_supported[] = {
00128         __ADD(SUPPORTED_10baseT_Half, 10baseT-Half)
00129         __ADD(SUPPORTED_10baseT_Full, 10baseT-Full)
00130         __ADD(SUPPORTED_100baseT_Half, 100baseT-Half)
00131         __ADD(SUPPORTED_100baseT_Full, 100baseT-Full)
00132         __ADD(SUPPORTED_1000baseT_Half, 1000baseT-Half)
00133         __ADD(SUPPORTED_1000baseT_Full, 1000baseT-Full)
00134         __ADD(SUPPORTED_Autoneg, Autoneg)
00135         __ADD(SUPPORTED_TP, TP)
00136         __ADD(SUPPORTED_AUI, AUI)
00137         __ADD(SUPPORTED_MII, MII)
00138         __ADD(SUPPORTED_FIBRE, FIBRE)
00139         __ADD(SUPPORTED_BNC, BNC)
00140         __ADD(SUPPORTED_10000baseT_Full, 10000baseT-Full)
00141         __ADD(SUPPORTED_Pause, Pause)
00142         __ADD(SUPPORTED_Asym_Pause, Asym-Pause)
00143         __ADD(SUPPORTED_2500baseX_Full, 2500baseX-Full)
00144         __ADD(SUPPORTED_Backplane, Backplane)
00145         __ADD(SUPPORTED_1000baseKX_Full, 1000baseKX-Full)
00146         __ADD(SUPPORTED_10000baseKX4_Full, 10000baseKX4-Full)
00147         __ADD(SUPPORTED_10000baseKR_Full, 10000baseKR-Full)
00148         __ADD(SUPPORTED_10000baseR_FEC, 1000baseR-FEC)
00149         __ADD(SUPPORTED_20000baseMLD2_Full, 20000baseMLD2-Full)
00150         __ADD(SUPPORTED_20000baseKR2_Full, 20000baseKR2-Full)
00151 };
00152 
00153 char *rtnl_ethtool_supported2str(int supported, char *buf, size_t len)
00154 {
00155         return __flags2str(supported, buf, len, ethtool_supported,
00156                            ARRAY_SIZE(ethtool_supported));
00157 }
00158 
00159 uint32_t rtnl_ethtool_get_supported(struct rtnl_link *link)
00160 {
00161         return 0;
00162 }
00163 
00164 uint32_t rtnl_ethtool_get_advertising(struct rtnl_link *link)
00165 {
00166         return 0;
00167 }
00168 
00169 static const struct trans_tbl ethtool_connectors[] = {
00170         __ADD(PORT_TP, tp)
00171         __ADD(PORT_AUI, aui)
00172         __ADD(PORT_MII, mii)
00173         __ADD(PORT_FIBRE, fibre)
00174         __ADD(PORT_BNC, bnc)
00175         __ADD(PORT_DA, da)
00176         __ADD(PORT_NONE, none)
00177         __ADD(PORT_OTHER, other)
00178 };
00179 
00180 char *rtnl_ethtool_connector2str(int connector, char *buf, size_t len)
00181 {
00182         return __type2str(connector, buf, len, ethtool_connectors,
00183                           ARRAY_SIZE(ethtool_connectors));
00184 }
00185 
00186 int rtnl_ethtool_str2connector(const char *name)
00187 {
00188         return __str2type(name, ethtool_connectors,
00189                           ARRAY_SIZE(ethtool_connectors));
00190 }
00191 
00192 static const struct trans_tbl ethtool_xcvrs[] = {
00193         __ADD(XCVR_INTERNAL, internal)
00194         __ADD(XCVR_EXTERNAL, external)
00195         __ADD(XCVR_DUMMY1, dummy1)
00196         __ADD(XCVR_DUMMY2, dummy2)
00197         __ADD(XCVR_DUMMY3, dummy3)
00198 };
00199 
00200 char *rtnl_ethtool_transceiver2str(int xcvr, char *buf, size_t len)
00201 {
00202         return __type2str(xcvr, buf, len, ethtool_xcvrs,
00203                           ARRAY_SIZE(ethtool_xcvrs));
00204 }
00205 
00206 int rtnl_ethtool_str2transceiver(const char *name)
00207 {
00208         return __str2type(name, ethtool_xcvrs, ARRAY_SIZE(ethtool_xcvrs));
00209 }
00210 
00211 
00212 /** @} */