diff options
author | Ursula Braun <ubraun@linux.ibm.com> | 2018-05-02 17:56:47 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-02 20:29:12 +0300 |
commit | cb9d43f6775457cac75544bc4197f26ac2b6f294 (patch) | |
tree | de4b7fd5d06c7221a155a9bf9000f513b93c4275 /net/smc | |
parent | 9b67e26f936cd40a551da98914ed56dc5606686b (diff) | |
download | linux-cb9d43f6775457cac75544bc4197f26ac2b6f294.tar.xz |
net/smc: determine vlan_id of stacked net_device
An SMC link group is bound to a specific vlan_id. Its link uses
the RoCE-GIDs established for the specific vlan_id. This patch makes
sure the appropriate vlan_id is determined for stacked scenarios like
for instance a master bonding device with vlan devices enslaved.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc')
-rw-r--r-- | net/smc/smc_core.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index d9247765aff3..1f3ea62fac5c 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -360,7 +360,8 @@ void smc_lgr_terminate(struct smc_link_group *lgr) static int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id) { struct dst_entry *dst = sk_dst_get(clcsock->sk); - int rc = 0; + struct net_device *ndev; + int i, nest_lvl, rc = 0; *vlan_id = 0; if (!dst) { @@ -372,8 +373,27 @@ static int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id) goto out_rel; } - if (is_vlan_dev(dst->dev)) - *vlan_id = vlan_dev_vlan_id(dst->dev); + ndev = dst->dev; + if (is_vlan_dev(ndev)) { + *vlan_id = vlan_dev_vlan_id(ndev); + goto out_rel; + } + + rtnl_lock(); + nest_lvl = dev_get_nest_level(ndev); + for (i = 0; i < nest_lvl; i++) { + struct list_head *lower = &ndev->adj_list.lower; + + if (list_empty(lower)) + break; + lower = lower->next; + ndev = (struct net_device *)netdev_lower_get_next(ndev, &lower); + if (is_vlan_dev(ndev)) { + *vlan_id = vlan_dev_vlan_id(ndev); + break; + } + } + rtnl_unlock(); out_rel: dst_release(dst); |