Skip to content

Commit 862096a

Browse files
ogerlitzdavem330
authored andcommitted
IB/ipoib: Add more rtnl_link_ops callbacks
Add the rtnl_link_ops changelink and fill_info callbacks, through which the admin can now set/get the driver mode, etc policies. Maintain the proprietary sysfs entries only for legacy childs. For child devices, set dev->iflink to point to the parent device ifindex, such that user space tools can now correctly show the uplink relation as done for vlan, macvlan, etc devices. Pointed out by Patrick McHardy <[email protected]> Signed-off-by: Or Gerlitz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d755998 commit 862096a

File tree

6 files changed

+118
-26
lines changed

6 files changed

+118
-26
lines changed

drivers/infiniband/ulp/ipoib/ipoib.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
523523
int __init ipoib_netlink_init(void);
524524
void __exit ipoib_netlink_fini(void);
525525

526+
void ipoib_set_umcast(struct net_device *ndev, int umcast_val);
527+
int ipoib_set_mode(struct net_device *dev, const char *buf);
528+
526529
void ipoib_setup(struct net_device *dev);
527530

528531
void ipoib_pkey_poll(struct work_struct *work);

drivers/infiniband/ulp/ipoib/ipoib_cm.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,15 +1448,10 @@ static ssize_t show_mode(struct device *d, struct device_attribute *attr,
14481448
return sprintf(buf, "datagram\n");
14491449
}
14501450

1451-
static ssize_t set_mode(struct device *d, struct device_attribute *attr,
1452-
const char *buf, size_t count)
1451+
int ipoib_set_mode(struct net_device *dev, const char *buf)
14531452
{
1454-
struct net_device *dev = to_net_dev(d);
14551453
struct ipoib_dev_priv *priv = netdev_priv(dev);
14561454

1457-
if (!rtnl_trylock())
1458-
return restart_syscall();
1459-
14601455
/* flush paths if we switch modes so that connections are restarted */
14611456
if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) {
14621457
set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
@@ -1467,7 +1462,8 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
14671462
priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
14681463

14691464
ipoib_flush_paths(dev);
1470-
return count;
1465+
rtnl_lock();
1466+
return 0;
14711467
}
14721468

14731469
if (!strcmp(buf, "datagram\n")) {
@@ -1476,14 +1472,32 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
14761472
dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu));
14771473
rtnl_unlock();
14781474
ipoib_flush_paths(dev);
1479-
1480-
return count;
1475+
rtnl_lock();
1476+
return 0;
14811477
}
1482-
rtnl_unlock();
14831478

14841479
return -EINVAL;
14851480
}
14861481

1482+
static ssize_t set_mode(struct device *d, struct device_attribute *attr,
1483+
const char *buf, size_t count)
1484+
{
1485+
struct net_device *dev = to_net_dev(d);
1486+
int ret;
1487+
1488+
if (!rtnl_trylock())
1489+
return restart_syscall();
1490+
1491+
ret = ipoib_set_mode(dev, buf);
1492+
1493+
rtnl_unlock();
1494+
1495+
if (!ret)
1496+
return count;
1497+
1498+
return ret;
1499+
}
1500+
14871501
static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode);
14881502

14891503
int ipoib_cm_add_mode_attr(struct net_device *dev)

drivers/infiniband/ulp/ipoib/ipoib_main.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,19 +1381,25 @@ static ssize_t show_umcast(struct device *dev,
13811381
return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags));
13821382
}
13831383

1384-
static ssize_t set_umcast(struct device *dev,
1385-
struct device_attribute *attr,
1386-
const char *buf, size_t count)
1384+
void ipoib_set_umcast(struct net_device *ndev, int umcast_val)
13871385
{
1388-
struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev));
1389-
unsigned long umcast_val = simple_strtoul(buf, NULL, 0);
1386+
struct ipoib_dev_priv *priv = netdev_priv(ndev);
13901387

13911388
if (umcast_val > 0) {
13921389
set_bit(IPOIB_FLAG_UMCAST, &priv->flags);
13931390
ipoib_warn(priv, "ignoring multicast groups joined directly "
13941391
"by userspace\n");
13951392
} else
13961393
clear_bit(IPOIB_FLAG_UMCAST, &priv->flags);
1394+
}
1395+
1396+
static ssize_t set_umcast(struct device *dev,
1397+
struct device_attribute *attr,
1398+
const char *buf, size_t count)
1399+
{
1400+
unsigned long umcast_val = simple_strtoul(buf, NULL, 0);
1401+
1402+
ipoib_set_umcast(to_net_dev(dev), umcast_val);
13971403

13981404
return count;
13991405
}

drivers/infiniband/ulp/ipoib/ipoib_netlink.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,60 @@
3737

3838
static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = {
3939
[IFLA_IPOIB_PKEY] = { .type = NLA_U16 },
40+
[IFLA_IPOIB_MODE] = { .type = NLA_U16 },
41+
[IFLA_IPOIB_UMCAST] = { .type = NLA_U16 },
4042
};
4143

