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