diff options
Diffstat (limited to 'include/rdma/ib_addr.h')
| -rw-r--r-- | include/rdma/ib_addr.h | 94 | 
1 files changed, 62 insertions, 32 deletions
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index b5fc9f39122..ce55906b54a 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -38,10 +38,15 @@  #include <linux/in6.h>  #include <linux/if_arp.h>  #include <linux/netdevice.h> +#include <linux/inetdevice.h>  #include <linux/socket.h>  #include <linux/if_vlan.h> +#include <net/ipv6.h> +#include <net/if_inet6.h> +#include <net/ip.h>  #include <rdma/ib_verbs.h>  #include <rdma/ib_pack.h> +#include <net/ipv6.h>  struct rdma_addr_client {  	atomic_t refcount; @@ -72,7 +77,8 @@ struct rdma_dev_addr {   * rdma_translate_ip - Translate a local IP address to an RDMA hardware   *   address.   */ -int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr); +int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr, +		      u16 *vlan_id);  /**   * rdma_resolve_ip - Resolve source and destination IP addresses to @@ -102,11 +108,11 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr);  int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,  	      const unsigned char *dst_dev_addr); -static inline int ip_addr_size(struct sockaddr *addr) -{ -	return addr->sa_family == AF_INET6 ? -	       sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); -} +int rdma_addr_size(struct sockaddr *addr); + +int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id); +int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *smac, +			       u16 *vlan_id);  static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)  { @@ -130,41 +136,60 @@ static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr)  	return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;  } -static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid) +static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)  { -	memset(gid->raw, 0, 16); -	*((__be32 *) gid->raw) = cpu_to_be32(0xfe800000); -	if (vid < 0x1000) { -		gid->raw[12] = vid & 0xff; -		gid->raw[11] = vid >> 8; -	} else { -		gid->raw[12] = 0xfe; -		gid->raw[11] = 0xff; +	return dev->priv_flags & IFF_802_1Q_VLAN ? +		vlan_dev_vlan_id(dev) : 0xffff; +} + +static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid) +{ +	switch (addr->sa_family) { +	case AF_INET: +		ipv6_addr_set_v4mapped(((struct sockaddr_in *) +					addr)->sin_addr.s_addr, +				       (struct in6_addr *)gid); +		break; +	case AF_INET6: +		memcpy(gid->raw, &((struct sockaddr_in6 *)addr)->sin6_addr, 16); +		break; +	default: +		return -EINVAL;  	} -	memcpy(gid->raw + 13, mac + 3, 3); -	memcpy(gid->raw + 8, mac, 3); -	gid->raw[8] ^= 2; +	return 0;  } -static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev) +/* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */ +static inline int rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)  { -	return dev->priv_flags & IFF_802_1Q_VLAN ? -		vlan_dev_vlan_id(dev) : 0xffff; +	if (ipv6_addr_v4mapped((struct in6_addr *)gid)) { +		struct sockaddr_in *out_in = (struct sockaddr_in *)out; +		memset(out_in, 0, sizeof(*out_in)); +		out_in->sin_family = AF_INET; +		memcpy(&out_in->sin_addr.s_addr, gid->raw + 12, 4); +	} else { +		struct sockaddr_in6 *out_in = (struct sockaddr_in6 *)out; +		memset(out_in, 0, sizeof(*out_in)); +		out_in->sin6_family = AF_INET6; +		memcpy(&out_in->sin6_addr.s6_addr, gid->raw, 16); +	} +	return 0;  }  static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,  				      union ib_gid *gid)  {  	struct net_device *dev; -	u16 vid = 0xffff; +	struct in_device *ip4;  	dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);  	if (dev) { -		vid = rdma_vlan_dev_vlan_id(dev); +		ip4 = (struct in_device *)dev->ip_ptr; +		if (ip4 && ip4->ifa_list && ip4->ifa_list->ifa_address) +			ipv6_addr_set_v4mapped(ip4->ifa_list->ifa_address, +					       (struct in6_addr *)gid);  		dev_put(dev);  	} - -	iboe_mac_vlan_to_ll(gid, dev_addr->src_dev_addr, vid);  }  static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid) @@ -217,18 +242,23 @@ static inline enum ib_mtu iboe_get_mtu(int mtu)  static inline int iboe_get_rate(struct net_device *dev)  {  	struct ethtool_cmd cmd; +	u32 speed; +	int err; -	if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings || -	    dev->ethtool_ops->get_settings(dev, &cmd)) +	rtnl_lock(); +	err = __ethtool_get_settings(dev, &cmd); +	rtnl_unlock(); +	if (err)  		return IB_RATE_PORT_CURRENT; -	if (cmd.speed >= 40000) +	speed = ethtool_cmd_speed(&cmd); +	if (speed >= 40000)  		return IB_RATE_40_GBPS; -	else if (cmd.speed >= 30000) +	else if (speed >= 30000)  		return IB_RATE_30_GBPS; -	else if (cmd.speed >= 20000) +	else if (speed >= 20000)  		return IB_RATE_20_GBPS; -	else if (cmd.speed >= 10000) +	else if (speed >= 10000)  		return IB_RATE_10_GBPS;  	else  		return IB_RATE_PORT_CURRENT; @@ -276,7 +306,7 @@ static inline u16 rdma_get_vlan_id(union ib_gid *dgid)  static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev)  {  	return dev->priv_flags & IFF_802_1Q_VLAN ? -		vlan_dev_real_dev(dev) : 0; +		vlan_dev_real_dev(dev) : NULL;  }  #endif /* IB_ADDR_H */  | 
