Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
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     /* When this function is called for a port then the br pointer is
0386      * invalid, therefor set the br to point correctly
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         /* Only clear if this is a GETLINK */
0649         if (getlink) {
0650             /* Clear all 'seen' indications */
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) { /* Only clear if this is a GETLINK */
0709                 /* Clear all 'seen' indications */
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 }