drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
Extension
.c
Size
60177 bytes
Lines
2103
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

if (offset > PEDIT_OFFSET_SMAC_LAST_4_BYTES) {
			netdev_err(bp->dev,
				   "%s: eth_hdr: Invalid pedit field\n",
				   __func__);
			return -EINVAL;
		}
		actions->flags |= BNXT_TC_ACTION_FLAG_L2_REWRITE;

		bnxt_set_l2_key_mask(val, mask, &eth_addr[offset],
				     &eth_addr_mask[offset]);
		break;
	case FLOW_ACT_MANGLE_HDR_TYPE_IP4:
		actions->flags |= BNXT_TC_ACTION_FLAG_NAT_XLATE;
		actions->nat.l3_is_ipv4 = true;
		if (offset ==  offsetof(struct iphdr, saddr)) {
			actions->nat.src_xlate = true;
			actions->nat.l3.ipv4.saddr.s_addr = htonl(val);
		} else if (offset ==  offsetof(struct iphdr, daddr)) {
			actions->nat.src_xlate = false;
			actions->nat.l3.ipv4.daddr.s_addr = htonl(val);
		} else {
			netdev_err(bp->dev,
				   "%s: IPv4_hdr: Invalid pedit field\n",
				   __func__);
			return -EINVAL;
		}

		netdev_dbg(bp->dev, "nat.src_xlate = %d src IP: %pI4 dst ip : %pI4\n",
			   actions->nat.src_xlate, &actions->nat.l3.ipv4.saddr,
			   &actions->nat.l3.ipv4.daddr);
		break;

	case FLOW_ACT_MANGLE_HDR_TYPE_IP6:
		actions->flags |= BNXT_TC_ACTION_FLAG_NAT_XLATE;
		actions->nat.l3_is_ipv4 = false;
		if (offset >= offsetof(struct ipv6hdr, saddr) &&
		    offset < offset_of_ip6_daddr) {
			/* 16 byte IPv6 address comes in 4 iterations of
			 * 4byte chunks each
			 */
			actions->nat.src_xlate = true;
			idx = (offset - offset_of_ip6_saddr) / 4;
			/* First 4bytes will be copied to idx 0 and so on */
			actions->nat.l3.ipv6.saddr.s6_addr32[idx] = htonl(val);
		} else if (offset >= offset_of_ip6_daddr &&
			   offset < offset_of_ip6_daddr + 16) {
			actions->nat.src_xlate = false;
			idx = (offset - offset_of_ip6_daddr) / 4;
			actions->nat.l3.ipv6.daddr.s6_addr32[idx] = htonl(val);
		} else {
			netdev_err(bp->dev,
				   "%s: IPv6_hdr: Invalid pedit field\n",
				   __func__);
			return -EINVAL;
		}
		break;
	case FLOW_ACT_MANGLE_HDR_TYPE_TCP:
	case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
		/* HW does not support L4 rewrite alone without L3
		 * rewrite
		 */
		if (!(actions->flags & BNXT_TC_ACTION_FLAG_NAT_XLATE)) {
			netdev_err(bp->dev,
				   "Need to specify L3 rewrite as well\n");
			return -EINVAL;
		}
		if (actions->nat.src_xlate)
			actions->nat.l4.ports.sport = htons(val);
		else
			actions->nat.l4.ports.dport = htons(val);
		netdev_dbg(bp->dev, "actions->nat.sport = %d dport = %d\n",
			   actions->nat.l4.ports.sport,
			   actions->nat.l4.ports.dport);
		break;
	default:
		netdev_err(bp->dev, "%s: Unsupported pedit hdr type\n",
			   __func__);
		return -EINVAL;
	}
	return 0;
}

static int bnxt_tc_parse_actions(struct bnxt *bp,
				 struct bnxt_tc_actions *actions,
				 struct flow_action *flow_action,
				 struct netlink_ext_ack *extack)
{
	/* Used to store the L2 rewrite mask for dmac (6 bytes) followed by
	 * smac (6 bytes) if rewrite of both is specified, otherwise either
	 * dmac or smac

Annotation

Implementation Notes