0001
0002
0003 #include <net/genetlink.h>
0004
0005 #include "br_private.h"
0006 #include "br_private_cfm.h"
0007
0008 static const struct nla_policy
0009 br_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1] = {
0010 [IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC] = { .type = NLA_REJECT },
0011 [IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE] = { .type = NLA_U32 },
0012 [IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN] = { .type = NLA_U32 },
0013 [IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION] = { .type = NLA_U32 },
0014 [IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX] = { .type = NLA_U32 },
0015 };
0016
0017 static const struct nla_policy
0018 br_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1] = {
0019 [IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC] = { .type = NLA_REJECT },
0020 [IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE] = { .type = NLA_U32 },
0021 };
0022
0023 static const struct nla_policy
0024 br_cfm_mep_config_policy[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1] = {
0025 [IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC] = { .type = NLA_REJECT },
0026 [IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE] = { .type = NLA_U32 },
0027 [IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = NLA_POLICY_ETH_ADDR,
0028 [IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL] = NLA_POLICY_MAX(NLA_U32, 7),
0029 [IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
0030 };
0031
0032 static const struct nla_policy
0033 br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = {
0034 [IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] = { .type = NLA_REJECT },
0035 [IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] = { .type = NLA_U32 },
0036 [IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] = { .type = NLA_U32 },
0037 [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 },
0038 [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID] = {
0039 .type = NLA_BINARY, .len = CFM_MAID_LENGTH },
0040 };
0041
0042 static const struct nla_policy
0043 br_cfm_cc_peer_mep_policy[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1] = {
0044 [IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC] = { .type = NLA_REJECT },
0045 [IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE] = { .type = NLA_U32 },
0046 [IFLA_BRIDGE_CFM_CC_PEER_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
0047 };
0048
0049 static const struct nla_policy
0050 br_cfm_cc_rdi_policy[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1] = {
0051 [IFLA_BRIDGE_CFM_CC_RDI_UNSPEC] = { .type = NLA_REJECT },
0052 [IFLA_BRIDGE_CFM_CC_RDI_INSTANCE] = { .type = NLA_U32 },
0053 [IFLA_BRIDGE_CFM_CC_RDI_RDI] = { .type = NLA_U32 },
0054 };
0055
0056 static const struct nla_policy
0057 br_cfm_cc_ccm_tx_policy[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1] = {
0058 [IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC] = { .type = NLA_REJECT },
0059 [IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE] = { .type = NLA_U32 },
0060 [IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC] = NLA_POLICY_ETH_ADDR,
0061 [IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE] = { .type = NLA_U32 },
0062 [IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD] = { .type = NLA_U32 },
0063 [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV] = { .type = NLA_U32 },
0064 [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE] = { .type = NLA_U8 },
0065 [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV] = { .type = NLA_U32 },
0066 [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = { .type = NLA_U8 },
0067 };
0068
0069 static const struct nla_policy
0070 br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = {
0071 [IFLA_BRIDGE_CFM_UNSPEC] = { .type = NLA_REJECT },
0072 [IFLA_BRIDGE_CFM_MEP_CREATE] =
0073 NLA_POLICY_NESTED(br_cfm_mep_create_policy),
0074 [IFLA_BRIDGE_CFM_MEP_DELETE] =
0075 NLA_POLICY_NESTED(br_cfm_mep_delete_policy),
0076 [IFLA_BRIDGE_CFM_MEP_CONFIG] =
0077 NLA_POLICY_NESTED(br_cfm_mep_config_policy),
0078 [IFLA_BRIDGE_CFM_CC_CONFIG] =
0079 NLA_POLICY_NESTED(br_cfm_cc_config_policy),
0080 [IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD] =
0081 NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
0082 [IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE] =
0083 NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
0084 [IFLA_BRIDGE_CFM_CC_RDI] =
0085 NLA_POLICY_NESTED(br_cfm_cc_rdi_policy),
0086 [IFLA_BRIDGE_CFM_CC_CCM_TX] =
0087 NLA_POLICY_NESTED(br_cfm_cc_ccm_tx_policy),
0088 };
0089
0090 static int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr,
0091 struct netlink_ext_ack *extack)
0092 {
0093 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1];
0094 struct br_cfm_mep_create create;
0095 u32 instance;
0096 int err;
0097
0098 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CREATE_MAX, attr,
0099 br_cfm_mep_create_policy, extack);
0100 if (err)
0101 return err;
0102
0103 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]) {
0104 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
0105 return -EINVAL;
0106 }
0107 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]) {
0108 NL_SET_ERR_MSG_MOD(extack, "Missing DOMAIN attribute");
0109 return -EINVAL;
0110 }
0111 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]) {
0112 NL_SET_ERR_MSG_MOD(extack, "Missing DIRECTION attribute");
0113 return -EINVAL;
0114 }
0115 if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]) {
0116 NL_SET_ERR_MSG_MOD(extack, "Missing IFINDEX attribute");
0117 return -EINVAL;
0118 }
0119
0120 memset(&create, 0, sizeof(create));
0121
0122 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]);
0123 create.domain = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]);
0124 create.direction = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]);
0125 create.ifindex = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]);
0126
0127 return br_cfm_mep_create(br, instance, &create, extack);
0128 }
0129
0130 static int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr,
0131 struct netlink_ext_ack *extack)
0132 {
0133 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1];
0134 u32 instance;
0135 int err;
0136
0137 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_DELETE_MAX, attr,
0138 br_cfm_mep_delete_policy, extack);
0139 if (err)
0140 return err;
0141
0142 if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]) {
0143 NL_SET_ERR_MSG_MOD(extack,
0144 "Missing INSTANCE attribute");
0145 return -EINVAL;
0146 }
0147
0148 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]);
0149
0150 return br_cfm_mep_delete(br, instance, extack);
0151 }
0152
0153 static int br_mep_config_parse(struct net_bridge *br, struct nlattr *attr,
0154 struct netlink_ext_ack *extack)
0155 {
0156 struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1];
0157 struct br_cfm_mep_config config;
0158 u32 instance;
0159 int err;
0160
0161 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CONFIG_MAX, attr,
0162 br_cfm_mep_config_policy, extack);
0163 if (err)
0164 return err;
0165
0166 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]) {
0167 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
0168 return -EINVAL;
0169 }
0170 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC]) {
0171 NL_SET_ERR_MSG_MOD(extack, "Missing UNICAST_MAC attribute");
0172 return -EINVAL;
0173 }
0174 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]) {
0175 NL_SET_ERR_MSG_MOD(extack, "Missing MDLEVEL attribute");
0176 return -EINVAL;
0177 }
0178 if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]) {
0179 NL_SET_ERR_MSG_MOD(extack, "Missing MEPID attribute");
0180 return -EINVAL;
0181 }
0182
0183 memset(&config, 0, sizeof(config));
0184
0185 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]);
0186 nla_memcpy(&config.unicast_mac.addr,
0187 tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC],
0188 sizeof(config.unicast_mac.addr));
0189 config.mdlevel = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]);
0190 config.mepid = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]);
0191
0192 return br_cfm_mep_config_set(br, instance, &config, extack);
0193 }
0194
0195 static int br_cc_config_parse(struct net_bridge *br, struct nlattr *attr,
0196 struct netlink_ext_ack *extack)
0197 {
0198 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1];
0199 struct br_cfm_cc_config config;
0200 u32 instance;
0201 int err;
0202
0203 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CONFIG_MAX, attr,
0204 br_cfm_cc_config_policy, extack);
0205 if (err)
0206 return err;
0207
0208 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]) {
0209 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
0210 return -EINVAL;
0211 }
0212 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]) {
0213 NL_SET_ERR_MSG_MOD(extack, "Missing ENABLE attribute");
0214 return -EINVAL;
0215 }
0216 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]) {
0217 NL_SET_ERR_MSG_MOD(extack, "Missing INTERVAL attribute");
0218 return -EINVAL;
0219 }
0220 if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]) {
0221 NL_SET_ERR_MSG_MOD(extack, "Missing MAID attribute");
0222 return -EINVAL;
0223 }
0224
0225 memset(&config, 0, sizeof(config));
0226
0227 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]);
0228 config.enable = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]);
0229 config.exp_interval = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]);
0230 nla_memcpy(&config.exp_maid.data, tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID],
0231 sizeof(config.exp_maid.data));
0232
0233 return br_cfm_cc_config_set(br, instance, &config, extack);
0234 }
0235
0236 static int br_cc_peer_mep_add_parse(struct net_bridge *br, struct nlattr *attr,
0237 struct netlink_ext_ack *extack)
0238 {
0239 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
0240 u32 instance, peer_mep_id;
0241 int err;
0242
0243 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
0244 br_cfm_cc_peer_mep_policy, extack);
0245 if (err)
0246 return err;
0247
0248 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
0249 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
0250 return -EINVAL;
0251 }
0252 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
0253 NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
0254 return -EINVAL;
0255 }
0256
0257 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
0258 peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
0259
0260 return br_cfm_cc_peer_mep_add(br, instance, peer_mep_id, extack);
0261 }
0262
0263 static int br_cc_peer_mep_remove_parse(struct net_bridge *br, struct nlattr *attr,
0264 struct netlink_ext_ack *extack)
0265 {
0266 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
0267 u32 instance, peer_mep_id;
0268 int err;
0269
0270 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
0271 br_cfm_cc_peer_mep_policy, extack);
0272 if (err)
0273 return err;
0274
0275 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
0276 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
0277 return -EINVAL;
0278 }
0279 if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
0280 NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
0281 return -EINVAL;
0282 }
0283
0284 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
0285 peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
0286
0287 return br_cfm_cc_peer_mep_remove(br, instance, peer_mep_id, extack);
0288 }
0289
0290 static int br_cc_rdi_parse(struct net_bridge *br, struct nlattr *attr,
0291 struct netlink_ext_ack *extack)
0292 {
0293 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1];
0294 u32 instance, rdi;
0295 int err;
0296
0297 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_RDI_MAX, attr,
0298 br_cfm_cc_rdi_policy, extack);
0299 if (err)
0300 return err;
0301
0302 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]) {
0303 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
0304 return -EINVAL;
0305 }
0306 if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) {
0307 NL_SET_ERR_MSG_MOD(extack, "Missing RDI attribute");
0308 return -EINVAL;
0309 }
0310
0311 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]);
0312 rdi = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]);
0313
0314 return br_cfm_cc_rdi_set(br, instance, rdi, extack);
0315 }
0316
0317 static int br_cc_ccm_tx_parse(struct net_bridge *br, struct nlattr *attr,
0318 struct netlink_ext_ack *extack)
0319 {
0320 struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1];
0321 struct br_cfm_cc_ccm_tx_info tx_info;
0322 u32 instance;
0323 int err;
0324
0325 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CCM_TX_MAX, attr,
0326 br_cfm_cc_ccm_tx_policy, extack);
0327 if (err)
0328 return err;
0329
0330 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]) {
0331 NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
0332 return -EINVAL;
0333 }
0334 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]) {
0335 NL_SET_ERR_MSG_MOD(extack, "Missing DMAC attribute");
0336 return -EINVAL;
0337 }
0338 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]) {
0339 NL_SET_ERR_MSG_MOD(extack, "Missing SEQ_NO_UPDATE attribute");
0340 return -EINVAL;
0341 }
0342 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]) {
0343 NL_SET_ERR_MSG_MOD(extack, "Missing PERIOD attribute");
0344 return -EINVAL;
0345 }
0346 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]) {
0347 NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV attribute");
0348 return -EINVAL;
0349 }
0350 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]) {
0351 NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV_VALUE attribute");
0352 return -EINVAL;
0353 }
0354 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]) {
0355 NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV attribute");
0356 return -EINVAL;
0357 }
0358 if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]) {
0359 NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV_VALUE attribute");
0360 return -EINVAL;
0361 }
0362
0363 memset(&tx_info, 0, sizeof(tx_info));
0364
0365 instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]);
0366 nla_memcpy(&tx_info.dmac.addr,
0367 tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC],
0368 sizeof(tx_info.dmac.addr));
0369 tx_info.seq_no_update = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]);
0370 tx_info.period = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]);
0371 tx_info.if_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]);
0372 tx_info.if_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]);
0373 tx_info.port_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]);
0374 tx_info.port_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]);
0375
0376 return br_cfm_cc_ccm_tx(br, instance, &tx_info, extack);
0377 }
0378
0379 int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
0380 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
0381 {
0382 struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1];
0383 int err;
0384
0385
0386
0387
0388 if (p)
0389 br = p->br;
0390
0391 err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MAX, attr,
0392 br_cfm_policy, extack);
0393 if (err)
0394 return err;
0395
0396 if (tb[IFLA_BRIDGE_CFM_MEP_CREATE]) {
0397 err = br_mep_create_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CREATE],
0398 extack);
0399 if (err)
0400 return err;
0401 }
0402
0403 if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) {
0404 err = br_mep_delete_parse(br, tb[IFLA_BRIDGE_CFM_MEP_DELETE],
0405 extack);
0406 if (err)
0407 return err;
0408 }
0409
0410 if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) {
0411 err = br_mep_config_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CONFIG],
0412 extack);
0413 if (err)
0414 return err;
0415 }
0416
0417 if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) {
0418 err = br_cc_config_parse(br, tb[IFLA_BRIDGE_CFM_CC_CONFIG],
0419 extack);
0420 if (err)
0421 return err;
0422 }
0423
0424 if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]) {
0425 err = br_cc_peer_mep_add_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD],
0426 extack);
0427 if (err)
0428 return err;
0429 }
0430
0431 if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]) {
0432 err = br_cc_peer_mep_remove_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE],
0433 extack);
0434 if (err)
0435 return err;
0436 }
0437
0438 if (tb[IFLA_BRIDGE_CFM_CC_RDI]) {
0439 err = br_cc_rdi_parse(br, tb[IFLA_BRIDGE_CFM_CC_RDI],
0440 extack);
0441 if (err)
0442 return err;
0443 }
0444
0445 if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) {
0446 err = br_cc_ccm_tx_parse(br, tb[IFLA_BRIDGE_CFM_CC_CCM_TX],
0447 extack);
0448 if (err)
0449 return err;
0450 }
0451
0452 return 0;
0453 }
0454
0455 int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
0456 {
0457 struct br_cfm_peer_mep *peer_mep;
0458 struct br_cfm_mep *mep;
0459 struct nlattr *tb;
0460
0461 hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
0462 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INFO);
0463 if (!tb)
0464 goto nla_info_failure;
0465
0466 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE,
0467 mep->instance))
0468 goto nla_put_failure;
0469
0470 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN,
0471 mep->create.domain))
0472 goto nla_put_failure;
0473
0474 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION,
0475 mep->create.direction))
0476 goto nla_put_failure;
0477
0478 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX,
0479 mep->create.ifindex))
0480 goto nla_put_failure;
0481
0482 nla_nest_end(skb, tb);
0483
0484 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INFO);
0485
0486 if (!tb)
0487 goto nla_info_failure;
0488
0489 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE,
0490 mep->instance))
0491 goto nla_put_failure;
0492
0493 if (nla_put(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC,
0494 sizeof(mep->config.unicast_mac.addr),
0495 mep->config.unicast_mac.addr))
0496 goto nla_put_failure;
0497
0498 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL,
0499 mep->config.mdlevel))
0500 goto nla_put_failure;
0501
0502 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID,
0503 mep->config.mepid))
0504 goto nla_put_failure;
0505
0506 nla_nest_end(skb, tb);
0507
0508 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INFO);
0509
0510 if (!tb)
0511 goto nla_info_failure;
0512
0513 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE,
0514 mep->instance))
0515 goto nla_put_failure;
0516
0517 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE,
0518 mep->cc_config.enable))
0519 goto nla_put_failure;
0520
0521 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL,
0522 mep->cc_config.exp_interval))
0523 goto nla_put_failure;
0524
0525 if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID,
0526 sizeof(mep->cc_config.exp_maid.data),
0527 mep->cc_config.exp_maid.data))
0528 goto nla_put_failure;
0529
0530 nla_nest_end(skb, tb);
0531
0532 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_RDI_INFO);
0533
0534 if (!tb)
0535 goto nla_info_failure;
0536
0537 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE,
0538 mep->instance))
0539 goto nla_put_failure;
0540
0541 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_RDI,
0542 mep->rdi))
0543 goto nla_put_failure;
0544
0545 nla_nest_end(skb, tb);
0546
0547 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INFO);
0548
0549 if (!tb)
0550 goto nla_info_failure;
0551
0552 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE,
0553 mep->instance))
0554 goto nla_put_failure;
0555
0556 if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC,
0557 sizeof(mep->cc_ccm_tx_info.dmac),
0558 mep->cc_ccm_tx_info.dmac.addr))
0559 goto nla_put_failure;
0560
0561 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE,
0562 mep->cc_ccm_tx_info.seq_no_update))
0563 goto nla_put_failure;
0564
0565 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD,
0566 mep->cc_ccm_tx_info.period))
0567 goto nla_put_failure;
0568
0569 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV,
0570 mep->cc_ccm_tx_info.if_tlv))
0571 goto nla_put_failure;
0572
0573 if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE,
0574 mep->cc_ccm_tx_info.if_tlv_value))
0575 goto nla_put_failure;
0576
0577 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV,
0578 mep->cc_ccm_tx_info.port_tlv))
0579 goto nla_put_failure;
0580
0581 if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE,
0582 mep->cc_ccm_tx_info.port_tlv_value))
0583 goto nla_put_failure;
0584
0585 nla_nest_end(skb, tb);
0586
0587 hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
0588 tb = nla_nest_start(skb,
0589 IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO);
0590
0591 if (!tb)
0592 goto nla_info_failure;
0593
0594 if (nla_put_u32(skb,
0595 IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE,
0596 mep->instance))
0597 goto nla_put_failure;
0598
0599 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_MEPID,
0600 peer_mep->mepid))
0601 goto nla_put_failure;
0602
0603 nla_nest_end(skb, tb);
0604 }
0605 }
0606
0607 return 0;
0608
0609 nla_put_failure:
0610 nla_nest_cancel(skb, tb);
0611
0612 nla_info_failure:
0613 return -EMSGSIZE;
0614 }
0615
0616 int br_cfm_status_fill_info(struct sk_buff *skb,
0617 struct net_bridge *br,
0618 bool getlink)
0619 {
0620 struct br_cfm_peer_mep *peer_mep;
0621 struct br_cfm_mep *mep;
0622 struct nlattr *tb;
0623
0624 hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
0625 tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INFO);
0626 if (!tb)
0627 goto nla_info_failure;
0628
0629 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE,
0630 mep->instance))
0631 goto nla_put_failure;
0632
0633 if (nla_put_u32(skb,
0634 IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN,
0635 mep->status.opcode_unexp_seen))
0636 goto nla_put_failure;
0637
0638 if (nla_put_u32(skb,
0639 IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN,
0640 mep->status.version_unexp_seen))
0641 goto nla_put_failure;
0642
0643 if (nla_put_u32(skb,
0644 IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN,
0645 mep->status.rx_level_low_seen))
0646 goto nla_put_failure;
0647
0648
0649 if (getlink) {
0650
0651 mep->status.opcode_unexp_seen = false;
0652 mep->status.version_unexp_seen = false;
0653 mep->status.rx_level_low_seen = false;
0654 }
0655
0656 nla_nest_end(skb, tb);
0657
0658 hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
0659 tb = nla_nest_start(skb,
0660 IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO);
0661 if (!tb)
0662 goto nla_info_failure;
0663
0664 if (nla_put_u32(skb,
0665 IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE,
0666 mep->instance))
0667 goto nla_put_failure;
0668
0669 if (nla_put_u32(skb,
0670 IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID,
0671 peer_mep->mepid))
0672 goto nla_put_failure;
0673
0674 if (nla_put_u32(skb,
0675 IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT,
0676 peer_mep->cc_status.ccm_defect))
0677 goto nla_put_failure;
0678
0679 if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI,
0680 peer_mep->cc_status.rdi))
0681 goto nla_put_failure;
0682
0683 if (nla_put_u8(skb,
0684 IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE,
0685 peer_mep->cc_status.port_tlv_value))
0686 goto nla_put_failure;
0687
0688 if (nla_put_u8(skb,
0689 IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE,
0690 peer_mep->cc_status.if_tlv_value))
0691 goto nla_put_failure;
0692
0693 if (nla_put_u32(skb,
0694 IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN,
0695 peer_mep->cc_status.seen))
0696 goto nla_put_failure;
0697
0698 if (nla_put_u32(skb,
0699 IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN,
0700 peer_mep->cc_status.tlv_seen))
0701 goto nla_put_failure;
0702
0703 if (nla_put_u32(skb,
0704 IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN,
0705 peer_mep->cc_status.seq_unexp_seen))
0706 goto nla_put_failure;
0707
0708 if (getlink) {
0709
0710 peer_mep->cc_status.seen = false;
0711 peer_mep->cc_status.tlv_seen = false;
0712 peer_mep->cc_status.seq_unexp_seen = false;
0713 }
0714
0715 nla_nest_end(skb, tb);
0716 }
0717 }
0718
0719 return 0;
0720
0721 nla_put_failure:
0722 nla_nest_cancel(skb, tb);
0723
0724 nla_info_failure:
0725 return -EMSGSIZE;
0726 }