Skip to content

Commit d438945

Browse files
committed
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: David S. Miller <[email protected]>
2 parents 129bd7c + 542575f commit d438945

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

drivers/net/vxlan.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3175,9 +3175,29 @@ static void vxlan_get_drvinfo(struct net_device *netdev,
31753175
strlcpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver));
31763176
}
31773177

3178+
static int vxlan_get_link_ksettings(struct net_device *dev,
3179+
struct ethtool_link_ksettings *cmd)
3180+
{
3181+
struct vxlan_dev *vxlan = netdev_priv(dev);
3182+
struct vxlan_rdst *dst = &vxlan->default_dst;
3183+
struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
3184+
dst->remote_ifindex);
3185+
3186+
if (!lowerdev) {
3187+
cmd->base.duplex = DUPLEX_UNKNOWN;
3188+
cmd->base.port = PORT_OTHER;
3189+
cmd->base.speed = SPEED_UNKNOWN;
3190+
3191+
return 0;
3192+
}
3193+
3194+
return __ethtool_get_link_ksettings(lowerdev, cmd);
3195+
}
3196+
31783197
static const struct ethtool_ops vxlan_ethtool_ops = {
3179-
.get_drvinfo = vxlan_get_drvinfo,
3180-
.get_link = ethtool_op_get_link,
3198+
.get_drvinfo = vxlan_get_drvinfo,
3199+
.get_link = ethtool_op_get_link,
3200+
.get_link_ksettings = vxlan_get_link_ksettings,
31813201
};
31823202

31833203
static struct socket *vxlan_create_sock(struct net *net, bool ipv6,

net/bridge/br_device.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,37 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
263263
strlcpy(info->bus_info, "N/A", sizeof(info->bus_info));
264264
}
265265

266+
static int br_get_link_ksettings(struct net_device *dev,
267+
struct ethtool_link_ksettings *cmd)
268+
{
269+
struct net_bridge *br = netdev_priv(dev);
270+
struct net_bridge_port *p;
271+
272+
cmd->base.duplex = DUPLEX_UNKNOWN;
273+
cmd->base.port = PORT_OTHER;
274+
cmd->base.speed = SPEED_UNKNOWN;
275+
276+
list_for_each_entry(p, &br->port_list, list) {
277+
struct ethtool_link_ksettings ecmd;
278+
struct net_device *pdev = p->dev;
279+
280+
if (!netif_running(pdev) || !netif_oper_up(pdev))
281+
continue;
282+
283+
if (__ethtool_get_link_ksettings(pdev, &ecmd))
284+
continue;
285+
286+
if (ecmd.base.speed == (__u32)SPEED_UNKNOWN)
287+
continue;
288+
289+
if (cmd->base.speed == (__u32)SPEED_UNKNOWN ||
290+
cmd->base.speed < ecmd.base.speed)
291+
cmd->base.speed = ecmd.base.speed;
292+
}
293+
294+
return 0;
295+
}
296+
266297
static netdev_features_t br_fix_features(struct net_device *dev,
267298
netdev_features_t features)
268299
{
@@ -365,8 +396,9 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
365396
}
366397

367398
static const struct ethtool_ops br_ethtool_ops = {
368-
.get_drvinfo = br_getinfo,
369-
.get_link = ethtool_op_get_link,
399+
.get_drvinfo = br_getinfo,
400+
.get_link = ethtool_op_get_link,
401+
.get_link_ksettings = br_get_link_ksettings,
370402
};
371403

372404
static const struct net_device_ops br_netdev_ops = {

0 commit comments

Comments
 (0)