44+
static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev)
45+
{
46+
struct ipoib_dev_priv *priv = netdev_priv(dev);
47+
u16 val;
48+
49+
if (nla_put_u16(skb, IFLA_IPOIB_PKEY, priv->pkey))
50+
goto nla_put_failure;
51+
52+
val = test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
53+
if (nla_put_u16(skb, IFLA_IPOIB_MODE, val))
54+
goto nla_put_failure;
55+
56+
val = test_bit(IPOIB_FLAG_UMCAST, &priv->flags);
57+
if (nla_put_u16(skb, IFLA_IPOIB_UMCAST, val))
58+
goto nla_put_failure;
59+
60+
return 0;
61+
62+
nla_put_failure:
63+
return -EMSGSIZE;
64+
}
65+
66+
static int ipoib_changelink(struct net_device *dev,
67+
struct nlattr *tb[], struct nlattr *data[])
68+
{
69+
u16 mode, umcast;
70+
int ret = 0;
71+
72+
if (data[IFLA_IPOIB_MODE]) {
73+
mode = nla_get_u16(data[IFLA_IPOIB_MODE]);
74+
if (mode == IPOIB_MODE_DATAGRAM)
75+
ret = ipoib_set_mode(dev, "datagram\n");
76+
else if (mode == IPOIB_MODE_CONNECTED)
77+
ret = ipoib_set_mode(dev, "connected\n");
78+
else
79+
ret = -EINVAL;
80+
81+
if (ret < 0)
82+
goto out_err;
83+
}
84+
85+
if (data[IFLA_IPOIB_UMCAST]) {
86+
umcast = nla_get_u16(data[IFLA_IPOIB_UMCAST]);
87+
ipoib_set_umcast(dev, umcast);
88+
}
89+
90+
out_err:
91+
return ret;
92+
}
93+
4294
static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
4395
struct nlattr *tb[], struct nlattr *data[])
4496
{
@@ -69,6 +121,8 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
69121

70122
err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD);
71123

124+
if (!err && data)
125+
err = ipoib_changelink(dev, tb, data);
72126
return err;
73127
}
74128

@@ -87,7 +141,9 @@ static void ipoib_unregister_child_dev(struct net_device *dev, struct list_head
87141

88142
static size_t ipoib_get_size(const struct net_device *dev)
89143
{
90-
return nla_total_size(2); /* IFLA_IPOIB_PKEY */
144+
return nla_total_size(2) + /* IFLA_IPOIB_PKEY */
145+
nla_total_size(2) + /* IFLA_IPOIB_MODE */
146+
nla_total_size(2); /* IFLA_IPOIB_UMCAST */
91147
}
92148

93149
static struct rtnl_link_ops ipoib_link_ops __read_mostly = {
@@ -97,8 +153,10 @@ static struct rtnl_link_ops ipoib_link_ops __read_mostly = {
97153
.priv_size = sizeof(struct ipoib_dev_priv),
98154
.setup = ipoib_setup,
99155
.newlink = ipoib_new_child_link,
156+
.changelink = ipoib_changelink,
100157
.dellink = ipoib_unregister_child_dev,
101158
.get_size = ipoib_get_size,
159+
.fill_info = ipoib_fill_info,
102160
};
103161

104162
int __init ipoib_netlink_init(void)

drivers/infiniband/ulp/ipoib/ipoib_vlan.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,21 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
8888

8989
ipoib_create_debug_files(priv->dev);
9090

91-
if (ipoib_cm_add_mode_attr(priv->dev))
92-
goto sysfs_failed;
93-
if (ipoib_add_pkey_attr(priv->dev))
94-
goto sysfs_failed;
95-
if (ipoib_add_umcast_attr(priv->dev))
96-
goto sysfs_failed;
97-
98-
if (device_create_file(&priv->dev->dev, &dev_attr_parent))
99-
goto sysfs_failed;
91+
/* RTNL childs don't need proprietary sysfs entries */
92+
if (type == IPOIB_LEGACY_CHILD) {
93+
if (ipoib_cm_add_mode_attr(priv->dev))
94+
goto sysfs_failed;
95+
if (ipoib_add_pkey_attr(priv->dev))
96+
goto sysfs_failed;
97+
if (ipoib_add_umcast_attr(priv->dev))
98+
goto sysfs_failed;
99+
100+
if (device_create_file(&priv->dev->dev, &dev_attr_parent))
101+
goto sysfs_failed;
102+
}
100103

101-
priv->child_type = type;
104+
priv->child_type = type;
105+
priv->dev->iflink = ppriv->dev->ifindex;
102106
list_add_tail(&priv->list, &ppriv->child_intfs);
103107

104108
return 0;

include/linux/if_link.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,16 @@ struct ifla_port_vsi {
404404
enum {
405405
IFLA_IPOIB_UNSPEC,
406406
IFLA_IPOIB_PKEY,
407+
IFLA_IPOIB_MODE,
408+
IFLA_IPOIB_UMCAST,
407409
__IFLA_IPOIB_MAX
408410
};
409411

412+
enum {
413+
IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */
414+
IPOIB_MODE_CONNECTED = 1, /* using connected QPs */
415+
};
416+
410417
#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
411418

412419
#endif /* _LINUX_IF_LINK_H */

0 commit comments

Comments
 (0)