1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <net/genetlink.h> 4 5 #include <uapi/linux/mrp_bridge.h> 6 #include "br_private.h" 7 #include "br_private_mrp.h" 8 9 static const struct nla_policy br_mrp_policy[IFLA_BRIDGE_MRP_MAX + 1] = { 10 [IFLA_BRIDGE_MRP_UNSPEC] = { .type = NLA_REJECT }, 11 [IFLA_BRIDGE_MRP_INSTANCE] = { .type = NLA_EXACT_LEN, 12 .len = sizeof(struct br_mrp_instance)}, 13 [IFLA_BRIDGE_MRP_PORT_STATE] = { .type = NLA_U32 }, 14 [IFLA_BRIDGE_MRP_PORT_ROLE] = { .type = NLA_EXACT_LEN, 15 .len = sizeof(struct br_mrp_port_role)}, 16 [IFLA_BRIDGE_MRP_RING_STATE] = { .type = NLA_EXACT_LEN, 17 .len = sizeof(struct br_mrp_ring_state)}, 18 [IFLA_BRIDGE_MRP_RING_ROLE] = { .type = NLA_EXACT_LEN, 19 .len = sizeof(struct br_mrp_ring_role)}, 20 [IFLA_BRIDGE_MRP_START_TEST] = { .type = NLA_EXACT_LEN, 21 .len = sizeof(struct br_mrp_start_test)}, 22 }; 23 24 int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, 25 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack) 26 { 27 struct nlattr *tb[IFLA_BRIDGE_MRP_MAX + 1]; 28 int err; 29 30 if (br->stp_enabled != BR_NO_STP) { 31 NL_SET_ERR_MSG_MOD(extack, "MRP can't be enabled if STP is already enabled\n"); 32 return -EINVAL; 33 } 34 35 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_MAX, attr, 36 br_mrp_policy, extack); 37 if (err) 38 return err; 39 40 if (tb[IFLA_BRIDGE_MRP_INSTANCE]) { 41 struct br_mrp_instance *instance = 42 nla_data(tb[IFLA_BRIDGE_MRP_INSTANCE]); 43 44 if (cmd == RTM_SETLINK) 45 err = br_mrp_add(br, instance); 46 else 47 err = br_mrp_del(br, instance); 48 if (err) 49 return err; 50 } 51 52 if (tb[IFLA_BRIDGE_MRP_PORT_STATE]) { 53 enum br_mrp_port_state_type state = 54 nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_STATE]); 55 56 err = br_mrp_set_port_state(p, state); 57 if (err) 58 return err; 59 } 60 61 if (tb[IFLA_BRIDGE_MRP_PORT_ROLE]) { 62 struct br_mrp_port_role *role = 63 nla_data(tb[IFLA_BRIDGE_MRP_PORT_ROLE]); 64 65 err = br_mrp_set_port_role(p, role); 66 if (err) 67 return err; 68 } 69 70 if (tb[IFLA_BRIDGE_MRP_RING_STATE]) { 71 struct br_mrp_ring_state *state = 72 nla_data(tb[IFLA_BRIDGE_MRP_RING_STATE]); 73 74 err = br_mrp_set_ring_state(br, state); 75 if (err) 76 return err; 77 } 78 79 if (tb[IFLA_BRIDGE_MRP_RING_ROLE]) { 80 struct br_mrp_ring_role *role = 81 nla_data(tb[IFLA_BRIDGE_MRP_RING_ROLE]); 82 83 err = br_mrp_set_ring_role(br, role); 84 if (err) 85 return err; 86 } 87 88 if (tb[IFLA_BRIDGE_MRP_START_TEST]) { 89 struct br_mrp_start_test *test = 90 nla_data(tb[IFLA_BRIDGE_MRP_START_TEST]); 91 92 err = br_mrp_start_test(br, test); 93 if (err) 94 return err; 95 } 96 97 return 0; 98 } 99 100 int br_mrp_port_open(struct net_device *dev, u8 loc) 101 { 102 struct net_bridge_port *p; 103 int err = 0; 104 105 p = br_port_get_rcu(dev); 106 if (!p) { 107 err = -EINVAL; 108 goto out; 109 } 110 111 if (loc) 112 p->flags |= BR_MRP_LOST_CONT; 113 else 114 p->flags &= ~BR_MRP_LOST_CONT; 115 116 br_ifinfo_notify(RTM_NEWLINK, NULL, p); 117 118 out: 119 return err; 120 } 121