aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2012-06-19 01:54:08 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-19 18:00:23 -0400
commitb13033262d2496e271444d5a09226a2be5ceb989 (patch)
treec5a78a0023f3c28425e7425a91c6fd2ac71d29d9 /drivers
parentf82b959d26557fe4ce283d3b27050d4b8268ef1e (diff)
team: introduce array options
Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/team/team.c75
1 files changed, 52 insertions, 23 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index f50b8ca8dc94..32cb290fb800 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -90,6 +90,7 @@ struct team_option_inst { /* One for each option instance */
90 struct list_head list; 90 struct list_head list;
91 struct team_option *option; 91 struct team_option *option;
92 struct team_port *port; /* != NULL if per-port */ 92 struct team_port *port; /* != NULL if per-port */
93 u32 array_index;
93 bool changed; 94 bool changed;
94 bool removed; 95 bool removed;
95}; 96};
@@ -106,22 +107,6 @@ static struct team_option *__team_find_option(struct team *team,
106 return NULL; 107 return NULL;
107} 108}
108 109
109static int __team_option_inst_add(struct team *team, struct team_option *option,
110 struct team_port *port)
111{
112 struct team_option_inst *opt_inst;
113
114 opt_inst = kmalloc(sizeof(*opt_inst), GFP_KERNEL);
115 if (!opt_inst)
116 return -ENOMEM;
117 opt_inst->option = option;
118 opt_inst->port = port;
119 opt_inst->changed = true;
120 opt_inst->removed = false;
121 list_add_tail(&opt_inst->list, &team->option_inst_list);
122 return 0;
123}
124
125static void __team_option_inst_del(struct team_option_inst *opt_inst) 110static void __team_option_inst_del(struct team_option_inst *opt_inst)
126{ 111{
127 list_del(&opt_inst->list); 112 list_del(&opt_inst->list);
@@ -139,14 +124,42 @@ static void __team_option_inst_del_option(struct team *team,
139 } 124 }
140} 125}
141 126
127static int __team_option_inst_add(struct team *team, struct team_option *option,
128 struct team_port *port)
129{
130 struct team_option_inst *opt_inst;
131 unsigned int array_size;
132 unsigned int i;
133
134 array_size = option->array_size;
135 if (!array_size)
136 array_size = 1; /* No array but still need one instance */
137
138 for (i = 0; i < array_size; i++) {
139 opt_inst = kmalloc(sizeof(*opt_inst), GFP_KERNEL);
140 if (!opt_inst)
141 return -ENOMEM;
142 opt_inst->option = option;
143 opt_inst->port = port;
144 opt_inst->array_index = i;
145 opt_inst->changed = true;
146 opt_inst->removed = false;
147 list_add_tail(&opt_inst->list, &team->option_inst_list);
148 }
149 return 0;
150}
151
142static int __team_option_inst_add_option(struct team *team, 152static int __team_option_inst_add_option(struct team *team,
143 struct team_option *option) 153 struct team_option *option)
144{ 154{
145 struct team_port *port; 155 struct team_port *port;
146 int err; 156 int err;
147 157
148 if (!option->per_port) 158 if (!option->per_port) {
149 return __team_option_inst_add(team, option, 0); 159 err = __team_option_inst_add(team, option, 0);
160 if (err)
161 goto inst_del_option;
162 }
150 163
151 list_for_each_entry(port, &team->port_list, list) { 164 list_for_each_entry(port, &team->port_list, list) {
152 err = __team_option_inst_add(team, option, port); 165 err = __team_option_inst_add(team, option, port);
@@ -1567,6 +1580,11 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
1567 opt_inst->port->dev->ifindex)) 1580 opt_inst->port->dev->ifindex))
1568 goto nla_put_failure; 1581 goto nla_put_failure;
1569 ctx.port = opt_inst->port; 1582 ctx.port = opt_inst->port;
1583 if (opt_inst->option->array_size &&
1584 nla_put_u32(skb, TEAM_ATTR_OPTION_ARRAY_INDEX,
1585 opt_inst->array_index))
1586 goto nla_put_failure;
1587 ctx.array_index = opt_inst->array_index;
1570 switch (option->type) { 1588 switch (option->type) {
1571 case TEAM_OPTION_TYPE_U32: 1589 case TEAM_OPTION_TYPE_U32:
1572 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32)) 1590 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32))
@@ -1668,10 +1686,12 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
1668 1686
1669 nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) { 1687 nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) {
1670 struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1]; 1688 struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1];
1671 struct nlattr *attr_port_ifindex; 1689 struct nlattr *attr;
1672 struct nlattr *attr_data; 1690 struct nlattr *attr_data;
1673 enum team_option_type opt_type; 1691 enum team_option_type opt_type;
1674 int opt_port_ifindex = 0; /* != 0 for per-port options */ 1692 int opt_port_ifindex = 0; /* != 0 for per-port options */
1693 u32 opt_array_index = 0;
1694 bool opt_is_array = false;
1675 struct team_option_inst *opt_inst; 1695 struct team_option_inst *opt_inst;
1676 char *opt_name; 1696 char *opt_name;
1677 bool opt_found = false; 1697 bool opt_found = false;
@@ -1713,9 +1733,15 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
1713 } 1733 }
1714 1734
1715 opt_name = nla_data(opt_attrs[TEAM_ATTR_OPTION_NAME]); 1735 opt_name = nla_data(opt_attrs[TEAM_ATTR_OPTION_NAME]);
1716 attr_port_ifindex = opt_attrs[TEAM_ATTR_OPTION_PORT_IFINDEX]; 1736 attr = opt_attrs[TEAM_ATTR_OPTION_PORT_IFINDEX];
1717 if (attr_port_ifindex) 1737 if (attr)
1718 opt_port_ifindex = nla_get_u32(attr_port_ifindex); 1738 opt_port_ifindex = nla_get_u32(attr);
1739
1740 attr = opt_attrs[TEAM_ATTR_OPTION_ARRAY_INDEX];
1741 if (attr) {
1742 opt_is_array = true;
1743 opt_array_index = nla_get_u32(attr);
1744 }
1719 1745
1720 list_for_each_entry(opt_inst, &team->option_inst_list, list) { 1746 list_for_each_entry(opt_inst, &team->option_inst_list, list) {
1721 struct team_option *option = opt_inst->option; 1747 struct team_option *option = opt_inst->option;
@@ -1726,10 +1752,13 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
1726 opt_inst->port->dev->ifindex : 0; 1752 opt_inst->port->dev->ifindex : 0;
1727 if (option->type != opt_type || 1753 if (option->type != opt_type ||
1728 strcmp(option->name, opt_name) || 1754 strcmp(option->name, opt_name) ||
1729 tmp_ifindex != opt_port_ifindex) 1755 tmp_ifindex != opt_port_ifindex ||
1756 (option->array_size && !opt_is_array) ||
1757 opt_inst->array_index != opt_array_index)
1730 continue; 1758 continue;
1731 opt_found = true; 1759 opt_found = true;
1732 ctx.port = opt_inst->port; 1760 ctx.port = opt_inst->port;
1761 ctx.array_index = opt_inst->array_index;
1733 switch (opt_type) { 1762 switch (opt_type) {
1734 case TEAM_OPTION_TYPE_U32: 1763 case TEAM_OPTION_TYPE_U32:
1735 ctx.data.u32_val = nla_get_u32(attr_data); 1764 ctx.data.u32_val = nla_get_u32(attr_data);