aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2012-06-19 01:54:14 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-19 18:00:23 -0400
commit01048d9a293cbe9aac00fd014b9754bbc7eb136f (patch)
treee39bbe3f797a1a6bfa2c5a08480826498bfc40ef /drivers/net
parent3221c64603d9843d8a28dfd8e678e46625d5d807 (diff)
team: allow to specify one option instance to be send to userspace
No need to walk through option instance list and look for ->changed == true when called knows exactly what one option instance changed. Also use lists to pass option instances needed to be present in netlink message. Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/team/team.c210
1 files changed, 124 insertions, 86 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index e977f440c378..da72f41d3914 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -89,6 +89,7 @@ static void team_refresh_port_linkup(struct team_port *port)
89 89
90struct team_option_inst { /* One for each option instance */ 90struct team_option_inst { /* One for each option instance */
91 struct list_head list; 91 struct list_head list;
92 struct list_head tmp_list;
92 struct team_option *option; 93 struct team_option *option;
93 struct team_option_inst_info info; 94 struct team_option_inst_info info;
94 bool changed; 95 bool changed;
@@ -319,6 +320,8 @@ static void __team_options_unregister(struct team *team,
319} 320}
320 321
321static void __team_options_change_check(struct team *team); 322static void __team_options_change_check(struct team *team);
323static void __team_option_inst_change(struct team *team,
324 struct team_option_inst *opt_inst);
322 325
323int team_options_register(struct team *team, 326int team_options_register(struct team *team,
324 const struct team_option *option, 327 const struct team_option *option,
@@ -383,8 +386,7 @@ static int team_option_set(struct team *team,
383 if (err) 386 if (err)
384 return err; 387 return err;
385 388
386 opt_inst->changed = true; 389 __team_option_inst_change(team, opt_inst);
387 __team_options_change_check(team);
388 return err; 390 return err;
389} 391}
390 392
@@ -1565,9 +1567,95 @@ err_fill:
1565 return err; 1567 return err;
1566} 1568}
1567 1569
1570static int team_nl_fill_one_option_get(struct sk_buff *skb, struct team *team,
1571 struct team_option_inst *opt_inst)
1572{
1573 struct nlattr *option_item;
1574 struct team_option *option = opt_inst->option;
1575 struct team_option_inst_info *opt_inst_info;
1576 struct team_gsetter_ctx ctx;
1577 int err;
1578
1579 option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION);
1580 if (!option_item)
1581 goto nla_put_failure;
1582 if (nla_put_string(skb, TEAM_ATTR_OPTION_NAME, option->name))
1583 goto nla_put_failure;
1584 if (opt_inst->changed) {
1585 if (nla_put_flag(skb, TEAM_ATTR_OPTION_CHANGED))
1586 goto nla_put_failure;
1587 opt_inst->changed = false;
1588 }
1589 if (opt_inst->removed && nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED))
1590 goto nla_put_failure;
1591
1592 opt_inst_info = &opt_inst->info;
1593 if (opt_inst_info->port &&
1594 nla_put_u32(skb, TEAM_ATTR_OPTION_PORT_IFINDEX,
1595 opt_inst_info->port->dev->ifindex))
1596 goto nla_put_failure;
1597 if (opt_inst->option->array_size &&
1598 nla_put_u32(skb, TEAM_ATTR_OPTION_ARRAY_INDEX,
1599 opt_inst_info->array_index))
1600 goto nla_put_failure;
1601 ctx.info = opt_inst_info;
1602
1603 switch (option->type) {
1604 case TEAM_OPTION_TYPE_U32:
1605 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32))
1606 goto nla_put_failure;
1607 err = team_option_get(team, opt_inst, &ctx);
1608 if (err)
1609 goto errout;
1610 if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA, ctx.data.u32_val))
1611 goto nla_put_failure;
1612 break;
1613 case TEAM_OPTION_TYPE_STRING:
1614 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING))
1615 goto nla_put_failure;
1616 err = team_option_get(team, opt_inst, &ctx);
1617 if (err)
1618 goto errout;
1619 if (nla_put_string(skb, TEAM_ATTR_OPTION_DATA,
1620 ctx.data.str_val))
1621 goto nla_put_failure;
1622 break;
1623 case TEAM_OPTION_TYPE_BINARY:
1624 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_BINARY))
1625 goto nla_put_failure;
1626 err = team_option_get(team, opt_inst, &ctx);
1627 if (err)
1628 goto errout;
1629 if (nla_put(skb, TEAM_ATTR_OPTION_DATA, ctx.data.bin_val.len,
1630 ctx.data.bin_val.ptr))
1631 goto nla_put_failure;
1632 break;
1633 case TEAM_OPTION_TYPE_BOOL:
1634 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_FLAG))
1635 goto nla_put_failure;
1636 err = team_option_get(team, opt_inst, &ctx);
1637 if (err)
1638 goto errout;
1639 if (ctx.data.bool_val &&
1640 nla_put_flag(skb, TEAM_ATTR_OPTION_DATA))
1641 goto nla_put_failure;
1642 break;
1643 default:
1644 BUG();
1645 }
1646 nla_nest_end(skb, option_item);
1647 return 0;
1648
1649nla_put_failure:
1650 err = -EMSGSIZE;
1651errout:
1652 return err;
1653}
1654
1568static int team_nl_fill_options_get(struct sk_buff *skb, 1655static int team_nl_fill_options_get(struct sk_buff *skb,
1569 u32 pid, u32 seq, int flags, 1656 u32 pid, u32 seq, int flags,
1570 struct team *team, bool fillall) 1657 struct team *team,
1658 struct list_head *sel_opt_inst_list)
1571{ 1659{
1572 struct nlattr *option_list; 1660 struct nlattr *option_list;
1573 void *hdr; 1661 void *hdr;
@@ -1585,85 +1673,10 @@ static int team_nl_fill_options_get(struct sk_buff *skb,
1585 if (!option_list) 1673 if (!option_list)
1586 goto nla_put_failure; 1674 goto nla_put_failure;
1587 1675
1588 list_for_each_entry(opt_inst, &team->option_inst_list, list) { 1676 list_for_each_entry(opt_inst, sel_opt_inst_list, tmp_list) {
1589 struct nlattr *option_item; 1677 err = team_nl_fill_one_option_get(skb, team, opt_inst);
1590 struct team_option *option = opt_inst->option; 1678 if (err)
1591 struct team_option_inst_info *opt_inst_info; 1679 goto errout;
1592 struct team_gsetter_ctx ctx;
1593
1594 /* Include only changed options if fill all mode is not on */
1595 if (!fillall && !opt_inst->changed)
1596 continue;
1597 option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION);
1598 if (!option_item)
1599 goto nla_put_failure;
1600 if (nla_put_string(skb, TEAM_ATTR_OPTION_NAME, option->name))
1601 goto nla_put_failure;
1602 if (opt_inst->changed) {
1603 if (nla_put_flag(skb, TEAM_ATTR_OPTION_CHANGED))
1604 goto nla_put_failure;
1605 opt_inst->changed = false;
1606 }
1607 if (opt_inst->removed &&
1608 nla_put_flag(skb, TEAM_ATTR_OPTION_REMOVED))
1609 goto nla_put_failure;
1610
1611 opt_inst_info = &opt_inst->info;
1612 if (opt_inst_info->port &&
1613 nla_put_u32(skb, TEAM_ATTR_OPTION_PORT_IFINDEX,
1614 opt_inst_info->port->dev->ifindex))
1615 goto nla_put_failure;
1616 if (opt_inst->option->array_size &&
1617 nla_put_u32(skb, TEAM_ATTR_OPTION_ARRAY_INDEX,
1618 opt_inst_info->array_index))
1619 goto nla_put_failure;
1620 ctx.info = opt_inst_info;
1621
1622 switch (option->type) {
1623 case TEAM_OPTION_TYPE_U32:
1624 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32))
1625 goto nla_put_failure;
1626 err = team_option_get(team, opt_inst, &ctx);
1627 if (err)
1628 goto errout;
1629 if (nla_put_u32(skb, TEAM_ATTR_OPTION_DATA,
1630 ctx.data.u32_val))
1631 goto nla_put_failure;
1632 break;
1633 case TEAM_OPTION_TYPE_STRING:
1634 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING))
1635 goto nla_put_failure;
1636 err = team_option_get(team, opt_inst, &ctx);
1637 if (err)
1638 goto errout;
1639 if (nla_put_string(skb, TEAM_ATTR_OPTION_DATA,
1640 ctx.data.str_val))
1641 goto nla_put_failure;
1642 break;
1643 case TEAM_OPTION_TYPE_BINARY:
1644 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_BINARY))
1645 goto nla_put_failure;
1646 err = team_option_get(team, opt_inst, &ctx);
1647 if (err)
1648 goto errout;
1649 if (nla_put(skb, TEAM_ATTR_OPTION_DATA,
1650 ctx.data.bin_val.len, ctx.data.bin_val.ptr))
1651 goto nla_put_failure;
1652 break;
1653 case TEAM_OPTION_TYPE_BOOL:
1654 if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_FLAG))
1655 goto nla_put_failure;
1656 err = team_option_get(team, opt_inst, &ctx);
1657 if (err)
1658 goto errout;
1659 if (ctx.data.bool_val &&
1660 nla_put_flag(skb, TEAM_ATTR_OPTION_DATA))
1661 goto nla_put_failure;
1662 break;
1663 default:
1664 BUG();
1665 }
1666 nla_nest_end(skb, option_item);
1667 } 1680 }
1668 1681
1669 nla_nest_end(skb, option_list); 1682 nla_nest_end(skb, option_list);
@@ -1680,9 +1693,14 @@ static int team_nl_fill_options_get_all(struct sk_buff *skb,
1680 struct genl_info *info, int flags, 1693 struct genl_info *info, int flags,
1681 struct team *team) 1694 struct team *team)
1682{ 1695{
1696 struct team_option_inst *opt_inst;
1697 LIST_HEAD(sel_opt_inst_list);
1698
1699 list_for_each_entry(opt_inst, &team->option_inst_list, list)
1700 list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list);
1683 return team_nl_fill_options_get(skb, info->snd_pid, 1701 return team_nl_fill_options_get(skb, info->snd_pid,
1684 info->snd_seq, NLM_F_ACK, 1702 info->snd_seq, NLM_F_ACK,
1685 team, true); 1703 team, &sel_opt_inst_list);
1686} 1704}
1687 1705
1688static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) 1706static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info)
@@ -1941,7 +1959,8 @@ static struct genl_multicast_group team_change_event_mcgrp = {
1941 .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, 1959 .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
1942}; 1960};
1943 1961
1944static int team_nl_send_event_options_get(struct team *team) 1962static int team_nl_send_event_options_get(struct team *team,
1963 struct list_head *sel_opt_inst_list)
1945{ 1964{
1946 struct sk_buff *skb; 1965 struct sk_buff *skb;
1947 int err; 1966 int err;
@@ -1951,7 +1970,7 @@ static int team_nl_send_event_options_get(struct team *team)
1951 if (!skb) 1970 if (!skb)
1952 return -ENOMEM; 1971 return -ENOMEM;
1953 1972
1954 err = team_nl_fill_options_get(skb, 0, 0, 0, team, false); 1973 err = team_nl_fill_options_get(skb, 0, 0, 0, team, sel_opt_inst_list);
1955 if (err < 0) 1974 if (err < 0)
1956 goto err_fill; 1975 goto err_fill;
1957 1976
@@ -2021,12 +2040,31 @@ static void team_nl_fini(void)
2021static void __team_options_change_check(struct team *team) 2040static void __team_options_change_check(struct team *team)
2022{ 2041{
2023 int err; 2042 int err;
2043 struct team_option_inst *opt_inst;
2044 LIST_HEAD(sel_opt_inst_list);
2024 2045
2025 err = team_nl_send_event_options_get(team); 2046 list_for_each_entry(opt_inst, &team->option_inst_list, list) {
2047 if (opt_inst->changed)
2048 list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list);
2049 }
2050 err = team_nl_send_event_options_get(team, &sel_opt_inst_list);
2026 if (err) 2051 if (err)
2027 netdev_warn(team->dev, "Failed to send options change via netlink\n"); 2052 netdev_warn(team->dev, "Failed to send options change via netlink\n");
2028} 2053}
2029 2054
2055static void __team_option_inst_change(struct team *team,
2056 struct team_option_inst *sel_opt_inst)
2057{
2058 int err;
2059 LIST_HEAD(sel_opt_inst_list);
2060
2061 sel_opt_inst->changed = true;
2062 list_add(&sel_opt_inst->tmp_list, &sel_opt_inst_list);
2063 err = team_nl_send_event_options_get(team, &sel_opt_inst_list);
2064 if (err)
2065 netdev_warn(team->dev, "Failed to send option change via netlink\n");
2066}
2067
2030/* rtnl lock is held */ 2068/* rtnl lock is held */
2031static void __team_port_change_check(struct team_port *port, bool linkup) 2069static void __team_port_change_check(struct team_port *port, bool linkup)
2032{ 2070{