drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
Extension
.c
Size
51030 bytes
Lines
1892
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 mlx5e_route_key {
	int ip_version;
	union {
		__be32 v4;
		struct in6_addr v6;
	} endpoint_ip;
};

struct mlx5e_route_entry {
	struct mlx5e_route_key key;
	struct list_head encap_entries;
	struct list_head decap_flows;
	u32 flags;
	struct hlist_node hlist;
	refcount_t refcnt;
	int tunnel_dev_index;
	struct rcu_head rcu;
};

struct mlx5e_tc_tun_encap {
	struct mlx5e_priv *priv;
	struct notifier_block fib_nb;
	spinlock_t route_lock; /* protects route_tbl */
	unsigned long route_tbl_last_update;
	DECLARE_HASHTABLE(route_tbl, 8);
};

static bool mlx5e_route_entry_valid(struct mlx5e_route_entry *r)
{
	return r->flags & MLX5E_ROUTE_ENTRY_VALID;
}

int mlx5e_tc_set_attr_rx_tun(struct mlx5e_tc_flow *flow,
			     struct mlx5_flow_spec *spec)
{
	struct mlx5_esw_flow_attr *esw_attr = flow->attr->esw_attr;
	struct mlx5_rx_tun_attr *tun_attr;
	void *daddr, *saddr;
	u8 ip_version;

	tun_attr = kvzalloc_obj(*tun_attr);
	if (!tun_attr)
		return -ENOMEM;

	esw_attr->rx_tun_attr = tun_attr;
	ip_version = mlx5e_tc_get_ip_version(spec, true);

	if (ip_version == 4) {
		daddr = MLX5_ADDR_OF(fte_match_param, spec->match_value,
				     outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
		saddr = MLX5_ADDR_OF(fte_match_param, spec->match_value,
				     outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4);
		tun_attr->dst_ip.v4 = *(__be32 *)daddr;
		tun_attr->src_ip.v4 = *(__be32 *)saddr;
		if (!tun_attr->dst_ip.v4 || !tun_attr->src_ip.v4)
			return 0;
	}
#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
	else if (ip_version == 6) {
		int ipv6_size = MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6);

		daddr = MLX5_ADDR_OF(fte_match_param, spec->match_value,
				     outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6);
		saddr = MLX5_ADDR_OF(fte_match_param, spec->match_value,
				     outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6);
		memcpy(&tun_attr->dst_ip.v6, daddr, ipv6_size);
		memcpy(&tun_attr->src_ip.v6, saddr, ipv6_size);
		if (ipv6_addr_any(&tun_attr->dst_ip.v6) ||
		    ipv6_addr_any(&tun_attr->src_ip.v6))
			return 0;
	}
#endif
	/* Only set the flag if both src and dst ip addresses exist. They are
	 * required to establish routing.
	 */
	flow_flag_set(flow, TUN_RX);
	flow->attr->tun_ip_version = ip_version;
	return 0;
}

static bool mlx5e_tc_flow_all_encaps_valid(struct mlx5_esw_flow_attr *esw_attr)
{
	bool all_flow_encaps_valid = true;
	int i;

	/* Flow can be associated with multiple encap entries.
	 * Before offloading the flow verify that all of them have
	 * a valid neighbour.
	 */
	for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) {

Annotation

Implementation Notes