1 // SPDX-License-Identifier: GPL-2.0-or-later 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 #include <net/genetlink.h> 3 #include <net/genetlink.h> 4 4 5 #include "br_private.h" 5 #include "br_private.h" 6 #include "br_private_cfm.h" 6 #include "br_private_cfm.h" 7 7 8 static const struct nla_policy 8 static const struct nla_policy 9 br_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_C 9 br_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1] = { 10 [IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC] 10 [IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC] = { .type = NLA_REJECT }, 11 [IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE] 11 [IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE] = { .type = NLA_U32 }, 12 [IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN] 12 [IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN] = { .type = NLA_U32 }, 13 [IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION] 13 [IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION] = { .type = NLA_U32 }, 14 [IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX] 14 [IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX] = { .type = NLA_U32 }, 15 }; 15 }; 16 16 17 static const struct nla_policy 17 static const struct nla_policy 18 br_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_D 18 br_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1] = { 19 [IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC] 19 [IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC] = { .type = NLA_REJECT }, 20 [IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE] 20 [IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE] = { .type = NLA_U32 }, 21 }; 21 }; 22 22 23 static const struct nla_policy 23 static const struct nla_policy 24 br_cfm_mep_config_policy[IFLA_BRIDGE_CFM_MEP_C 24 br_cfm_mep_config_policy[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1] = { 25 [IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC] 25 [IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC] = { .type = NLA_REJECT }, 26 [IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE] 26 [IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE] = { .type = NLA_U32 }, 27 [IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MA 27 [IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = NLA_POLICY_ETH_ADDR, 28 [IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL] 28 [IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL] = NLA_POLICY_MAX(NLA_U32, 7), 29 [IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID] 29 [IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF), 30 }; 30 }; 31 31 32 static const struct nla_policy 32 static const struct nla_policy 33 br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CON 33 br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = { 34 [IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] 34 [IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] = { .type = NLA_REJECT }, 35 [IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] 35 [IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] = { .type = NLA_U32 }, 36 [IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] 36 [IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] = { .type = NLA_U32 }, 37 [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVA 37 [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 }, 38 [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID] 38 [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID] = { 39 .type = NLA_BINARY, .len = CFM_MAID_LE 39 .type = NLA_BINARY, .len = CFM_MAID_LENGTH }, 40 }; 40 }; 41 41 42 static const struct nla_policy 42 static const struct nla_policy 43 br_cfm_cc_peer_mep_policy[IFLA_BRIDGE_CFM_CC_P 43 br_cfm_cc_peer_mep_policy[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1] = { 44 [IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC] 44 [IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC] = { .type = NLA_REJECT }, 45 [IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE] 45 [IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE] = { .type = NLA_U32 }, 46 [IFLA_BRIDGE_CFM_CC_PEER_MEPID] 46 [IFLA_BRIDGE_CFM_CC_PEER_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF), 47 }; 47 }; 48 48 49 static const struct nla_policy 49 static const struct nla_policy 50 br_cfm_cc_rdi_policy[IFLA_BRIDGE_CFM_CC_RDI_MA 50 br_cfm_cc_rdi_policy[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1] = { 51 [IFLA_BRIDGE_CFM_CC_RDI_UNSPEC] 51 [IFLA_BRIDGE_CFM_CC_RDI_UNSPEC] = { .type = NLA_REJECT }, 52 [IFLA_BRIDGE_CFM_CC_RDI_INSTANCE] 52 [IFLA_BRIDGE_CFM_CC_RDI_INSTANCE] = { .type = NLA_U32 }, 53 [IFLA_BRIDGE_CFM_CC_RDI_RDI] 53 [IFLA_BRIDGE_CFM_CC_RDI_RDI] = { .type = NLA_U32 }, 54 }; 54 }; 55 55 56 static const struct nla_policy 56 static const struct nla_policy 57 br_cfm_cc_ccm_tx_policy[IFLA_BRIDGE_CFM_CC_CCM 57 br_cfm_cc_ccm_tx_policy[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1] = { 58 [IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC] 58 [IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC] = { .type = NLA_REJECT }, 59 [IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE] 59 [IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE] = { .type = NLA_U32 }, 60 [IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC] 60 [IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC] = NLA_POLICY_ETH_ADDR, 61 [IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDA 61 [IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE] = { .type = NLA_U32 }, 62 [IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD] 62 [IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD] = { .type = NLA_U32 }, 63 [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV] 63 [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV] = { .type = NLA_U32 }, 64 [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALU 64 [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE] = { .type = NLA_U8 }, 65 [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV] 65 [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV] = { .type = NLA_U32 }, 66 [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VA 66 [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = { .type = NLA_U8 }, 67 }; 67 }; 68 68 69 static const struct nla_policy 69 static const struct nla_policy 70 br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = { 70 br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = { 71 [IFLA_BRIDGE_CFM_UNSPEC] 71 [IFLA_BRIDGE_CFM_UNSPEC] = { .type = NLA_REJECT }, 72 [IFLA_BRIDGE_CFM_MEP_CREATE] 72 [IFLA_BRIDGE_CFM_MEP_CREATE] = 73 NLA_POLICY_NES 73 NLA_POLICY_NESTED(br_cfm_mep_create_policy), 74 [IFLA_BRIDGE_CFM_MEP_DELETE] 74 [IFLA_BRIDGE_CFM_MEP_DELETE] = 75 NLA_POLICY_NES 75 NLA_POLICY_NESTED(br_cfm_mep_delete_policy), 76 [IFLA_BRIDGE_CFM_MEP_CONFIG] 76 [IFLA_BRIDGE_CFM_MEP_CONFIG] = 77 NLA_POLICY_NES 77 NLA_POLICY_NESTED(br_cfm_mep_config_policy), 78 [IFLA_BRIDGE_CFM_CC_CONFIG] 78 [IFLA_BRIDGE_CFM_CC_CONFIG] = 79 NLA_POLICY_NES 79 NLA_POLICY_NESTED(br_cfm_cc_config_policy), 80 [IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD] 80 [IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD] = 81 NLA_POLICY_NES 81 NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy), 82 [IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE] 82 [IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE] = 83 NLA_POLICY_NES 83 NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy), 84 [IFLA_BRIDGE_CFM_CC_RDI] 84 [IFLA_BRIDGE_CFM_CC_RDI] = 85 NLA_POLICY_NES 85 NLA_POLICY_NESTED(br_cfm_cc_rdi_policy), 86 [IFLA_BRIDGE_CFM_CC_CCM_TX] 86 [IFLA_BRIDGE_CFM_CC_CCM_TX] = 87 NLA_POLICY_NES 87 NLA_POLICY_NESTED(br_cfm_cc_ccm_tx_policy), 88 }; 88 }; 89 89 90 static int br_mep_create_parse(struct net_brid 90 static int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr, 91 struct netlink_ 91 struct netlink_ext_ack *extack) 92 { 92 { 93 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_ 93 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1]; 94 struct br_cfm_mep_create create; 94 struct br_cfm_mep_create create; 95 u32 instance; 95 u32 instance; 96 int err; 96 int err; 97 97 98 err = nla_parse_nested(tb, IFLA_BRIDGE 98 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CREATE_MAX, attr, 99 br_cfm_mep_crea 99 br_cfm_mep_create_policy, extack); 100 if (err) 100 if (err) 101 return err; 101 return err; 102 102 103 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INS 103 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]) { 104 NL_SET_ERR_MSG_MOD(extack, "Mi 104 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute"); 105 return -EINVAL; 105 return -EINVAL; 106 } 106 } 107 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOM 107 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]) { 108 NL_SET_ERR_MSG_MOD(extack, "Mi 108 NL_SET_ERR_MSG_MOD(extack, "Missing DOMAIN attribute"); 109 return -EINVAL; 109 return -EINVAL; 110 } 110 } 111 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIR 111 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]) { 112 NL_SET_ERR_MSG_MOD(extack, "Mi 112 NL_SET_ERR_MSG_MOD(extack, "Missing DIRECTION attribute"); 113 return -EINVAL; 113 return -EINVAL; 114 } 114 } 115 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFI 115 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]) { 116 NL_SET_ERR_MSG_MOD(extack, "Mi 116 NL_SET_ERR_MSG_MOD(extack, "Missing IFINDEX attribute"); 117 return -EINVAL; 117 return -EINVAL; 118 } 118 } 119 119 120 memset(&create, 0, sizeof(create)); 120 memset(&create, 0, sizeof(create)); 121 121 122 instance = nla_get_u32(tb[IFLA_BRIDGE 122 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]); 123 create.domain = nla_get_u32(tb[IFLA_BR 123 create.domain = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]); 124 create.direction = nla_get_u32(tb[IFLA 124 create.direction = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]); 125 create.ifindex = nla_get_u32(tb[IFLA_B 125 create.ifindex = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]); 126 126 127 return br_cfm_mep_create(br, instance, 127 return br_cfm_mep_create(br, instance, &create, extack); 128 } 128 } 129 129 130 static int br_mep_delete_parse(struct net_brid 130 static int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr, 131 struct netlink_ 131 struct netlink_ext_ack *extack) 132 { 132 { 133 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_ 133 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1]; 134 u32 instance; 134 u32 instance; 135 int err; 135 int err; 136 136 137 err = nla_parse_nested(tb, IFLA_BRIDGE 137 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_DELETE_MAX, attr, 138 br_cfm_mep_dele 138 br_cfm_mep_delete_policy, extack); 139 if (err) 139 if (err) 140 return err; 140 return err; 141 141 142 if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INS 142 if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]) { 143 NL_SET_ERR_MSG_MOD(extack, 143 NL_SET_ERR_MSG_MOD(extack, 144 "Missing IN 144 "Missing INSTANCE attribute"); 145 return -EINVAL; 145 return -EINVAL; 146 } 146 } 147 147 148 instance = nla_get_u32(tb[IFLA_BRIDGE 148 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]); 149 149 150 return br_cfm_mep_delete(br, instance, 150 return br_cfm_mep_delete(br, instance, extack); 151 } 151 } 152 152 153 static int br_mep_config_parse(struct net_brid 153 static int br_mep_config_parse(struct net_bridge *br, struct nlattr *attr, 154 struct netlink_ 154 struct netlink_ext_ack *extack) 155 { 155 { 156 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_ 156 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1]; 157 struct br_cfm_mep_config config; 157 struct br_cfm_mep_config config; 158 u32 instance; 158 u32 instance; 159 int err; 159 int err; 160 160 161 err = nla_parse_nested(tb, IFLA_BRIDGE 161 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CONFIG_MAX, attr, 162 br_cfm_mep_conf 162 br_cfm_mep_config_policy, extack); 163 if (err) 163 if (err) 164 return err; 164 return err; 165 165 166 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INS 166 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]) { 167 NL_SET_ERR_MSG_MOD(extack, "Mi 167 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute"); 168 return -EINVAL; 168 return -EINVAL; 169 } 169 } 170 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNI 170 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC]) { 171 NL_SET_ERR_MSG_MOD(extack, "Mi 171 NL_SET_ERR_MSG_MOD(extack, "Missing UNICAST_MAC attribute"); 172 return -EINVAL; 172 return -EINVAL; 173 } 173 } 174 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDL 174 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]) { 175 NL_SET_ERR_MSG_MOD(extack, "Mi 175 NL_SET_ERR_MSG_MOD(extack, "Missing MDLEVEL attribute"); 176 return -EINVAL; 176 return -EINVAL; 177 } 177 } 178 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEP 178 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]) { 179 NL_SET_ERR_MSG_MOD(extack, "Mi 179 NL_SET_ERR_MSG_MOD(extack, "Missing MEPID attribute"); 180 return -EINVAL; 180 return -EINVAL; 181 } 181 } 182 182 183 memset(&config, 0, sizeof(config)); 183 memset(&config, 0, sizeof(config)); 184 184 185 instance = nla_get_u32(tb[IFLA_BRIDGE 185 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]); 186 nla_memcpy(&config.unicast_mac.addr, 186 nla_memcpy(&config.unicast_mac.addr, 187 tb[IFLA_BRIDGE_CFM_MEP_CONF 187 tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC], 188 sizeof(config.unicast_mac.a 188 sizeof(config.unicast_mac.addr)); 189 config.mdlevel = nla_get_u32(tb[IFLA_B 189 config.mdlevel = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]); 190 config.mepid = nla_get_u32(tb[IFLA_BRI 190 config.mepid = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]); 191 191 192 return br_cfm_mep_config_set(br, insta 192 return br_cfm_mep_config_set(br, instance, &config, extack); 193 } 193 } 194 194 195 static int br_cc_config_parse(struct net_bridg 195 static int br_cc_config_parse(struct net_bridge *br, struct nlattr *attr, 196 struct netlink_e 196 struct netlink_ext_ack *extack) 197 { 197 { 198 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_C 198 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1]; 199 struct br_cfm_cc_config config; 199 struct br_cfm_cc_config config; 200 u32 instance; 200 u32 instance; 201 int err; 201 int err; 202 202 203 err = nla_parse_nested(tb, IFLA_BRIDGE 203 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CONFIG_MAX, attr, 204 br_cfm_cc_confi 204 br_cfm_cc_config_policy, extack); 205 if (err) 205 if (err) 206 return err; 206 return err; 207 207 208 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INST 208 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]) { 209 NL_SET_ERR_MSG_MOD(extack, "Mi 209 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute"); 210 return -EINVAL; 210 return -EINVAL; 211 } 211 } 212 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENAB 212 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]) { 213 NL_SET_ERR_MSG_MOD(extack, "Mi 213 NL_SET_ERR_MSG_MOD(extack, "Missing ENABLE attribute"); 214 return -EINVAL; 214 return -EINVAL; 215 } 215 } 216 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_ 216 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]) { 217 NL_SET_ERR_MSG_MOD(extack, "Mi 217 NL_SET_ERR_MSG_MOD(extack, "Missing INTERVAL attribute"); 218 return -EINVAL; 218 return -EINVAL; 219 } 219 } 220 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_ 220 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]) { 221 NL_SET_ERR_MSG_MOD(extack, "Mi 221 NL_SET_ERR_MSG_MOD(extack, "Missing MAID attribute"); 222 return -EINVAL; 222 return -EINVAL; 223 } 223 } 224 224 225 memset(&config, 0, sizeof(config)); 225 memset(&config, 0, sizeof(config)); 226 226 227 instance = nla_get_u32(tb[IFLA_BRIDGE 227 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]); 228 config.enable = nla_get_u32(tb[IFLA_BR 228 config.enable = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]); 229 config.exp_interval = nla_get_u32(tb[I 229 config.exp_interval = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]); 230 nla_memcpy(&config.exp_maid.data, tb[I 230 nla_memcpy(&config.exp_maid.data, tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID], 231 sizeof(config.exp_maid.data 231 sizeof(config.exp_maid.data)); 232 232 233 return br_cfm_cc_config_set(br, instan 233 return br_cfm_cc_config_set(br, instance, &config, extack); 234 } 234 } 235 235 236 static int br_cc_peer_mep_add_parse(struct net 236 static int br_cc_peer_mep_add_parse(struct net_bridge *br, struct nlattr *attr, 237 struct net 237 struct netlink_ext_ack *extack) 238 { 238 { 239 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_P 239 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1]; 240 u32 instance, peer_mep_id; 240 u32 instance, peer_mep_id; 241 int err; 241 int err; 242 242 243 err = nla_parse_nested(tb, IFLA_BRIDGE 243 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr, 244 br_cfm_cc_peer_ 244 br_cfm_cc_peer_mep_policy, extack); 245 if (err) 245 if (err) 246 return err; 246 return err; 247 247 248 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_IN 248 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) { 249 NL_SET_ERR_MSG_MOD(extack, "Mi 249 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute"); 250 return -EINVAL; 250 return -EINVAL; 251 } 251 } 252 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID] 252 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) { 253 NL_SET_ERR_MSG_MOD(extack, "Mi 253 NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute"); 254 return -EINVAL; 254 return -EINVAL; 255 } 255 } 256 256 257 instance = nla_get_u32(tb[IFLA_BRIDGE 257 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]); 258 peer_mep_id = nla_get_u32(tb[IFLA_BRI 258 peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]); 259 259 260 return br_cfm_cc_peer_mep_add(br, inst 260 return br_cfm_cc_peer_mep_add(br, instance, peer_mep_id, extack); 261 } 261 } 262 262 263 static int br_cc_peer_mep_remove_parse(struct 263 static int br_cc_peer_mep_remove_parse(struct net_bridge *br, struct nlattr *attr, 264 struct 264 struct netlink_ext_ack *extack) 265 { 265 { 266 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_P 266 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1]; 267 u32 instance, peer_mep_id; 267 u32 instance, peer_mep_id; 268 int err; 268 int err; 269 269 270 err = nla_parse_nested(tb, IFLA_BRIDGE 270 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr, 271 br_cfm_cc_peer_ 271 br_cfm_cc_peer_mep_policy, extack); 272 if (err) 272 if (err) 273 return err; 273 return err; 274 274 275 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_IN 275 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) { 276 NL_SET_ERR_MSG_MOD(extack, "Mi 276 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute"); 277 return -EINVAL; 277 return -EINVAL; 278 } 278 } 279 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID] 279 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) { 280 NL_SET_ERR_MSG_MOD(extack, "Mi 280 NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute"); 281 return -EINVAL; 281 return -EINVAL; 282 } 282 } 283 283 284 instance = nla_get_u32(tb[IFLA_BRIDGE 284 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]); 285 peer_mep_id = nla_get_u32(tb[IFLA_BRI 285 peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]); 286 286 287 return br_cfm_cc_peer_mep_remove(br, i 287 return br_cfm_cc_peer_mep_remove(br, instance, peer_mep_id, extack); 288 } 288 } 289 289 290 static int br_cc_rdi_parse(struct net_bridge * 290 static int br_cc_rdi_parse(struct net_bridge *br, struct nlattr *attr, 291 struct netlink_ext_ 291 struct netlink_ext_ack *extack) 292 { 292 { 293 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_R 293 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1]; 294 u32 instance, rdi; 294 u32 instance, rdi; 295 int err; 295 int err; 296 296 297 err = nla_parse_nested(tb, IFLA_BRIDGE 297 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_RDI_MAX, attr, 298 br_cfm_cc_rdi_p 298 br_cfm_cc_rdi_policy, extack); 299 if (err) 299 if (err) 300 return err; 300 return err; 301 301 302 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANC 302 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]) { 303 NL_SET_ERR_MSG_MOD(extack, "Mi 303 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute"); 304 return -EINVAL; 304 return -EINVAL; 305 } 305 } 306 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) { 306 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) { 307 NL_SET_ERR_MSG_MOD(extack, "Mi 307 NL_SET_ERR_MSG_MOD(extack, "Missing RDI attribute"); 308 return -EINVAL; 308 return -EINVAL; 309 } 309 } 310 310 311 instance = nla_get_u32(tb[IFLA_BRIDGE 311 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]); 312 rdi = nla_get_u32(tb[IFLA_BRIDGE_CFM_ 312 rdi = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]); 313 313 314 return br_cfm_cc_rdi_set(br, instance, 314 return br_cfm_cc_rdi_set(br, instance, rdi, extack); 315 } 315 } 316 316 317 static int br_cc_ccm_tx_parse(struct net_bridg 317 static int br_cc_ccm_tx_parse(struct net_bridge *br, struct nlattr *attr, 318 struct netlink_e 318 struct netlink_ext_ack *extack) 319 { 319 { 320 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_C 320 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1]; 321 struct br_cfm_cc_ccm_tx_info tx_info; 321 struct br_cfm_cc_ccm_tx_info tx_info; 322 u32 instance; 322 u32 instance; 323 int err; 323 int err; 324 324 325 err = nla_parse_nested(tb, IFLA_BRIDGE 325 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CCM_TX_MAX, attr, 326 br_cfm_cc_ccm_t 326 br_cfm_cc_ccm_tx_policy, extack); 327 if (err) 327 if (err) 328 return err; 328 return err; 329 329 330 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INST 330 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]) { 331 NL_SET_ERR_MSG_MOD(extack, "Mi 331 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute"); 332 return -EINVAL; 332 return -EINVAL; 333 } 333 } 334 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC 334 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]) { 335 NL_SET_ERR_MSG_MOD(extack, "Mi 335 NL_SET_ERR_MSG_MOD(extack, "Missing DMAC attribute"); 336 return -EINVAL; 336 return -EINVAL; 337 } 337 } 338 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_ 338 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]) { 339 NL_SET_ERR_MSG_MOD(extack, "Mi 339 NL_SET_ERR_MSG_MOD(extack, "Missing SEQ_NO_UPDATE attribute"); 340 return -EINVAL; 340 return -EINVAL; 341 } 341 } 342 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERI 342 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]) { 343 NL_SET_ERR_MSG_MOD(extack, "Mi 343 NL_SET_ERR_MSG_MOD(extack, "Missing PERIOD attribute"); 344 return -EINVAL; 344 return -EINVAL; 345 } 345 } 346 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_T 346 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]) { 347 NL_SET_ERR_MSG_MOD(extack, "Mi 347 NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV attribute"); 348 return -EINVAL; 348 return -EINVAL; 349 } 349 } 350 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_T 350 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]) { 351 NL_SET_ERR_MSG_MOD(extack, "Mi 351 NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV_VALUE attribute"); 352 return -EINVAL; 352 return -EINVAL; 353 } 353 } 354 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT 354 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]) { 355 NL_SET_ERR_MSG_MOD(extack, "Mi 355 NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV attribute"); 356 return -EINVAL; 356 return -EINVAL; 357 } 357 } 358 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT 358 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]) { 359 NL_SET_ERR_MSG_MOD(extack, "Mi 359 NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV_VALUE attribute"); 360 return -EINVAL; 360 return -EINVAL; 361 } 361 } 362 362 363 memset(&tx_info, 0, sizeof(tx_info)); 363 memset(&tx_info, 0, sizeof(tx_info)); 364 364 365 instance = nla_get_u32(tb[IFLA_BRIDGE_ 365 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]); 366 nla_memcpy(&tx_info.dmac.addr, 366 nla_memcpy(&tx_info.dmac.addr, 367 tb[IFLA_BRIDGE_CFM_CC_CCM_T 367 tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC], 368 sizeof(tx_info.dmac.addr)); 368 sizeof(tx_info.dmac.addr)); 369 tx_info.seq_no_update = nla_get_u32(tb 369 tx_info.seq_no_update = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]); 370 tx_info.period = nla_get_u32(tb[IFLA_B 370 tx_info.period = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]); 371 tx_info.if_tlv = nla_get_u32(tb[IFLA_B 371 tx_info.if_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]); 372 tx_info.if_tlv_value = nla_get_u8(tb[I 372 tx_info.if_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]); 373 tx_info.port_tlv = nla_get_u32(tb[IFLA 373 tx_info.port_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]); 374 tx_info.port_tlv_value = nla_get_u8(tb 374 tx_info.port_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]); 375 375 376 return br_cfm_cc_ccm_tx(br, instance, 376 return br_cfm_cc_ccm_tx(br, instance, &tx_info, extack); 377 } 377 } 378 378 379 int br_cfm_parse(struct net_bridge *br, struct 379 int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p, 380 struct nlattr *attr, int cmd, 380 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack) 381 { 381 { 382 struct nlattr *tb[IFLA_BRIDGE_CFM_MAX 382 struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1]; 383 int err; 383 int err; 384 384 385 /* When this function is called for a 385 /* When this function is called for a port then the br pointer is 386 * invalid, therefor set the br to poi 386 * invalid, therefor set the br to point correctly 387 */ 387 */ 388 if (p) 388 if (p) 389 br = p->br; 389 br = p->br; 390 390 391 err = nla_parse_nested(tb, IFLA_BRIDGE 391 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MAX, attr, 392 br_cfm_policy, 392 br_cfm_policy, extack); 393 if (err) 393 if (err) 394 return err; 394 return err; 395 395 396 if (tb[IFLA_BRIDGE_CFM_MEP_CREATE]) { 396 if (tb[IFLA_BRIDGE_CFM_MEP_CREATE]) { 397 err = br_mep_create_parse(br, 397 err = br_mep_create_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CREATE], 398 exta 398 extack); 399 if (err) 399 if (err) 400 return err; 400 return err; 401 } 401 } 402 402 403 if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) { 403 if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) { 404 err = br_mep_delete_parse(br, 404 err = br_mep_delete_parse(br, tb[IFLA_BRIDGE_CFM_MEP_DELETE], 405 exta 405 extack); 406 if (err) 406 if (err) 407 return err; 407 return err; 408 } 408 } 409 409 410 if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) { 410 if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) { 411 err = br_mep_config_parse(br, 411 err = br_mep_config_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CONFIG], 412 exta 412 extack); 413 if (err) 413 if (err) 414 return err; 414 return err; 415 } 415 } 416 416 417 if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) { 417 if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) { 418 err = br_cc_config_parse(br, t 418 err = br_cc_config_parse(br, tb[IFLA_BRIDGE_CFM_CC_CONFIG], 419 extac 419 extack); 420 if (err) 420 if (err) 421 return err; 421 return err; 422 } 422 } 423 423 424 if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD 424 if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]) { 425 err = br_cc_peer_mep_add_parse 425 err = br_cc_peer_mep_add_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD], 426 426 extack); 427 if (err) 427 if (err) 428 return err; 428 return err; 429 } 429 } 430 430 431 if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REM 431 if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]) { 432 err = br_cc_peer_mep_remove_pa 432 err = br_cc_peer_mep_remove_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE], 433 433 extack); 434 if (err) 434 if (err) 435 return err; 435 return err; 436 } 436 } 437 437 438 if (tb[IFLA_BRIDGE_CFM_CC_RDI]) { 438 if (tb[IFLA_BRIDGE_CFM_CC_RDI]) { 439 err = br_cc_rdi_parse(br, tb[I 439 err = br_cc_rdi_parse(br, tb[IFLA_BRIDGE_CFM_CC_RDI], 440 extack); 440 extack); 441 if (err) 441 if (err) 442 return err; 442 return err; 443 } 443 } 444 444 445 if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) { 445 if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) { 446 err = br_cc_ccm_tx_parse(br, t 446 err = br_cc_ccm_tx_parse(br, tb[IFLA_BRIDGE_CFM_CC_CCM_TX], 447 extac 447 extack); 448 if (err) 448 if (err) 449 return err; 449 return err; 450 } 450 } 451 451 452 return 0; 452 return 0; 453 } 453 } 454 454 455 int br_cfm_config_fill_info(struct sk_buff *sk 455 int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br) 456 { 456 { 457 struct br_cfm_peer_mep *peer_mep; 457 struct br_cfm_peer_mep *peer_mep; 458 struct br_cfm_mep *mep; 458 struct br_cfm_mep *mep; 459 struct nlattr *tb; 459 struct nlattr *tb; 460 460 461 hlist_for_each_entry_rcu(mep, &br->mep 461 hlist_for_each_entry_rcu(mep, &br->mep_list, head) { 462 tb = nla_nest_start(skb, IFLA_ 462 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INFO); 463 if (!tb) 463 if (!tb) 464 goto nla_info_failure; 464 goto nla_info_failure; 465 465 466 if (nla_put_u32(skb, IFLA_BRID 466 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE, 467 mep->instance) 467 mep->instance)) 468 goto nla_put_failure; 468 goto nla_put_failure; 469 469 470 if (nla_put_u32(skb, IFLA_BRID 470 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN, 471 mep->create.do 471 mep->create.domain)) 472 goto nla_put_failure; 472 goto nla_put_failure; 473 473 474 if (nla_put_u32(skb, IFLA_BRID 474 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION, 475 mep->create.di 475 mep->create.direction)) 476 goto nla_put_failure; 476 goto nla_put_failure; 477 477 478 if (nla_put_u32(skb, IFLA_BRID 478 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX, 479 mep->create.if 479 mep->create.ifindex)) 480 goto nla_put_failure; 480 goto nla_put_failure; 481 481 482 nla_nest_end(skb, tb); 482 nla_nest_end(skb, tb); 483 483 484 tb = nla_nest_start(skb, IFLA_ 484 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INFO); 485 485 486 if (!tb) 486 if (!tb) 487 goto nla_info_failure; 487 goto nla_info_failure; 488 488 489 if (nla_put_u32(skb, IFLA_BRID 489 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE, 490 mep->instance) 490 mep->instance)) 491 goto nla_put_failure; 491 goto nla_put_failure; 492 492 493 if (nla_put(skb, IFLA_BRIDGE_C 493 if (nla_put(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC, 494 sizeof(mep->config 494 sizeof(mep->config.unicast_mac.addr), 495 mep->config.unicas 495 mep->config.unicast_mac.addr)) 496 goto nla_put_failure; 496 goto nla_put_failure; 497 497 498 if (nla_put_u32(skb, IFLA_BRID 498 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL, 499 mep->config.md 499 mep->config.mdlevel)) 500 goto nla_put_failure; 500 goto nla_put_failure; 501 501 502 if (nla_put_u32(skb, IFLA_BRID 502 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID, 503 mep->config.me 503 mep->config.mepid)) 504 goto nla_put_failure; 504 goto nla_put_failure; 505 505 506 nla_nest_end(skb, tb); 506 nla_nest_end(skb, tb); 507 507 508 tb = nla_nest_start(skb, IFLA_ 508 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INFO); 509 509 510 if (!tb) 510 if (!tb) 511 goto nla_info_failure; 511 goto nla_info_failure; 512 512 513 if (nla_put_u32(skb, IFLA_BRID 513 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE, 514 mep->instance) 514 mep->instance)) 515 goto nla_put_failure; 515 goto nla_put_failure; 516 516 517 if (nla_put_u32(skb, IFLA_BRID 517 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE, 518 mep->cc_config 518 mep->cc_config.enable)) 519 goto nla_put_failure; 519 goto nla_put_failure; 520 520 521 if (nla_put_u32(skb, IFLA_BRID 521 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL, 522 mep->cc_config 522 mep->cc_config.exp_interval)) 523 goto nla_put_failure; 523 goto nla_put_failure; 524 524 525 if (nla_put(skb, IFLA_BRIDGE_C 525 if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID, 526 sizeof(mep->cc_con 526 sizeof(mep->cc_config.exp_maid.data), 527 mep->cc_config.exp 527 mep->cc_config.exp_maid.data)) 528 goto nla_put_failure; 528 goto nla_put_failure; 529 529 530 nla_nest_end(skb, tb); 530 nla_nest_end(skb, tb); 531 531 532 tb = nla_nest_start(skb, IFLA_ 532 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_RDI_INFO); 533 533 534 if (!tb) 534 if (!tb) 535 goto nla_info_failure; 535 goto nla_info_failure; 536 536 537 if (nla_put_u32(skb, IFLA_BRID 537 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE, 538 mep->instance) 538 mep->instance)) 539 goto nla_put_failure; 539 goto nla_put_failure; 540 540 541 if (nla_put_u32(skb, IFLA_BRID 541 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_RDI, 542 mep->rdi)) 542 mep->rdi)) 543 goto nla_put_failure; 543 goto nla_put_failure; 544 544 545 nla_nest_end(skb, tb); 545 nla_nest_end(skb, tb); 546 546 547 tb = nla_nest_start(skb, IFLA_ 547 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INFO); 548 548 549 if (!tb) 549 if (!tb) 550 goto nla_info_failure; 550 goto nla_info_failure; 551 551 552 if (nla_put_u32(skb, IFLA_BRID 552 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE, 553 mep->instance) 553 mep->instance)) 554 goto nla_put_failure; 554 goto nla_put_failure; 555 555 556 if (nla_put(skb, IFLA_BRIDGE_C 556 if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC, 557 sizeof(mep->cc_ccm 557 sizeof(mep->cc_ccm_tx_info.dmac), 558 mep->cc_ccm_tx_inf 558 mep->cc_ccm_tx_info.dmac.addr)) 559 goto nla_put_failure; 559 goto nla_put_failure; 560 560 561 if (nla_put_u32(skb, IFLA_BRID 561 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE, 562 mep->cc_ccm_tx 562 mep->cc_ccm_tx_info.seq_no_update)) 563 goto nla_put_failure; 563 goto nla_put_failure; 564 564 565 if (nla_put_u32(skb, IFLA_BRID 565 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD, 566 mep->cc_ccm_tx 566 mep->cc_ccm_tx_info.period)) 567 goto nla_put_failure; 567 goto nla_put_failure; 568 568 569 if (nla_put_u32(skb, IFLA_BRID 569 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV, 570 mep->cc_ccm_tx 570 mep->cc_ccm_tx_info.if_tlv)) 571 goto nla_put_failure; 571 goto nla_put_failure; 572 572 573 if (nla_put_u8(skb, IFLA_BRIDG 573 if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE, 574 mep->cc_ccm_tx_ 574 mep->cc_ccm_tx_info.if_tlv_value)) 575 goto nla_put_failure; 575 goto nla_put_failure; 576 576 577 if (nla_put_u32(skb, IFLA_BRID 577 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV, 578 mep->cc_ccm_tx 578 mep->cc_ccm_tx_info.port_tlv)) 579 goto nla_put_failure; 579 goto nla_put_failure; 580 580 581 if (nla_put_u8(skb, IFLA_BRIDG 581 if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE, 582 mep->cc_ccm_tx_ 582 mep->cc_ccm_tx_info.port_tlv_value)) 583 goto nla_put_failure; 583 goto nla_put_failure; 584 584 585 nla_nest_end(skb, tb); 585 nla_nest_end(skb, tb); 586 586 587 hlist_for_each_entry_rcu(peer_ 587 hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) { 588 tb = nla_nest_start(sk 588 tb = nla_nest_start(skb, 589 IF 589 IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO); 590 590 591 if (!tb) 591 if (!tb) 592 goto nla_info_ 592 goto nla_info_failure; 593 593 594 if (nla_put_u32(skb, 594 if (nla_put_u32(skb, 595 IFLA_B 595 IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE, 596 mep->i 596 mep->instance)) 597 goto nla_put_f 597 goto nla_put_failure; 598 598 599 if (nla_put_u32(skb, I 599 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_MEPID, 600 peer_m 600 peer_mep->mepid)) 601 goto nla_put_f 601 goto nla_put_failure; 602 602 603 nla_nest_end(skb, tb); 603 nla_nest_end(skb, tb); 604 } 604 } 605 } 605 } 606 606 607 return 0; 607 return 0; 608 608 609 nla_put_failure: 609 nla_put_failure: 610 nla_nest_cancel(skb, tb); 610 nla_nest_cancel(skb, tb); 611 611 612 nla_info_failure: 612 nla_info_failure: 613 return -EMSGSIZE; 613 return -EMSGSIZE; 614 } 614 } 615 615 616 int br_cfm_status_fill_info(struct sk_buff *sk 616 int br_cfm_status_fill_info(struct sk_buff *skb, 617 struct net_bridge 617 struct net_bridge *br, 618 bool getlink) 618 bool getlink) 619 { 619 { 620 struct br_cfm_peer_mep *peer_mep; 620 struct br_cfm_peer_mep *peer_mep; 621 struct br_cfm_mep *mep; 621 struct br_cfm_mep *mep; 622 struct nlattr *tb; 622 struct nlattr *tb; 623 623 624 hlist_for_each_entry_rcu(mep, &br->mep 624 hlist_for_each_entry_rcu(mep, &br->mep_list, head) { 625 tb = nla_nest_start(skb, IFLA_ 625 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INFO); 626 if (!tb) 626 if (!tb) 627 goto nla_info_failure; 627 goto nla_info_failure; 628 628 629 if (nla_put_u32(skb, IFLA_BRID 629 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE, 630 mep->instance) 630 mep->instance)) 631 goto nla_put_failure; 631 goto nla_put_failure; 632 632 633 if (nla_put_u32(skb, 633 if (nla_put_u32(skb, 634 IFLA_BRIDGE_CF 634 IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN, 635 mep->status.op 635 mep->status.opcode_unexp_seen)) 636 goto nla_put_failure; 636 goto nla_put_failure; 637 637 638 if (nla_put_u32(skb, 638 if (nla_put_u32(skb, 639 IFLA_BRIDGE_CF 639 IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN, 640 mep->status.ve 640 mep->status.version_unexp_seen)) 641 goto nla_put_failure; 641 goto nla_put_failure; 642 642 643 if (nla_put_u32(skb, 643 if (nla_put_u32(skb, 644 IFLA_BRIDGE_CF 644 IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN, 645 mep->status.rx 645 mep->status.rx_level_low_seen)) 646 goto nla_put_failure; 646 goto nla_put_failure; 647 647 648 /* Only clear if this is a GET 648 /* Only clear if this is a GETLINK */ 649 if (getlink) { 649 if (getlink) { 650 /* Clear all 'seen' in 650 /* Clear all 'seen' indications */ 651 mep->status.opcode_une 651 mep->status.opcode_unexp_seen = false; 652 mep->status.version_un 652 mep->status.version_unexp_seen = false; 653 mep->status.rx_level_l 653 mep->status.rx_level_low_seen = false; 654 } 654 } 655 655 656 nla_nest_end(skb, tb); 656 nla_nest_end(skb, tb); 657 657 658 hlist_for_each_entry_rcu(peer_ 658 hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) { 659 tb = nla_nest_start(sk 659 tb = nla_nest_start(skb, 660 IF 660 IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO); 661 if (!tb) 661 if (!tb) 662 goto nla_info_ 662 goto nla_info_failure; 663 663 664 if (nla_put_u32(skb, 664 if (nla_put_u32(skb, 665 IFLA_B 665 IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE, 666 mep->i 666 mep->instance)) 667 goto nla_put_f 667 goto nla_put_failure; 668 668 669 if (nla_put_u32(skb, 669 if (nla_put_u32(skb, 670 IFLA_B 670 IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID, 671 peer_m 671 peer_mep->mepid)) 672 goto nla_put_f 672 goto nla_put_failure; 673 673 674 if (nla_put_u32(skb, 674 if (nla_put_u32(skb, 675 IFLA_B 675 IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT, 676 peer_m 676 peer_mep->cc_status.ccm_defect)) 677 goto nla_put_f 677 goto nla_put_failure; 678 678 679 if (nla_put_u32(skb, I 679 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI, 680 peer_m 680 peer_mep->cc_status.rdi)) 681 goto nla_put_f 681 goto nla_put_failure; 682 682 683 if (nla_put_u8(skb, 683 if (nla_put_u8(skb, 684 IFLA_BR 684 IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE, 685 peer_me 685 peer_mep->cc_status.port_tlv_value)) 686 goto nla_put_f 686 goto nla_put_failure; 687 687 688 if (nla_put_u8(skb, 688 if (nla_put_u8(skb, 689 IFLA_BR 689 IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE, 690 peer_me 690 peer_mep->cc_status.if_tlv_value)) 691 goto nla_put_f 691 goto nla_put_failure; 692 692 693 if (nla_put_u32(skb, 693 if (nla_put_u32(skb, 694 IFLA_B 694 IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN, 695 peer_m 695 peer_mep->cc_status.seen)) 696 goto nla_put_f 696 goto nla_put_failure; 697 697 698 if (nla_put_u32(skb, 698 if (nla_put_u32(skb, 699 IFLA_B 699 IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN, 700 peer_m 700 peer_mep->cc_status.tlv_seen)) 701 goto nla_put_f 701 goto nla_put_failure; 702 702 703 if (nla_put_u32(skb, 703 if (nla_put_u32(skb, 704 IFLA_B 704 IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN, 705 peer_m 705 peer_mep->cc_status.seq_unexp_seen)) 706 goto nla_put_f 706 goto nla_put_failure; 707 707 708 if (getlink) { /* Only 708 if (getlink) { /* Only clear if this is a GETLINK */ 709 /* Clear all ' 709 /* Clear all 'seen' indications */ 710 peer_mep->cc_s 710 peer_mep->cc_status.seen = false; 711 peer_mep->cc_s 711 peer_mep->cc_status.tlv_seen = false; 712 peer_mep->cc_s 712 peer_mep->cc_status.seq_unexp_seen = false; 713 } 713 } 714 714 715 nla_nest_end(skb, tb); 715 nla_nest_end(skb, tb); 716 } 716 } 717 } 717 } 718 718 719 return 0; 719 return 0; 720 720 721 nla_put_failure: 721 nla_put_failure: 722 nla_nest_cancel(skb, tb); 722 nla_nest_cancel(skb, tb); 723 723 724 nla_info_failure: 724 nla_info_failure: 725 return -EMSGSIZE; 725 return -EMSGSIZE; 726 } 726 } 727 727
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.