drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c
Extension
.c
Size
5185 bytes
Lines
197
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mlx5_vxlan {
	struct mlx5_core_dev		*mdev;
	/* max_num_ports is usually 4, 16 buckets is more than enough */
	DECLARE_HASHTABLE(htable, 4);
	struct mutex                    sync_lock; /* sync add/del port HW operations */
};

struct mlx5_vxlan_port {
	struct hlist_node hlist;
	u16 udp_port;
};

static int mlx5_vxlan_core_add_port_cmd(struct mlx5_core_dev *mdev, u16 port)
{
	u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {};

	MLX5_SET(add_vxlan_udp_dport_in, in, opcode,
		 MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT);
	MLX5_SET(add_vxlan_udp_dport_in, in, vxlan_udp_port, port);
	return mlx5_cmd_exec_in(mdev, add_vxlan_udp_dport, in);
}

static int mlx5_vxlan_core_del_port_cmd(struct mlx5_core_dev *mdev, u16 port)
{
	u32 in[MLX5_ST_SZ_DW(delete_vxlan_udp_dport_in)] = {};

	MLX5_SET(delete_vxlan_udp_dport_in, in, opcode,
		 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
	MLX5_SET(delete_vxlan_udp_dport_in, in, vxlan_udp_port, port);
	return mlx5_cmd_exec_in(mdev, delete_vxlan_udp_dport, in);
}

bool mlx5_vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port)
{
	struct mlx5_vxlan_port *vxlanp;
	bool found = false;

	if (!mlx5_vxlan_allowed(vxlan))
		return NULL;

	rcu_read_lock();
	hash_for_each_possible_rcu(vxlan->htable, vxlanp, hlist, port)
		if (vxlanp->udp_port == port) {
			found = true;
			break;
		}
	rcu_read_unlock();

	return found;
}

static struct mlx5_vxlan_port *vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port)
{
	struct mlx5_vxlan_port *vxlanp;

	hash_for_each_possible(vxlan->htable, vxlanp, hlist, port)
		if (vxlanp->udp_port == port)
			return vxlanp;
	return NULL;
}

int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port)
{
	struct mlx5_vxlan_port *vxlanp;
	int ret;

	vxlanp = kzalloc_obj(*vxlanp);
	if (!vxlanp)
		return -ENOMEM;
	vxlanp->udp_port = port;

	ret = mlx5_vxlan_core_add_port_cmd(vxlan->mdev, port);
	if (ret) {
		kfree(vxlanp);
		return ret;
	}

	mutex_lock(&vxlan->sync_lock);
	hash_add_rcu(vxlan->htable, &vxlanp->hlist, port);
	mutex_unlock(&vxlan->sync_lock);

	return 0;
}

int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port)
{
	struct mlx5_vxlan_port *vxlanp;
	int ret = 0;

	mutex_lock(&vxlan->sync_lock);

Annotation

Implementation Notes