Commit d438945a authored by David S. Miller's avatar David S. Miller

Merge branch 'Implement-get_link_ksettings-for-VXLAN-and-bridge'

Matthias Schiffer says:

====================
Implement get_link_ksettings for VXLAN and bridge

Mesh routing protocol batman-adv (in particular the new BATMAN_V algorithm)
uses the link speed reported by get_link_ksettings to determine a path
metric for wired links. In the mesh framework Gluon [1], we layer VXLAN
and sometimes bridge interfaces on our Ethernet links.

These patches implement get_link_ksettings for these two interface types.
While this is obviously not accurate for bridges with multiple active
ports, it's much better than having no estimate at all (and in the
particular setup of Gluon, bridges with a single port aren't completely
uncommon).

[1] https://github.com/freifunk-gluon/gluon
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 129bd7ca 542575fe
...@@ -3175,9 +3175,29 @@ static void vxlan_get_drvinfo(struct net_device *netdev, ...@@ -3175,9 +3175,29 @@ static void vxlan_get_drvinfo(struct net_device *netdev,
strlcpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver)); strlcpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver));
} }
static int vxlan_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
dst->remote_ifindex);
if (!lowerdev) {
cmd->base.duplex = DUPLEX_UNKNOWN;
cmd->base.port = PORT_OTHER;
cmd->base.speed = SPEED_UNKNOWN;
return 0;
}
return __ethtool_get_link_ksettings(lowerdev, cmd);
}
static const struct ethtool_ops vxlan_ethtool_ops = { static const struct ethtool_ops vxlan_ethtool_ops = {
.get_drvinfo = vxlan_get_drvinfo, .get_drvinfo = vxlan_get_drvinfo,
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
.get_link_ksettings = vxlan_get_link_ksettings,
}; };
static struct socket *vxlan_create_sock(struct net *net, bool ipv6, static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
......
...@@ -263,6 +263,37 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) ...@@ -263,6 +263,37 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
strlcpy(info->bus_info, "N/A", sizeof(info->bus_info)); strlcpy(info->bus_info, "N/A", sizeof(info->bus_info));
} }
static int br_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
struct net_bridge *br = netdev_priv(dev);
struct net_bridge_port *p;
cmd->base.duplex = DUPLEX_UNKNOWN;
cmd->base.port = PORT_OTHER;
cmd->base.speed = SPEED_UNKNOWN;
list_for_each_entry(p, &br->port_list, list) {
struct ethtool_link_ksettings ecmd;
struct net_device *pdev = p->dev;
if (!netif_running(pdev) || !netif_oper_up(pdev))
continue;
if (__ethtool_get_link_ksettings(pdev, &ecmd))
continue;
if (ecmd.base.speed == (__u32)SPEED_UNKNOWN)
continue;
if (cmd->base.speed == (__u32)SPEED_UNKNOWN ||
cmd->base.speed < ecmd.base.speed)
cmd->base.speed = ecmd.base.speed;
}
return 0;
}
static netdev_features_t br_fix_features(struct net_device *dev, static netdev_features_t br_fix_features(struct net_device *dev,
netdev_features_t features) netdev_features_t features)
{ {
...@@ -365,8 +396,9 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev) ...@@ -365,8 +396,9 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
} }
static const struct ethtool_ops br_ethtool_ops = { static const struct ethtool_ops br_ethtool_ops = {
.get_drvinfo = br_getinfo, .get_drvinfo = br_getinfo,
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
.get_link_ksettings = br_get_link_ksettings,
}; };
static const struct net_device_ops br_netdev_ops = { static const struct net_device_ops br_netdev_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment