From patchwork Thu Aug 26 14:19:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eli Cohen X-Patchwork-Id: 134951 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o7QEHLNh017876 for ; Thu, 26 Aug 2010 14:19:40 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753633Ab0HZOTk (ORCPT ); Thu, 26 Aug 2010 10:19:40 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:32941 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752290Ab0HZOTj (ORCPT ); Thu, 26 Aug 2010 10:19:39 -0400 Received: by mail-bw0-f46.google.com with SMTP id 11so1108123bwz.19 for ; Thu, 26 Aug 2010 07:19:39 -0700 (PDT) Received: by 10.204.82.155 with SMTP id b27mr6332592bkl.182.1282832379228; Thu, 26 Aug 2010 07:19:39 -0700 (PDT) Received: from localhost ([82.166.227.17]) by mx.google.com with ESMTPS id bq20sm1694494bkb.4.2010.08.26.07.19.38 (version=TLSv1/SSLv3 cipher=RC4-MD5); Thu, 26 Aug 2010 07:19:38 -0700 (PDT) Date: Thu, 26 Aug 2010 17:19:44 +0300 From: Eli Cohen To: Roland Dreier Cc: RDMA list Subject: [PATCHv10 3/4] libibverbs: Add API to resolve GID to L2 address Message-ID: <20100826141944.GP8795@mtldesk30> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 26 Aug 2010 14:19:41 +0000 (UTC) diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h index 9a81416..dffb26d 100644 --- a/include/infiniband/driver.h +++ b/include/infiniband/driver.h @@ -37,6 +37,8 @@ #include #include +#include +#include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { @@ -143,4 +145,9 @@ const char *ibv_get_sysfs_path(void); int ibv_read_sysfs_file(const char *dir, const char *file, char *buf, size_t size); +int ibv_resolve_eth_gid(const struct ibv_pd *pd, uint8_t port_num, + union ibv_gid *dgid, uint8_t sgid_index, + uint8_t mac[], uint16_t *vlan, uint8_t *tagged, + uint8_t *is_mcast); + #endif /* INFINIBAND_DRIVER_H */ diff --git a/src/verbs.c b/src/verbs.c index ba3c0a4..2cc67c2 100644 --- a/src/verbs.c +++ b/src/verbs.c @@ -148,6 +148,7 @@ struct ibv_pd *__ibv_alloc_pd(struct ibv_context *context) } default_symver(__ibv_alloc_pd, ibv_alloc_pd); + int __ibv_dealloc_pd(struct ibv_pd *pd) { return pd->context->ops.dealloc_pd(pd); @@ -543,3 +544,99 @@ int __ibv_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid return qp->context->ops.detach_mcast(qp, gid, lid); } default_symver(__ibv_detach_mcast, ibv_detach_mcast); + +static uint16_t get_vlan_id(const union ibv_gid *dgid) +{ + return dgid->raw[11] << 8 | dgid->raw[12]; +} + +static void get_ll_mac(const union ibv_gid *gid, uint8_t *mac) +{ + memcpy(mac, &gid->raw[8], 3); + memcpy(mac + 3, &gid->raw[13], 3); + mac[0] ^= 2; +} + +static int is_multicast_gid(const union ibv_gid *gid) +{ + return gid->raw[0] == 0xff; +} + +static void get_mcast_mac(const union ibv_gid *gid, uint8_t *mac) +{ + int i; + + mac[0] = 0x33; + mac[1] = 0x33; + for (i = 2; i < 6; ++i) + mac[i] = gid->raw[i + 10]; +} + +static int is_link_local_gid(const union ibv_gid *gid) +{ + uint32_t hi = *(uint32_t *)(gid->raw); + uint32_t lo = *(uint32_t *)(gid->raw + 4); + if (hi == htonl(0xfe800000) && lo == 0) + return 1; + + return 0; +} + +static int resolve_gid(const union ibv_gid *dgid, uint8_t *mac, uint8_t *is_mcast) +{ + if (is_link_local_gid(dgid)) { + get_ll_mac(dgid, mac); + *is_mcast = 0; + } else if (is_multicast_gid(dgid)) { + get_mcast_mac(dgid, mac); + *is_mcast = 1; + } else + return -EINVAL; + + return 0; +} + +static int is_tagged_vlan(const union ibv_gid *gid) +{ + uint16_t tag; + + tag = gid->raw[11] << 8 | gid->raw[12]; + + return tag < 0x1000; +} + +int __ibv_resolve_eth_gid(struct ibv_pd *pd, uint8_t port_num, + const union ibv_gid *dgid, uint8_t sgid_index, + uint8_t mac[], uint16_t *vlan, uint8_t *tagged, + uint8_t *is_mcast) +{ + int err; + union ibv_gid sgid; + int stagged, svlan; + + err = resolve_gid(dgid, mac, is_mcast); + if (err) + return err; + + err = ibv_query_gid(pd->context, port_num, sgid_index, &sgid); + if (err) + return err; + + stagged = is_tagged_vlan(&sgid); + if (stagged) { + if (!is_tagged_vlan(dgid) && !is_mcast) + return -1; + + svlan = get_vlan_id(&sgid); + if (svlan != get_vlan_id(dgid) && !is_mcast) + return -1; + + *tagged = 1; + *vlan = svlan; + } else + *tagged = 0; + + return 0; +} +default_symver(__ibv_resolve_eth_gid, ibv_resolve_eth_gid); +