net/dsa/tag_netc.c

Source file repositories/reference/linux-study-clean/net/dsa/tag_netc.c

File Facts

System
Linux kernel
Corpus path
net/dsa/tag_netc.c
Extension
.c
Size
6119 bytes
Lines
215
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct netc_tag_cmn {
	__be16 tpid;
	u8 type;
	u8 qos;
	u8 switch_port;
} __packed;

static void netc_fill_common_tag(struct netc_tag_cmn *tag, u8 type,
				 u8 subtype, u8 sw_id, u8 port, u8 ipv)
{
	tag->tpid = htons(ETH_P_NXP_NETC);
	tag->type = FIELD_PREP(NETC_TAG_TYPE, type) |
		    FIELD_PREP(NETC_TAG_SUBTYPE, subtype);
	tag->qos = NETC_TAG_QV | FIELD_PREP(NETC_TAG_IPV, ipv);
	tag->switch_port = FIELD_PREP(NETC_TAG_SWITCH, sw_id) |
			   FIELD_PREP(NETC_TAG_PORT, port);
}

static void *netc_fill_common_tp_tag(struct sk_buff *skb,
				     struct net_device *ndev,
				     u8 subtype, int tag_len)
{
	struct dsa_port *dp = dsa_user_to_port(ndev);
	u16 queue = skb_get_queue_mapping(skb);
	s8 ipv = netdev_txq_to_tc(ndev, queue);
	void *tag;

	if (unlikely(ipv < 0))
		ipv = 0;

	skb_push(skb, tag_len);
	dsa_alloc_etype_header(skb, tag_len);

	tag = dsa_etype_header_pos_tx(skb);
	memset(tag + NETC_TAG_CMN_LEN, 0, tag_len - NETC_TAG_CMN_LEN);
	/* As 'dsa,member' is a required property for NETC switch, the member
	 * is used to specify the switch ID (thus the hardware switch ID and
	 * the software switch ID are consistent), its range is 1 ~ 7. The
	 * NETC switch driver will check this value, and if it is invalid,
	 * the switch driver will fail the probe.
	 * In addition, according to the nxp,netc-switch.yaml doc, the port
	 * index will not be greater than 0xf.
	 */
	netc_fill_common_tag(tag, NETC_TAG_TO_PORT, subtype,
			     dp->ds->index, dp->index, ipv);

	return tag;
}

static void netc_fill_tp_tag_subtype0(struct sk_buff *skb,
				      struct net_device *ndev)
{
	netc_fill_common_tp_tag(skb, ndev, NETC_TAG_TP_SUBTYPE0,
				NETC_TAG_TP_SUBTYPE0_LEN);
}

/* Currently only support To_Port tag, subtype 0 */
static struct sk_buff *netc_xmit(struct sk_buff *skb,
				 struct net_device *ndev)
{
	netc_fill_tp_tag_subtype0(skb, ndev);

	return skb;
}

static int netc_get_rx_tag_len(int type, int subtype)
{
	/* Only NETC_TAG_TO_HOST and NETC_TAG_FORWARD are expected in RX,
	 * NETC_TAG_TO_PORT is a TX switch tag that does not exist in RX.
	 */
	if (type == NETC_TAG_TO_HOST) {
		if (subtype == NETC_TAG_TH_SUBTYPE1)
			return NETC_TAG_TH_SUBTYPE1_LEN;
		else if (subtype == NETC_TAG_TH_SUBTYPE2)
			return NETC_TAG_TH_SUBTYPE2_LEN;
		else
			return NETC_TAG_TH_SUBTYPE0_LEN;
	}

	return NETC_TAG_FORWARD_LEN;
}

static struct sk_buff *netc_rcv(struct sk_buff *skb,
				struct net_device *ndev)
{
	struct netc_tag_cmn *tag_cmn;
	int tag_len, sw_id, port;
	int type, subtype;

	if (unlikely(!pskb_may_pull(skb, NETC_TAG_MAX_LEN)))

Annotation

Implementation Notes