drivers/net/ethernet/netronome/nfp/flower/action.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/netronome/nfp/flower/action.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/netronome/nfp/flower/action.c
Extension
.c
Size
40504 bytes
Lines
1323
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 ipv4_ttl_word {
	__u8	ttl;
	__u8	protocol;
	__sum16	check;
};

static int
nfp_fl_set_ip4(const struct flow_action_entry *act, u32 off,
	       struct nfp_fl_set_ip4_addrs *set_ip_addr,
	       struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos,
	       struct netlink_ext_ack *extack)
{
	struct ipv4_ttl_word *ttl_word_mask;
	struct ipv4_ttl_word *ttl_word;
	struct iphdr *tos_word_mask;
	struct iphdr *tos_word;
	__be32 exact, mask;

	/* We are expecting tcf_pedit to return a big endian value */
	mask = (__force __be32)~act->mangle.mask;
	exact = (__force __be32)act->mangle.val;

	if (exact & ~mask) {
		NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv4 action");
		return -EOPNOTSUPP;
	}

	switch (off) {
	case offsetof(struct iphdr, daddr):
		set_ip_addr->ipv4_dst_mask |= mask;
		set_ip_addr->ipv4_dst &= ~mask;
		set_ip_addr->ipv4_dst |= exact & mask;
		set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
		set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
					   NFP_FL_LW_SIZ;
		break;
	case offsetof(struct iphdr, saddr):
		set_ip_addr->ipv4_src_mask |= mask;
		set_ip_addr->ipv4_src &= ~mask;
		set_ip_addr->ipv4_src |= exact & mask;
		set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
		set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >>
					   NFP_FL_LW_SIZ;
		break;
	case offsetof(struct iphdr, ttl):
		ttl_word_mask = (struct ipv4_ttl_word *)&mask;
		ttl_word = (struct ipv4_ttl_word *)&exact;

		if (ttl_word_mask->protocol || ttl_word_mask->check) {
			NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv4 ttl action");
			return -EOPNOTSUPP;
		}

		set_ip_ttl_tos->ipv4_ttl_mask |= ttl_word_mask->ttl;
		set_ip_ttl_tos->ipv4_ttl &= ~ttl_word_mask->ttl;
		set_ip_ttl_tos->ipv4_ttl |= ttl_word->ttl & ttl_word_mask->ttl;
		set_ip_ttl_tos->head.jump_id =
			NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
		set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
					      NFP_FL_LW_SIZ;
		break;
	case round_down(offsetof(struct iphdr, tos), 4):
		tos_word_mask = (struct iphdr *)&mask;
		tos_word = (struct iphdr *)&exact;

		if (tos_word_mask->version || tos_word_mask->ihl ||
		    tos_word_mask->tot_len) {
			NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid pedit IPv4 tos action");
			return -EOPNOTSUPP;
		}

		set_ip_ttl_tos->ipv4_tos_mask |= tos_word_mask->tos;
		set_ip_ttl_tos->ipv4_tos &= ~tos_word_mask->tos;
		set_ip_ttl_tos->ipv4_tos |= tos_word->tos & tos_word_mask->tos;
		set_ip_ttl_tos->head.jump_id =
			NFP_FL_ACTION_OPCODE_SET_IPV4_TTL_TOS;
		set_ip_ttl_tos->head.len_lw = sizeof(*set_ip_ttl_tos) >>
					      NFP_FL_LW_SIZ;
		break;
	default:
		NL_SET_ERR_MSG_MOD(extack, "unsupported offload: pedit on unsupported section of IPv4 header");
		return -EOPNOTSUPP;
	}

	return 0;
}

static void
nfp_fl_set_ip6_helper(int opcode_tag, u8 word, __be32 exact, __be32 mask,
		      struct nfp_fl_set_ipv6_addr *ip6)

Annotation

Implementation Notes