aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_private_cfm.h
blob: a43a5e7fa2c3969a6f77484aced1c888df37c448 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef _BR_PRIVATE_CFM_H_
#define _BR_PRIVATE_CFM_H_

#include "br_private.h"
#include <uapi/linux/cfm_bridge.h>

struct br_cfm_mep_create {
	enum br_cfm_domain domain; /* Domain for this MEP */
	enum br_cfm_mep_direction direction; /* Up or Down MEP direction */
	u32 ifindex; /* Residence port */
};

int br_cfm_mep_create(struct net_bridge *br,
		      const u32 instance,
		      struct br_cfm_mep_create *const create,
		      struct netlink_ext_ack *extack);

int br_cfm_mep_delete(struct net_bridge *br,
		      const u32 instance,
		      struct netlink_ext_ack *extack);

struct br_cfm_mep_config {
	u32 mdlevel;
	u32 mepid; /* MEPID for this MEP */
	struct mac_addr unicast_mac; /* The MEP unicast MAC */
};

int br_cfm_mep_config_set(struct net_bridge *br,
			  const u32 instance,
			  const struct br_cfm_mep_config *const config,
			  struct netlink_ext_ack *extack);

struct br_cfm_maid {
	u8 data[CFM_MAID_LENGTH];
};

struct br_cfm_cc_config {
	/* Expected received CCM PDU MAID. */
	struct br_cfm_maid exp_maid;

	/* Expected received CCM PDU interval. */
	/* Transmitting CCM PDU interval when CCM tx is enabled. */
	enum br_cfm_ccm_interval exp_interval;

	bool enable; /* Enable/disable CCM PDU handling */
};

int br_cfm_cc_config_set(struct net_bridge *br,
			 const u32 instance,
			 const struct br_cfm_cc_config *const config,
			 struct netlink_ext_ack *extack);

int br_cfm_cc_peer_mep_add(struct net_bridge *br, const u32 instance,
			   u32 peer_mep_id,
			   struct netlink_ext_ack *extack);
int br_cfm_cc_peer_mep_remove(struct net_bridge *br, const u32 instance,
			      u32 peer_mep_id,
			      struct netlink_ext_ack *extack);

/* Transmitted CCM Remote Defect Indication status set.
 * This RDI is inserted in transmitted CCM PDUs if CCM transmission is enabled.
 * See br_cfm_cc_ccm_tx() with interval != BR_CFM_CCM_INTERVAL_NONE
 */
int br_cfm_cc_rdi_set(struct net_bridge *br, const u32 instance,
		      const bool rdi, struct netlink_ext_ack *extack);

/* OAM PDU Tx information */
struct br_cfm_cc_ccm_tx_info {
	struct mac_addr dmac;
	/* The CCM will be transmitted for this period in seconds.
	 * Call br_cfm_cc_ccm_tx before timeout to keep transmission alive.
	 * When period is zero any ongoing transmission will be stopped.
	 */
	u32 period;

	bool seq_no_update; /* Update Tx CCM sequence number */
	bool if_tlv; /* Insert Interface Status TLV */
	u8 if_tlv_value; /* Interface Status TLV value */
	bool port_tlv; /* Insert Port Status TLV */
	u8 port_tlv_value; /* Port Status TLV value */
	/* Sender ID TLV ??
	 * Organization-Specific TLV ??
	 */
};

int br_cfm_cc_ccm_tx(struct net_bridge *br, const u32 instance,
		     const struct br_cfm_cc_ccm_tx_info *const tx_info,
		     struct netlink_ext_ack *extack);

struct br_cfm_mep_status {
	/* Indications that an OAM PDU has been seen. */
	bool opcode_unexp_seen; /* RX of OAM PDU with unexpected opcode */
	bool version_unexp_seen; /* RX of OAM PDU with unexpected version */
	bool rx_level_low_seen; /* Rx of OAM PDU with level low */
};

struct br_cfm_cc_peer_status {
	/* This CCM related status is based on the latest received CCM PDU. */
	u8 port_tlv_value; /* Port Status TLV value */
	u8 if_tlv_value; /* Interface Status TLV value */

	/* CCM has not been received for 3.25 intervals */
	u8 ccm_defect:1;

	/* (RDI == 1) for last received CCM PDU */
	u8 rdi:1;

	/* Indications that a CCM PDU has been seen. */
	u8 seen:1; /* CCM PDU received */
	u8 tlv_seen:1; /* CCM PDU with TLV received */
	/* CCM PDU with unexpected sequence number received */
	u8 seq_unexp_seen:1;
};

struct br_cfm_mep {
	/* list header of MEP instances */
	struct hlist_node		head;
	u32				instance;
	struct br_cfm_mep_create	create;
	struct br_cfm_mep_config	config;
	struct br_cfm_cc_config		cc_config;
	struct br_cfm_cc_ccm_tx_info	cc_ccm_tx_info;
	/* List of multiple peer MEPs */
	struct hlist_head		peer_mep_list;
	struct net_bridge_port __rcu	*b_port;
	unsigned long			ccm_tx_end;
	struct delayed_work		ccm_tx_dwork;
	u32				ccm_tx_snumber;
	u32				ccm_rx_snumber;
	struct br_cfm_mep_status	status;
	bool				rdi;
	struct rcu_head			rcu;
};

struct br_cfm_peer_mep {
	struct hlist_node		head;
	struct br_cfm_mep		*mep;
	struct delayed_work		ccm_rx_dwork;
	u32				mepid;
	struct br_cfm_cc_peer_status	cc_status;
	u32				ccm_rx_count_miss;
	struct rcu_head			rcu;
};

#endif /* _BR_PRIVATE_CFM_H_ */