net/bridge/br_cfm.c

Source file repositories/reference/linux-study-clean/net/bridge/br_cfm.c

File Facts

System
Linux kernel
Corpus path
net/bridge/br_cfm.c
Extension
.c
Size
21062 bytes
Lines
874
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

if (peer_mep->cc_status.ccm_defect) {
			peer_mep->cc_status.ccm_defect = false;

			/* Change in CCM defect status - notify */
			br_cfm_notify(RTM_NEWLINK, port);

			/* Start CCM RX timer */
			ccm_rx_timer_start(peer_mep);
		}

		peer_mep->cc_status.seen = true;
		peer_mep->ccm_rx_count_miss = 0;

		/* RDI is in common header flags */
		peer_mep->cc_status.rdi = (hdr->flags & 0x80) ? true : false;

		/* Sequence number is after common header */
		snumber = skb_header_pointer(skb,
					     CFM_CCM_PDU_SEQNR_OFFSET,
					     sizeof(_snumber), &_snumber);
		if (!snumber)
			return 1;
		if (ntohl(*snumber) != (mep->ccm_rx_snumber + 1))
			/* Unexpected sequence number */
			peer_mep->cc_status.seq_unexp_seen = true;

		mep->ccm_rx_snumber = ntohl(*snumber);

		/* TLV end is after common header + sequence number + MEP ID +
		 * MA ID + ITU reserved
		 */
		index = CFM_CCM_PDU_TLV_OFFSET;
		max = 0;
		do { /* Handle all TLVs */
			size = ccm_tlv_extract(skb, index, peer_mep);
			index += size;
			max += 1;
		} while (size != 0 && max < 4); /* Max four TLVs possible */

		return 1;
	}

	mep->status.opcode_unexp_seen = true;

	return 1;
}

static struct br_frame_type cfm_frame_type __read_mostly = {
	.type = cpu_to_be16(ETH_P_CFM),
	.frame_handler = br_cfm_frame_rx,
};

int br_cfm_mep_create(struct net_bridge *br,
		      const u32 instance,
		      struct br_cfm_mep_create *const create,
		      struct netlink_ext_ack *extack)
{
	struct net_bridge_port *p;
	struct br_cfm_mep *mep;

	ASSERT_RTNL();

	if (create->domain == BR_CFM_VLAN) {
		NL_SET_ERR_MSG_MOD(extack,
				   "VLAN domain not supported");
		return -EINVAL;
	}
	if (create->domain != BR_CFM_PORT) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Invalid domain value");
		return -EINVAL;
	}
	if (create->direction == BR_CFM_MEP_DIRECTION_UP) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Up-MEP not supported");
		return -EINVAL;
	}
	if (create->direction != BR_CFM_MEP_DIRECTION_DOWN) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Invalid direction value");
		return -EINVAL;
	}
	p = br_mep_get_port(br, create->ifindex);
	if (!p) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Port is not related to bridge");
		return -EINVAL;
	}
	mep = br_mep_find(br, instance);
	if (mep) {

Annotation

Implementation Notes