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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c
Extension
.c
Size
12150 bytes
Lines
356
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

// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2018 Mellanox Technologies. */

#include <net/geneve.h>
#include "lib/geneve.h"
#include "en/tc_tun.h"

#define MLX5E_GENEVE_VER 0

static bool mlx5e_tc_tun_can_offload_geneve(struct mlx5e_priv *priv)
{
	return !!(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) & MLX5_FLEX_PROTO_GENEVE);
}

static int mlx5e_tc_tun_calc_hlen_geneve(struct mlx5e_encap_entry *e)
{
	return sizeof(struct udphdr) +
	       sizeof(struct genevehdr) +
	       e->tun_info->options_len;
}

static int mlx5e_tc_tun_check_udp_dport_geneve(struct mlx5e_priv *priv,
					       struct flow_cls_offload *f)
{
	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
	struct netlink_ext_ack *extack = f->common.extack;
	struct flow_match_ports enc_ports;

	if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS))
		return -EOPNOTSUPP;

	flow_rule_match_enc_ports(rule, &enc_ports);

	/* Currently we support only default GENEVE
	 * port, so udp dst port must match.
	 */
	if (be16_to_cpu(enc_ports.key->dst) != GENEVE_UDP_PORT) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Matched UDP dst port is not registered as a GENEVE port");
		netdev_warn(priv->netdev,
			    "UDP port %d is not registered as a GENEVE port\n",
			    be16_to_cpu(enc_ports.key->dst));
		return -EOPNOTSUPP;
	}

	return 0;
}

static int mlx5e_tc_tun_parse_udp_ports_geneve(struct mlx5e_priv *priv,
					       struct mlx5_flow_spec *spec,
					       struct flow_cls_offload *f,
					       void *headers_c,
					       void *headers_v)
{
	int err;

	err = mlx5e_tc_tun_parse_udp_ports(priv, spec, f, headers_c, headers_v);
	if (err)
		return err;

	return mlx5e_tc_tun_check_udp_dport_geneve(priv, f);
}

static int mlx5e_tc_tun_init_encap_attr_geneve(struct net_device *tunnel_dev,
					       struct mlx5e_priv *priv,
					       struct mlx5e_encap_entry *e,
					       struct netlink_ext_ack *extack)
{
	e->tunnel = &geneve_tunnel;

	/* Reformat type for GENEVE encap is similar to VXLAN:
	 * in both cases the HW adds in the same place a
	 * defined encapsulation header that the SW provides.
	 */
	e->reformat_type = MLX5_REFORMAT_TYPE_L2_TO_VXLAN;
	return 0;
}

static void mlx5e_tunnel_id_to_vni(__be64 tun_id, __u8 *vni)
{
#ifdef __BIG_ENDIAN
	vni[0] = (__force __u8)(tun_id >> 16);
	vni[1] = (__force __u8)(tun_id >> 8);
	vni[2] = (__force __u8)tun_id;
#else
	vni[0] = (__force __u8)((__force u64)tun_id >> 40);
	vni[1] = (__force __u8)((__force u64)tun_id >> 48);
	vni[2] = (__force __u8)((__force u64)tun_id >> 56);
#endif
}

Annotation

Implementation Notes