net/smc/smc_ib.c

Source file repositories/reference/linux-study-clean/net/smc/smc_ib.c

File Facts

System
Linux kernel
Corpus path
net/smc/smc_ib.c
Extension
.c
Size
28021 bytes
Lines
1026
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

smc_ib_gid_to_ipv4((u8 *)&attr->gid) != cpu_to_be32(INADDR_NONE)) {
		struct in_device *in_dev = __in_dev_get_rcu(ndev);
		struct net *net = dev_net(ndev);
		const struct in_ifaddr *ifa;
		bool subnet_match = false;

		if (!in_dev)
			goto out;
		in_dev_for_each_ifa_rcu(ifa, in_dev) {
			if (!inet_ifa_match(smcrv2->saddr, ifa))
				continue;
			subnet_match = true;
			break;
		}
		if (!subnet_match)
			goto out;
		if (smcrv2->daddr && smc_ib_find_route(net, smcrv2->saddr,
						       smcrv2->daddr,
						       smcrv2->nexthop_mac,
						       &smcrv2->uses_gateway))
			goto out;

		if (gid)
			memcpy(gid, &attr->gid, SMC_GID_SIZE);
		if (sgid_index)
			*sgid_index = attr->index;
		return 0;
	}
out:
	return -ENODEV;
}

/* determine the gid for an ib-device port and vlan id */
int smc_ib_determine_gid(struct smc_ib_device *smcibdev, u8 ibport,
			 unsigned short vlan_id, u8 gid[], u8 *sgid_index,
			 struct smc_init_info_smcrv2 *smcrv2)
{
	const struct ib_gid_attr *attr;
	const struct net_device *ndev;
	int i;

	for (i = 0; i < smcibdev->pattr[ibport - 1].gid_tbl_len; i++) {
		attr = rdma_get_gid_attr(smcibdev->ibdev, ibport, i);
		if (IS_ERR(attr))
			continue;

		rcu_read_lock();
		ndev = rdma_read_gid_attr_ndev_rcu(attr);
		if (!IS_ERR(ndev) &&
		    ((!vlan_id && !is_vlan_dev(ndev)) ||
		     (vlan_id && is_vlan_dev(ndev) &&
		      vlan_dev_vlan_id(ndev) == vlan_id))) {
			if (!smc_ib_determine_gid_rcu(ndev, attr, gid,
						      sgid_index, smcrv2)) {
				rcu_read_unlock();
				rdma_put_gid_attr(attr);
				return 0;
			}
		}
		rcu_read_unlock();
		rdma_put_gid_attr(attr);
	}
	return -ENODEV;
}

/* check if gid is still defined on smcibdev */
static bool smc_ib_check_link_gid(u8 gid[SMC_GID_SIZE], bool smcrv2,
				  struct smc_ib_device *smcibdev, u8 ibport)
{
	const struct ib_gid_attr *attr;
	bool rc = false;
	int i;

	for (i = 0; !rc && i < smcibdev->pattr[ibport - 1].gid_tbl_len; i++) {
		attr = rdma_get_gid_attr(smcibdev->ibdev, ibport, i);
		if (IS_ERR(attr))
			continue;

		rcu_read_lock();
		if ((!smcrv2 && attr->gid_type == IB_GID_TYPE_ROCE) ||
		    (smcrv2 && attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP &&
		     !(ipv6_addr_type((const struct in6_addr *)&attr->gid)
				     & IPV6_ADDR_LINKLOCAL)))
			if (!memcmp(gid, &attr->gid, SMC_GID_SIZE))
				rc = true;
		rcu_read_unlock();
		rdma_put_gid_attr(attr);
	}
	return rc;
}

Annotation

Implementation Notes