12be665c3SHenrik Bjoernlund // SPDX-License-Identifier: GPL-2.0-or-later
22be665c3SHenrik Bjoernlund
32be665c3SHenrik Bjoernlund #include <net/genetlink.h>
42be665c3SHenrik Bjoernlund
52be665c3SHenrik Bjoernlund #include "br_private.h"
62be665c3SHenrik Bjoernlund #include "br_private_cfm.h"
72be665c3SHenrik Bjoernlund
82be665c3SHenrik Bjoernlund static const struct nla_policy
92be665c3SHenrik Bjoernlund br_cfm_mep_create_policy[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1] = {
102be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC] = { .type = NLA_REJECT },
112be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE] = { .type = NLA_U32 },
122be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN] = { .type = NLA_U32 },
132be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION] = { .type = NLA_U32 },
142be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX] = { .type = NLA_U32 },
152be665c3SHenrik Bjoernlund };
162be665c3SHenrik Bjoernlund
172be665c3SHenrik Bjoernlund static const struct nla_policy
182be665c3SHenrik Bjoernlund br_cfm_mep_delete_policy[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1] = {
192be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC] = { .type = NLA_REJECT },
202be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE] = { .type = NLA_U32 },
212be665c3SHenrik Bjoernlund };
222be665c3SHenrik Bjoernlund
232be665c3SHenrik Bjoernlund static const struct nla_policy
242be665c3SHenrik Bjoernlund br_cfm_mep_config_policy[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1] = {
252be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC] = { .type = NLA_REJECT },
262be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE] = { .type = NLA_U32 },
272be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = NLA_POLICY_ETH_ADDR,
282be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL] = NLA_POLICY_MAX(NLA_U32, 7),
292be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
302be665c3SHenrik Bjoernlund };
312be665c3SHenrik Bjoernlund
322be665c3SHenrik Bjoernlund static const struct nla_policy
332be665c3SHenrik Bjoernlund br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = {
342be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] = { .type = NLA_REJECT },
352be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] = { .type = NLA_U32 },
362be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] = { .type = NLA_U32 },
372be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 },
382be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID] = {
392be665c3SHenrik Bjoernlund .type = NLA_BINARY, .len = CFM_MAID_LENGTH },
402be665c3SHenrik Bjoernlund };
412be665c3SHenrik Bjoernlund
422be665c3SHenrik Bjoernlund static const struct nla_policy
432be665c3SHenrik Bjoernlund br_cfm_cc_peer_mep_policy[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1] = {
442be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC] = { .type = NLA_REJECT },
452be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE] = { .type = NLA_U32 },
462be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_PEER_MEPID] = NLA_POLICY_MAX(NLA_U32, 0x1FFF),
472be665c3SHenrik Bjoernlund };
482be665c3SHenrik Bjoernlund
492be665c3SHenrik Bjoernlund static const struct nla_policy
502be665c3SHenrik Bjoernlund br_cfm_cc_rdi_policy[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1] = {
512be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_RDI_UNSPEC] = { .type = NLA_REJECT },
522be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_RDI_INSTANCE] = { .type = NLA_U32 },
532be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_RDI_RDI] = { .type = NLA_U32 },
542be665c3SHenrik Bjoernlund };
552be665c3SHenrik Bjoernlund
562be665c3SHenrik Bjoernlund static const struct nla_policy
572be665c3SHenrik Bjoernlund br_cfm_cc_ccm_tx_policy[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1] = {
582be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC] = { .type = NLA_REJECT },
592be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE] = { .type = NLA_U32 },
602be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC] = NLA_POLICY_ETH_ADDR,
612be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE] = { .type = NLA_U32 },
622be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD] = { .type = NLA_U32 },
632be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV] = { .type = NLA_U32 },
642be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE] = { .type = NLA_U8 },
652be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV] = { .type = NLA_U32 },
662be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = { .type = NLA_U8 },
672be665c3SHenrik Bjoernlund };
682be665c3SHenrik Bjoernlund
692be665c3SHenrik Bjoernlund static const struct nla_policy
702be665c3SHenrik Bjoernlund br_cfm_policy[IFLA_BRIDGE_CFM_MAX + 1] = {
712be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_UNSPEC] = { .type = NLA_REJECT },
722be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CREATE] =
732be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_mep_create_policy),
742be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_DELETE] =
752be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_mep_delete_policy),
762be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_MEP_CONFIG] =
772be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_mep_config_policy),
782be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CONFIG] =
792be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_cc_config_policy),
802be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD] =
812be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
822be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE] =
832be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_cc_peer_mep_policy),
842be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_RDI] =
852be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_cc_rdi_policy),
862be665c3SHenrik Bjoernlund [IFLA_BRIDGE_CFM_CC_CCM_TX] =
872be665c3SHenrik Bjoernlund NLA_POLICY_NESTED(br_cfm_cc_ccm_tx_policy),
882be665c3SHenrik Bjoernlund };
892be665c3SHenrik Bjoernlund
br_mep_create_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)902be665c3SHenrik Bjoernlund static int br_mep_create_parse(struct net_bridge *br, struct nlattr *attr,
912be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
922be665c3SHenrik Bjoernlund {
932be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CREATE_MAX + 1];
942be665c3SHenrik Bjoernlund struct br_cfm_mep_create create;
952be665c3SHenrik Bjoernlund u32 instance;
962be665c3SHenrik Bjoernlund int err;
972be665c3SHenrik Bjoernlund
982be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CREATE_MAX, attr,
992be665c3SHenrik Bjoernlund br_cfm_mep_create_policy, extack);
1002be665c3SHenrik Bjoernlund if (err)
1012be665c3SHenrik Bjoernlund return err;
1022be665c3SHenrik Bjoernlund
1032be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]) {
1042be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
1052be665c3SHenrik Bjoernlund return -EINVAL;
1062be665c3SHenrik Bjoernlund }
1072be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]) {
1082be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing DOMAIN attribute");
1092be665c3SHenrik Bjoernlund return -EINVAL;
1102be665c3SHenrik Bjoernlund }
1112be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]) {
1122be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing DIRECTION attribute");
1132be665c3SHenrik Bjoernlund return -EINVAL;
1142be665c3SHenrik Bjoernlund }
1152be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]) {
1162be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing IFINDEX attribute");
1172be665c3SHenrik Bjoernlund return -EINVAL;
1182be665c3SHenrik Bjoernlund }
1192be665c3SHenrik Bjoernlund
1202be665c3SHenrik Bjoernlund memset(&create, 0, sizeof(create));
1212be665c3SHenrik Bjoernlund
1222be665c3SHenrik Bjoernlund instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]);
1232be665c3SHenrik Bjoernlund create.domain = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]);
1242be665c3SHenrik Bjoernlund create.direction = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]);
1252be665c3SHenrik Bjoernlund create.ifindex = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]);
1262be665c3SHenrik Bjoernlund
1272be665c3SHenrik Bjoernlund return br_cfm_mep_create(br, instance, &create, extack);
1282be665c3SHenrik Bjoernlund }
1292be665c3SHenrik Bjoernlund
br_mep_delete_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)1302be665c3SHenrik Bjoernlund static int br_mep_delete_parse(struct net_bridge *br, struct nlattr *attr,
1312be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
1322be665c3SHenrik Bjoernlund {
1332be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_DELETE_MAX + 1];
1342be665c3SHenrik Bjoernlund u32 instance;
1352be665c3SHenrik Bjoernlund int err;
1362be665c3SHenrik Bjoernlund
1372be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_DELETE_MAX, attr,
1382be665c3SHenrik Bjoernlund br_cfm_mep_delete_policy, extack);
1392be665c3SHenrik Bjoernlund if (err)
1402be665c3SHenrik Bjoernlund return err;
1412be665c3SHenrik Bjoernlund
1422be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]) {
1432be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack,
1442be665c3SHenrik Bjoernlund "Missing INSTANCE attribute");
1452be665c3SHenrik Bjoernlund return -EINVAL;
1462be665c3SHenrik Bjoernlund }
1472be665c3SHenrik Bjoernlund
1482be665c3SHenrik Bjoernlund instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]);
1492be665c3SHenrik Bjoernlund
1502be665c3SHenrik Bjoernlund return br_cfm_mep_delete(br, instance, extack);
1512be665c3SHenrik Bjoernlund }
1522be665c3SHenrik Bjoernlund
br_mep_config_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)1532be665c3SHenrik Bjoernlund static int br_mep_config_parse(struct net_bridge *br, struct nlattr *attr,
1542be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
1552be665c3SHenrik Bjoernlund {
1562be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MAX + 1];
1572be665c3SHenrik Bjoernlund struct br_cfm_mep_config config;
1582be665c3SHenrik Bjoernlund u32 instance;
1592be665c3SHenrik Bjoernlund int err;
1602be665c3SHenrik Bjoernlund
1612be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MEP_CONFIG_MAX, attr,
1622be665c3SHenrik Bjoernlund br_cfm_mep_config_policy, extack);
1632be665c3SHenrik Bjoernlund if (err)
1642be665c3SHenrik Bjoernlund return err;
1652be665c3SHenrik Bjoernlund
1662be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]) {
1672be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
1682be665c3SHenrik Bjoernlund return -EINVAL;
1692be665c3SHenrik Bjoernlund }
1702be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC]) {
1712be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing UNICAST_MAC attribute");
1722be665c3SHenrik Bjoernlund return -EINVAL;
1732be665c3SHenrik Bjoernlund }
1742be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]) {
1752be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing MDLEVEL attribute");
1762be665c3SHenrik Bjoernlund return -EINVAL;
1772be665c3SHenrik Bjoernlund }
1782be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]) {
1792be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing MEPID attribute");
1802be665c3SHenrik Bjoernlund return -EINVAL;
1812be665c3SHenrik Bjoernlund }
1822be665c3SHenrik Bjoernlund
1832be665c3SHenrik Bjoernlund memset(&config, 0, sizeof(config));
1842be665c3SHenrik Bjoernlund
1852be665c3SHenrik Bjoernlund instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]);
1862be665c3SHenrik Bjoernlund nla_memcpy(&config.unicast_mac.addr,
1872be665c3SHenrik Bjoernlund tb[IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC],
1882be665c3SHenrik Bjoernlund sizeof(config.unicast_mac.addr));
1892be665c3SHenrik Bjoernlund config.mdlevel = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]);
1902be665c3SHenrik Bjoernlund config.mepid = nla_get_u32(tb[IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]);
1912be665c3SHenrik Bjoernlund
1922be665c3SHenrik Bjoernlund return br_cfm_mep_config_set(br, instance, &config, extack);
1932be665c3SHenrik Bjoernlund }
1942be665c3SHenrik Bjoernlund
br_cc_config_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)1952be665c3SHenrik Bjoernlund static int br_cc_config_parse(struct net_bridge *br, struct nlattr *attr,
1962be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
1972be665c3SHenrik Bjoernlund {
1982be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1];
1992be665c3SHenrik Bjoernlund struct br_cfm_cc_config config;
2002be665c3SHenrik Bjoernlund u32 instance;
2012be665c3SHenrik Bjoernlund int err;
2022be665c3SHenrik Bjoernlund
2032be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CONFIG_MAX, attr,
2042be665c3SHenrik Bjoernlund br_cfm_cc_config_policy, extack);
2052be665c3SHenrik Bjoernlund if (err)
2062be665c3SHenrik Bjoernlund return err;
2072be665c3SHenrik Bjoernlund
2082be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]) {
2092be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
2102be665c3SHenrik Bjoernlund return -EINVAL;
2112be665c3SHenrik Bjoernlund }
2122be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]) {
2132be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing ENABLE attribute");
2142be665c3SHenrik Bjoernlund return -EINVAL;
2152be665c3SHenrik Bjoernlund }
2162be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]) {
2172be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INTERVAL attribute");
2182be665c3SHenrik Bjoernlund return -EINVAL;
2192be665c3SHenrik Bjoernlund }
2202be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]) {
2212be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing MAID attribute");
2222be665c3SHenrik Bjoernlund return -EINVAL;
2232be665c3SHenrik Bjoernlund }
2242be665c3SHenrik Bjoernlund
2252be665c3SHenrik Bjoernlund memset(&config, 0, sizeof(config));
2262be665c3SHenrik Bjoernlund
2272be665c3SHenrik Bjoernlund instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]);
2282be665c3SHenrik Bjoernlund config.enable = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]);
2292be665c3SHenrik Bjoernlund config.exp_interval = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL]);
2302be665c3SHenrik Bjoernlund nla_memcpy(&config.exp_maid.data, tb[IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID],
2312be665c3SHenrik Bjoernlund sizeof(config.exp_maid.data));
2322be665c3SHenrik Bjoernlund
2332be665c3SHenrik Bjoernlund return br_cfm_cc_config_set(br, instance, &config, extack);
2342be665c3SHenrik Bjoernlund }
2352be665c3SHenrik Bjoernlund
br_cc_peer_mep_add_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2362be665c3SHenrik Bjoernlund static int br_cc_peer_mep_add_parse(struct net_bridge *br, struct nlattr *attr,
2372be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
2382be665c3SHenrik Bjoernlund {
2392be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
2402be665c3SHenrik Bjoernlund u32 instance, peer_mep_id;
2412be665c3SHenrik Bjoernlund int err;
2422be665c3SHenrik Bjoernlund
2432be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
2442be665c3SHenrik Bjoernlund br_cfm_cc_peer_mep_policy, extack);
2452be665c3SHenrik Bjoernlund if (err)
2462be665c3SHenrik Bjoernlund return err;
2472be665c3SHenrik Bjoernlund
2482be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
2492be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
2502be665c3SHenrik Bjoernlund return -EINVAL;
2512be665c3SHenrik Bjoernlund }
2522be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
2532be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
2542be665c3SHenrik Bjoernlund return -EINVAL;
2552be665c3SHenrik Bjoernlund }
2562be665c3SHenrik Bjoernlund
2572be665c3SHenrik Bjoernlund instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
2582be665c3SHenrik Bjoernlund peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
2592be665c3SHenrik Bjoernlund
2602be665c3SHenrik Bjoernlund return br_cfm_cc_peer_mep_add(br, instance, peer_mep_id, extack);
2612be665c3SHenrik Bjoernlund }
2622be665c3SHenrik Bjoernlund
br_cc_peer_mep_remove_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2632be665c3SHenrik Bjoernlund static int br_cc_peer_mep_remove_parse(struct net_bridge *br, struct nlattr *attr,
2642be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
2652be665c3SHenrik Bjoernlund {
2662be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX + 1];
2672be665c3SHenrik Bjoernlund u32 instance, peer_mep_id;
2682be665c3SHenrik Bjoernlund int err;
2692be665c3SHenrik Bjoernlund
2702be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX, attr,
2712be665c3SHenrik Bjoernlund br_cfm_cc_peer_mep_policy, extack);
2722be665c3SHenrik Bjoernlund if (err)
2732be665c3SHenrik Bjoernlund return err;
2742be665c3SHenrik Bjoernlund
2752be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]) {
2762be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
2772be665c3SHenrik Bjoernlund return -EINVAL;
2782be665c3SHenrik Bjoernlund }
2792be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]) {
2802be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing PEER_MEP_ID attribute");
2812be665c3SHenrik Bjoernlund return -EINVAL;
2822be665c3SHenrik Bjoernlund }
2832be665c3SHenrik Bjoernlund
2842be665c3SHenrik Bjoernlund instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]);
2852be665c3SHenrik Bjoernlund peer_mep_id = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_PEER_MEPID]);
2862be665c3SHenrik Bjoernlund
2872be665c3SHenrik Bjoernlund return br_cfm_cc_peer_mep_remove(br, instance, peer_mep_id, extack);
2882be665c3SHenrik Bjoernlund }
2892be665c3SHenrik Bjoernlund
br_cc_rdi_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2902be665c3SHenrik Bjoernlund static int br_cc_rdi_parse(struct net_bridge *br, struct nlattr *attr,
2912be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
2922be665c3SHenrik Bjoernlund {
2932be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_CC_RDI_MAX + 1];
2942be665c3SHenrik Bjoernlund u32 instance, rdi;
2952be665c3SHenrik Bjoernlund int err;
2962be665c3SHenrik Bjoernlund
2972be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_RDI_MAX, attr,
2982be665c3SHenrik Bjoernlund br_cfm_cc_rdi_policy, extack);
2992be665c3SHenrik Bjoernlund if (err)
3002be665c3SHenrik Bjoernlund return err;
3012be665c3SHenrik Bjoernlund
3022be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]) {
3032be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
3042be665c3SHenrik Bjoernlund return -EINVAL;
3052be665c3SHenrik Bjoernlund }
3062be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]) {
3072be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing RDI attribute");
3082be665c3SHenrik Bjoernlund return -EINVAL;
3092be665c3SHenrik Bjoernlund }
3102be665c3SHenrik Bjoernlund
3112be665c3SHenrik Bjoernlund instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]);
3122be665c3SHenrik Bjoernlund rdi = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_RDI_RDI]);
3132be665c3SHenrik Bjoernlund
3142be665c3SHenrik Bjoernlund return br_cfm_cc_rdi_set(br, instance, rdi, extack);
3152be665c3SHenrik Bjoernlund }
3162be665c3SHenrik Bjoernlund
br_cc_ccm_tx_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)3172be665c3SHenrik Bjoernlund static int br_cc_ccm_tx_parse(struct net_bridge *br, struct nlattr *attr,
3182be665c3SHenrik Bjoernlund struct netlink_ext_ack *extack)
3192be665c3SHenrik Bjoernlund {
3202be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_CC_CCM_TX_MAX + 1];
3212be665c3SHenrik Bjoernlund struct br_cfm_cc_ccm_tx_info tx_info;
3222be665c3SHenrik Bjoernlund u32 instance;
3232be665c3SHenrik Bjoernlund int err;
3242be665c3SHenrik Bjoernlund
3252be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_CC_CCM_TX_MAX, attr,
3262be665c3SHenrik Bjoernlund br_cfm_cc_ccm_tx_policy, extack);
3272be665c3SHenrik Bjoernlund if (err)
3282be665c3SHenrik Bjoernlund return err;
3292be665c3SHenrik Bjoernlund
3302be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]) {
3312be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing INSTANCE attribute");
3322be665c3SHenrik Bjoernlund return -EINVAL;
3332be665c3SHenrik Bjoernlund }
3342be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]) {
3352be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing DMAC attribute");
3362be665c3SHenrik Bjoernlund return -EINVAL;
3372be665c3SHenrik Bjoernlund }
3382be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]) {
3392be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing SEQ_NO_UPDATE attribute");
3402be665c3SHenrik Bjoernlund return -EINVAL;
3412be665c3SHenrik Bjoernlund }
3422be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]) {
3432be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing PERIOD attribute");
3442be665c3SHenrik Bjoernlund return -EINVAL;
3452be665c3SHenrik Bjoernlund }
3462be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]) {
3472be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV attribute");
3482be665c3SHenrik Bjoernlund return -EINVAL;
3492be665c3SHenrik Bjoernlund }
3502be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]) {
3512be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing IF_TLV_VALUE attribute");
3522be665c3SHenrik Bjoernlund return -EINVAL;
3532be665c3SHenrik Bjoernlund }
3542be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]) {
3552be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV attribute");
3562be665c3SHenrik Bjoernlund return -EINVAL;
3572be665c3SHenrik Bjoernlund }
3582be665c3SHenrik Bjoernlund if (!tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]) {
3592be665c3SHenrik Bjoernlund NL_SET_ERR_MSG_MOD(extack, "Missing PORT_TLV_VALUE attribute");
3602be665c3SHenrik Bjoernlund return -EINVAL;
3612be665c3SHenrik Bjoernlund }
3622be665c3SHenrik Bjoernlund
3632be665c3SHenrik Bjoernlund memset(&tx_info, 0, sizeof(tx_info));
3642be665c3SHenrik Bjoernlund
365*daa24d20SLin Ma instance = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]);
3662be665c3SHenrik Bjoernlund nla_memcpy(&tx_info.dmac.addr,
3672be665c3SHenrik Bjoernlund tb[IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC],
3682be665c3SHenrik Bjoernlund sizeof(tx_info.dmac.addr));
3692be665c3SHenrik Bjoernlund tx_info.seq_no_update = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]);
3702be665c3SHenrik Bjoernlund tx_info.period = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]);
3712be665c3SHenrik Bjoernlund tx_info.if_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]);
3722be665c3SHenrik Bjoernlund tx_info.if_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]);
3732be665c3SHenrik Bjoernlund tx_info.port_tlv = nla_get_u32(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]);
3742be665c3SHenrik Bjoernlund tx_info.port_tlv_value = nla_get_u8(tb[IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE]);
3752be665c3SHenrik Bjoernlund
3762be665c3SHenrik Bjoernlund return br_cfm_cc_ccm_tx(br, instance, &tx_info, extack);
3772be665c3SHenrik Bjoernlund }
3782be665c3SHenrik Bjoernlund
br_cfm_parse(struct net_bridge * br,struct net_bridge_port * p,struct nlattr * attr,int cmd,struct netlink_ext_ack * extack)3792be665c3SHenrik Bjoernlund int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p,
3802be665c3SHenrik Bjoernlund struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
3812be665c3SHenrik Bjoernlund {
3822be665c3SHenrik Bjoernlund struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1];
3832be665c3SHenrik Bjoernlund int err;
3842be665c3SHenrik Bjoernlund
3852be665c3SHenrik Bjoernlund /* When this function is called for a port then the br pointer is
3862be665c3SHenrik Bjoernlund * invalid, therefor set the br to point correctly
3872be665c3SHenrik Bjoernlund */
3882be665c3SHenrik Bjoernlund if (p)
3892be665c3SHenrik Bjoernlund br = p->br;
3902be665c3SHenrik Bjoernlund
3912be665c3SHenrik Bjoernlund err = nla_parse_nested(tb, IFLA_BRIDGE_CFM_MAX, attr,
3922be665c3SHenrik Bjoernlund br_cfm_policy, extack);
3932be665c3SHenrik Bjoernlund if (err)
3942be665c3SHenrik Bjoernlund return err;
3952be665c3SHenrik Bjoernlund
3962be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_MEP_CREATE]) {
3972be665c3SHenrik Bjoernlund err = br_mep_create_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CREATE],
3982be665c3SHenrik Bjoernlund extack);
3992be665c3SHenrik Bjoernlund if (err)
4002be665c3SHenrik Bjoernlund return err;
4012be665c3SHenrik Bjoernlund }
4022be665c3SHenrik Bjoernlund
4032be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) {
4042be665c3SHenrik Bjoernlund err = br_mep_delete_parse(br, tb[IFLA_BRIDGE_CFM_MEP_DELETE],
4052be665c3SHenrik Bjoernlund extack);
4062be665c3SHenrik Bjoernlund if (err)
4072be665c3SHenrik Bjoernlund return err;
4082be665c3SHenrik Bjoernlund }
4092be665c3SHenrik Bjoernlund
4102be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) {
4112be665c3SHenrik Bjoernlund err = br_mep_config_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CONFIG],
4122be665c3SHenrik Bjoernlund extack);
4132be665c3SHenrik Bjoernlund if (err)
4142be665c3SHenrik Bjoernlund return err;
4152be665c3SHenrik Bjoernlund }
4162be665c3SHenrik Bjoernlund
4172be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) {
4182be665c3SHenrik Bjoernlund err = br_cc_config_parse(br, tb[IFLA_BRIDGE_CFM_CC_CONFIG],
4192be665c3SHenrik Bjoernlund extack);
4202be665c3SHenrik Bjoernlund if (err)
4212be665c3SHenrik Bjoernlund return err;
4222be665c3SHenrik Bjoernlund }
4232be665c3SHenrik Bjoernlund
4242be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]) {
4252be665c3SHenrik Bjoernlund err = br_cc_peer_mep_add_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD],
4262be665c3SHenrik Bjoernlund extack);
4272be665c3SHenrik Bjoernlund if (err)
4282be665c3SHenrik Bjoernlund return err;
4292be665c3SHenrik Bjoernlund }
4302be665c3SHenrik Bjoernlund
4312be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]) {
4322be665c3SHenrik Bjoernlund err = br_cc_peer_mep_remove_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE],
4332be665c3SHenrik Bjoernlund extack);
4342be665c3SHenrik Bjoernlund if (err)
4352be665c3SHenrik Bjoernlund return err;
4362be665c3SHenrik Bjoernlund }
4372be665c3SHenrik Bjoernlund
4382be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_CC_RDI]) {
4392be665c3SHenrik Bjoernlund err = br_cc_rdi_parse(br, tb[IFLA_BRIDGE_CFM_CC_RDI],
4402be665c3SHenrik Bjoernlund extack);
4412be665c3SHenrik Bjoernlund if (err)
4422be665c3SHenrik Bjoernlund return err;
4432be665c3SHenrik Bjoernlund }
4442be665c3SHenrik Bjoernlund
4452be665c3SHenrik Bjoernlund if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) {
4462be665c3SHenrik Bjoernlund err = br_cc_ccm_tx_parse(br, tb[IFLA_BRIDGE_CFM_CC_CCM_TX],
4472be665c3SHenrik Bjoernlund extack);
4482be665c3SHenrik Bjoernlund if (err)
4492be665c3SHenrik Bjoernlund return err;
4502be665c3SHenrik Bjoernlund }
4512be665c3SHenrik Bjoernlund
4522be665c3SHenrik Bjoernlund return 0;
4532be665c3SHenrik Bjoernlund }
4545e312fc0SHenrik Bjoernlund
br_cfm_config_fill_info(struct sk_buff * skb,struct net_bridge * br)4555e312fc0SHenrik Bjoernlund int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
4565e312fc0SHenrik Bjoernlund {
4575e312fc0SHenrik Bjoernlund struct br_cfm_peer_mep *peer_mep;
4585e312fc0SHenrik Bjoernlund struct br_cfm_mep *mep;
4595e312fc0SHenrik Bjoernlund struct nlattr *tb;
4605e312fc0SHenrik Bjoernlund
4615e312fc0SHenrik Bjoernlund hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
4625e312fc0SHenrik Bjoernlund tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INFO);
4635e312fc0SHenrik Bjoernlund if (!tb)
4645e312fc0SHenrik Bjoernlund goto nla_info_failure;
4655e312fc0SHenrik Bjoernlund
4665e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE,
4675e312fc0SHenrik Bjoernlund mep->instance))
4685e312fc0SHenrik Bjoernlund goto nla_put_failure;
4695e312fc0SHenrik Bjoernlund
4705e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN,
4715e312fc0SHenrik Bjoernlund mep->create.domain))
4725e312fc0SHenrik Bjoernlund goto nla_put_failure;
4735e312fc0SHenrik Bjoernlund
4745e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION,
4755e312fc0SHenrik Bjoernlund mep->create.direction))
4765e312fc0SHenrik Bjoernlund goto nla_put_failure;
4775e312fc0SHenrik Bjoernlund
4785e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX,
4795e312fc0SHenrik Bjoernlund mep->create.ifindex))
4805e312fc0SHenrik Bjoernlund goto nla_put_failure;
4815e312fc0SHenrik Bjoernlund
4825e312fc0SHenrik Bjoernlund nla_nest_end(skb, tb);
4835e312fc0SHenrik Bjoernlund
4845e312fc0SHenrik Bjoernlund tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INFO);
4855e312fc0SHenrik Bjoernlund
4865e312fc0SHenrik Bjoernlund if (!tb)
4875e312fc0SHenrik Bjoernlund goto nla_info_failure;
4885e312fc0SHenrik Bjoernlund
4895e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE,
4905e312fc0SHenrik Bjoernlund mep->instance))
4915e312fc0SHenrik Bjoernlund goto nla_put_failure;
4925e312fc0SHenrik Bjoernlund
4935e312fc0SHenrik Bjoernlund if (nla_put(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC,
4945e312fc0SHenrik Bjoernlund sizeof(mep->config.unicast_mac.addr),
4955e312fc0SHenrik Bjoernlund mep->config.unicast_mac.addr))
4965e312fc0SHenrik Bjoernlund goto nla_put_failure;
4975e312fc0SHenrik Bjoernlund
4985e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL,
4995e312fc0SHenrik Bjoernlund mep->config.mdlevel))
5005e312fc0SHenrik Bjoernlund goto nla_put_failure;
5015e312fc0SHenrik Bjoernlund
5025e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID,
5035e312fc0SHenrik Bjoernlund mep->config.mepid))
5045e312fc0SHenrik Bjoernlund goto nla_put_failure;
5055e312fc0SHenrik Bjoernlund
5065e312fc0SHenrik Bjoernlund nla_nest_end(skb, tb);
5075e312fc0SHenrik Bjoernlund
5085e312fc0SHenrik Bjoernlund tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INFO);
5095e312fc0SHenrik Bjoernlund
5105e312fc0SHenrik Bjoernlund if (!tb)
5115e312fc0SHenrik Bjoernlund goto nla_info_failure;
5125e312fc0SHenrik Bjoernlund
5135e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE,
5145e312fc0SHenrik Bjoernlund mep->instance))
5155e312fc0SHenrik Bjoernlund goto nla_put_failure;
5165e312fc0SHenrik Bjoernlund
5175e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE,
5185e312fc0SHenrik Bjoernlund mep->cc_config.enable))
5195e312fc0SHenrik Bjoernlund goto nla_put_failure;
5205e312fc0SHenrik Bjoernlund
5215e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL,
5225e312fc0SHenrik Bjoernlund mep->cc_config.exp_interval))
5235e312fc0SHenrik Bjoernlund goto nla_put_failure;
5245e312fc0SHenrik Bjoernlund
5255e312fc0SHenrik Bjoernlund if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID,
5265e312fc0SHenrik Bjoernlund sizeof(mep->cc_config.exp_maid.data),
5275e312fc0SHenrik Bjoernlund mep->cc_config.exp_maid.data))
5285e312fc0SHenrik Bjoernlund goto nla_put_failure;
5295e312fc0SHenrik Bjoernlund
5305e312fc0SHenrik Bjoernlund nla_nest_end(skb, tb);
5315e312fc0SHenrik Bjoernlund
5325e312fc0SHenrik Bjoernlund tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_RDI_INFO);
5335e312fc0SHenrik Bjoernlund
5345e312fc0SHenrik Bjoernlund if (!tb)
5355e312fc0SHenrik Bjoernlund goto nla_info_failure;
5365e312fc0SHenrik Bjoernlund
5375e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_INSTANCE,
5385e312fc0SHenrik Bjoernlund mep->instance))
5395e312fc0SHenrik Bjoernlund goto nla_put_failure;
5405e312fc0SHenrik Bjoernlund
5415e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_RDI_RDI,
5425e312fc0SHenrik Bjoernlund mep->rdi))
5435e312fc0SHenrik Bjoernlund goto nla_put_failure;
5445e312fc0SHenrik Bjoernlund
5455e312fc0SHenrik Bjoernlund nla_nest_end(skb, tb);
5465e312fc0SHenrik Bjoernlund
5475e312fc0SHenrik Bjoernlund tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INFO);
5485e312fc0SHenrik Bjoernlund
5495e312fc0SHenrik Bjoernlund if (!tb)
5505e312fc0SHenrik Bjoernlund goto nla_info_failure;
5515e312fc0SHenrik Bjoernlund
5525e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE,
5535e312fc0SHenrik Bjoernlund mep->instance))
5545e312fc0SHenrik Bjoernlund goto nla_put_failure;
5555e312fc0SHenrik Bjoernlund
5565e312fc0SHenrik Bjoernlund if (nla_put(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC,
5575e312fc0SHenrik Bjoernlund sizeof(mep->cc_ccm_tx_info.dmac),
5585e312fc0SHenrik Bjoernlund mep->cc_ccm_tx_info.dmac.addr))
5595e312fc0SHenrik Bjoernlund goto nla_put_failure;
5605e312fc0SHenrik Bjoernlund
5615e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE,
5625e312fc0SHenrik Bjoernlund mep->cc_ccm_tx_info.seq_no_update))
5635e312fc0SHenrik Bjoernlund goto nla_put_failure;
5645e312fc0SHenrik Bjoernlund
5655e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD,
5665e312fc0SHenrik Bjoernlund mep->cc_ccm_tx_info.period))
5675e312fc0SHenrik Bjoernlund goto nla_put_failure;
5685e312fc0SHenrik Bjoernlund
5695e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV,
5705e312fc0SHenrik Bjoernlund mep->cc_ccm_tx_info.if_tlv))
5715e312fc0SHenrik Bjoernlund goto nla_put_failure;
5725e312fc0SHenrik Bjoernlund
5735e312fc0SHenrik Bjoernlund if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE,
5745e312fc0SHenrik Bjoernlund mep->cc_ccm_tx_info.if_tlv_value))
5755e312fc0SHenrik Bjoernlund goto nla_put_failure;
5765e312fc0SHenrik Bjoernlund
5775e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV,
5785e312fc0SHenrik Bjoernlund mep->cc_ccm_tx_info.port_tlv))
5795e312fc0SHenrik Bjoernlund goto nla_put_failure;
5805e312fc0SHenrik Bjoernlund
5815e312fc0SHenrik Bjoernlund if (nla_put_u8(skb, IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE,
5825e312fc0SHenrik Bjoernlund mep->cc_ccm_tx_info.port_tlv_value))
5835e312fc0SHenrik Bjoernlund goto nla_put_failure;
5845e312fc0SHenrik Bjoernlund
5855e312fc0SHenrik Bjoernlund nla_nest_end(skb, tb);
5865e312fc0SHenrik Bjoernlund
5875e312fc0SHenrik Bjoernlund hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
5885e312fc0SHenrik Bjoernlund tb = nla_nest_start(skb,
5895e312fc0SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO);
5905e312fc0SHenrik Bjoernlund
5915e312fc0SHenrik Bjoernlund if (!tb)
5925e312fc0SHenrik Bjoernlund goto nla_info_failure;
5935e312fc0SHenrik Bjoernlund
5945e312fc0SHenrik Bjoernlund if (nla_put_u32(skb,
5955e312fc0SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE,
5965e312fc0SHenrik Bjoernlund mep->instance))
5975e312fc0SHenrik Bjoernlund goto nla_put_failure;
5985e312fc0SHenrik Bjoernlund
5995e312fc0SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_MEPID,
6005e312fc0SHenrik Bjoernlund peer_mep->mepid))
6015e312fc0SHenrik Bjoernlund goto nla_put_failure;
6025e312fc0SHenrik Bjoernlund
6035e312fc0SHenrik Bjoernlund nla_nest_end(skb, tb);
6045e312fc0SHenrik Bjoernlund }
6055e312fc0SHenrik Bjoernlund }
6065e312fc0SHenrik Bjoernlund
6075e312fc0SHenrik Bjoernlund return 0;
6085e312fc0SHenrik Bjoernlund
6095e312fc0SHenrik Bjoernlund nla_put_failure:
6105e312fc0SHenrik Bjoernlund nla_nest_cancel(skb, tb);
6115e312fc0SHenrik Bjoernlund
6125e312fc0SHenrik Bjoernlund nla_info_failure:
6135e312fc0SHenrik Bjoernlund return -EMSGSIZE;
6145e312fc0SHenrik Bjoernlund }
615e77824d8SHenrik Bjoernlund
br_cfm_status_fill_info(struct sk_buff * skb,struct net_bridge * br,bool getlink)616b6d0425bSHenrik Bjoernlund int br_cfm_status_fill_info(struct sk_buff *skb,
617b6d0425bSHenrik Bjoernlund struct net_bridge *br,
618b6d0425bSHenrik Bjoernlund bool getlink)
619e77824d8SHenrik Bjoernlund {
620e77824d8SHenrik Bjoernlund struct br_cfm_peer_mep *peer_mep;
621e77824d8SHenrik Bjoernlund struct br_cfm_mep *mep;
622e77824d8SHenrik Bjoernlund struct nlattr *tb;
623e77824d8SHenrik Bjoernlund
624e77824d8SHenrik Bjoernlund hlist_for_each_entry_rcu(mep, &br->mep_list, head) {
625e77824d8SHenrik Bjoernlund tb = nla_nest_start(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INFO);
626e77824d8SHenrik Bjoernlund if (!tb)
627e77824d8SHenrik Bjoernlund goto nla_info_failure;
628e77824d8SHenrik Bjoernlund
629e77824d8SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE,
630e77824d8SHenrik Bjoernlund mep->instance))
631e77824d8SHenrik Bjoernlund goto nla_put_failure;
632e77824d8SHenrik Bjoernlund
633e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
634e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN,
635e77824d8SHenrik Bjoernlund mep->status.opcode_unexp_seen))
636e77824d8SHenrik Bjoernlund goto nla_put_failure;
637e77824d8SHenrik Bjoernlund
638e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
639e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN,
640e77824d8SHenrik Bjoernlund mep->status.version_unexp_seen))
641e77824d8SHenrik Bjoernlund goto nla_put_failure;
642e77824d8SHenrik Bjoernlund
643e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
644e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN,
645e77824d8SHenrik Bjoernlund mep->status.rx_level_low_seen))
646e77824d8SHenrik Bjoernlund goto nla_put_failure;
647e77824d8SHenrik Bjoernlund
648b6d0425bSHenrik Bjoernlund /* Only clear if this is a GETLINK */
649b6d0425bSHenrik Bjoernlund if (getlink) {
650e77824d8SHenrik Bjoernlund /* Clear all 'seen' indications */
651e77824d8SHenrik Bjoernlund mep->status.opcode_unexp_seen = false;
652e77824d8SHenrik Bjoernlund mep->status.version_unexp_seen = false;
653e77824d8SHenrik Bjoernlund mep->status.rx_level_low_seen = false;
654b6d0425bSHenrik Bjoernlund }
655e77824d8SHenrik Bjoernlund
656e77824d8SHenrik Bjoernlund nla_nest_end(skb, tb);
657e77824d8SHenrik Bjoernlund
658e77824d8SHenrik Bjoernlund hlist_for_each_entry_rcu(peer_mep, &mep->peer_mep_list, head) {
659e77824d8SHenrik Bjoernlund tb = nla_nest_start(skb,
660e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO);
661e77824d8SHenrik Bjoernlund if (!tb)
662e77824d8SHenrik Bjoernlund goto nla_info_failure;
663e77824d8SHenrik Bjoernlund
664e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
665e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE,
666e77824d8SHenrik Bjoernlund mep->instance))
667e77824d8SHenrik Bjoernlund goto nla_put_failure;
668e77824d8SHenrik Bjoernlund
669e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
670e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID,
671e77824d8SHenrik Bjoernlund peer_mep->mepid))
672e77824d8SHenrik Bjoernlund goto nla_put_failure;
673e77824d8SHenrik Bjoernlund
674e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
675e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT,
676e77824d8SHenrik Bjoernlund peer_mep->cc_status.ccm_defect))
677e77824d8SHenrik Bjoernlund goto nla_put_failure;
678e77824d8SHenrik Bjoernlund
679e77824d8SHenrik Bjoernlund if (nla_put_u32(skb, IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI,
680e77824d8SHenrik Bjoernlund peer_mep->cc_status.rdi))
681e77824d8SHenrik Bjoernlund goto nla_put_failure;
682e77824d8SHenrik Bjoernlund
683e77824d8SHenrik Bjoernlund if (nla_put_u8(skb,
684e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE,
685e77824d8SHenrik Bjoernlund peer_mep->cc_status.port_tlv_value))
686e77824d8SHenrik Bjoernlund goto nla_put_failure;
687e77824d8SHenrik Bjoernlund
688e77824d8SHenrik Bjoernlund if (nla_put_u8(skb,
689e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE,
690e77824d8SHenrik Bjoernlund peer_mep->cc_status.if_tlv_value))
691e77824d8SHenrik Bjoernlund goto nla_put_failure;
692e77824d8SHenrik Bjoernlund
693e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
694e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN,
695e77824d8SHenrik Bjoernlund peer_mep->cc_status.seen))
696e77824d8SHenrik Bjoernlund goto nla_put_failure;
697e77824d8SHenrik Bjoernlund
698e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
699e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN,
700e77824d8SHenrik Bjoernlund peer_mep->cc_status.tlv_seen))
701e77824d8SHenrik Bjoernlund goto nla_put_failure;
702e77824d8SHenrik Bjoernlund
703e77824d8SHenrik Bjoernlund if (nla_put_u32(skb,
704e77824d8SHenrik Bjoernlund IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN,
705e77824d8SHenrik Bjoernlund peer_mep->cc_status.seq_unexp_seen))
706e77824d8SHenrik Bjoernlund goto nla_put_failure;
707e77824d8SHenrik Bjoernlund
708b6d0425bSHenrik Bjoernlund if (getlink) { /* Only clear if this is a GETLINK */
709e77824d8SHenrik Bjoernlund /* Clear all 'seen' indications */
710e77824d8SHenrik Bjoernlund peer_mep->cc_status.seen = false;
711e77824d8SHenrik Bjoernlund peer_mep->cc_status.tlv_seen = false;
712e77824d8SHenrik Bjoernlund peer_mep->cc_status.seq_unexp_seen = false;
713b6d0425bSHenrik Bjoernlund }
714e77824d8SHenrik Bjoernlund
715e77824d8SHenrik Bjoernlund nla_nest_end(skb, tb);
716e77824d8SHenrik Bjoernlund }
717e77824d8SHenrik Bjoernlund }
718e77824d8SHenrik Bjoernlund
719e77824d8SHenrik Bjoernlund return 0;
720e77824d8SHenrik Bjoernlund
721e77824d8SHenrik Bjoernlund nla_put_failure:
722e77824d8SHenrik Bjoernlund nla_nest_cancel(skb, tb);
723e77824d8SHenrik Bjoernlund
724e77824d8SHenrik Bjoernlund nla_info_failure:
725e77824d8SHenrik Bjoernlund return -EMSGSIZE;
726e77824d8SHenrik Bjoernlund }
727