diff options
author | Roopa Prabhu <roopa@cumulusnetworks.com> | 2015-09-15 17:44:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-09-15 18:03:57 -0400 |
commit | d64f69b0373a7d0bcec8b5da7712977518a8f42b (patch) | |
tree | 046d2d594dd93ad4b8654cfed864d5c978146f2e /net | |
parent | daf158d0d544cec80b7b30deff8cfc59a6e17610 (diff) |
rtnetlink: catch -EOPNOTSUPP errors from ndo_bridge_getlink
problem reported:
kernel 4.1.3
------------
# bridge vlan
port vlan ids
eth0 1 PVID Egress Untagged
90
91
92
93
94
95
96
97
98
99
100
vmbr0 1 PVID Egress Untagged
94
kernel 4.2
-----------
# bridge vlan
port vlan ids
ndo_bridge_getlink can return -EOPNOTSUPP when an interfaces
ndo_bridge_getlink op is set to switchdev_port_bridge_getlink
and CONFIG_SWITCHDEV is not defined. This today can happen to
bond, rocker and team devices. This patch adds -EOPNOTSUPP
checks after calls to ndo_bridge_getlink.
Fixes: 85fdb956726ff2a ("switchdev: cut over to new switchdev_port_bridge_getlink")
Reported-by: Alexandre DERUMIER <aderumier@odiso.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/rtnetlink.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a466821d1441..0ec48403ed68 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -3047,6 +3047,7 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
3047 | u32 portid = NETLINK_CB(cb->skb).portid; | 3047 | u32 portid = NETLINK_CB(cb->skb).portid; |
3048 | u32 seq = cb->nlh->nlmsg_seq; | 3048 | u32 seq = cb->nlh->nlmsg_seq; |
3049 | u32 filter_mask = 0; | 3049 | u32 filter_mask = 0; |
3050 | int err; | ||
3050 | 3051 | ||
3051 | if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) { | 3052 | if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) { |
3052 | struct nlattr *extfilt; | 3053 | struct nlattr *extfilt; |
@@ -3067,20 +3068,25 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
3067 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); | 3068 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); |
3068 | 3069 | ||
3069 | if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) { | 3070 | if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) { |
3070 | if (idx >= cb->args[0] && | 3071 | if (idx >= cb->args[0]) { |
3071 | br_dev->netdev_ops->ndo_bridge_getlink( | 3072 | err = br_dev->netdev_ops->ndo_bridge_getlink( |
3072 | skb, portid, seq, dev, filter_mask, | 3073 | skb, portid, seq, dev, |
3073 | NLM_F_MULTI) < 0) | 3074 | filter_mask, NLM_F_MULTI); |
3074 | break; | 3075 | if (err < 0 && err != -EOPNOTSUPP) |
3076 | break; | ||
3077 | } | ||
3075 | idx++; | 3078 | idx++; |
3076 | } | 3079 | } |
3077 | 3080 | ||
3078 | if (ops->ndo_bridge_getlink) { | 3081 | if (ops->ndo_bridge_getlink) { |
3079 | if (idx >= cb->args[0] && | 3082 | if (idx >= cb->args[0]) { |
3080 | ops->ndo_bridge_getlink(skb, portid, seq, dev, | 3083 | err = ops->ndo_bridge_getlink(skb, portid, |
3081 | filter_mask, | 3084 | seq, dev, |
3082 | NLM_F_MULTI) < 0) | 3085 | filter_mask, |
3083 | break; | 3086 | NLM_F_MULTI); |
3087 | if (err < 0 && err != -EOPNOTSUPP) | ||
3088 | break; | ||
3089 | } | ||
3084 | idx++; | 3090 | idx++; |
3085 | } | 3091 | } |
3086 | } | 3092 | } |