aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorShmulik Ravid <shmulikr@broadcom.com>2011-07-05 02:16:22 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-06 02:42:17 -0400
commit37cf4d1a9b0903b874a638d0f8649873ddde8a12 (patch)
tree3098d533e421cc614fc2f3a3a67cdd82dfd50305 /net
parente12fe68ce34d60c04bb1ddb1d3cc5c3022388fe4 (diff)
dcbnl: Aggregated CEE GET operation
The following couple of patches add dcbnl an unsolicited notification of the the DCB configuration for the CEE flavor of the DCBX protocol. This is useful when the user-mode DCB client is not responsible for conducting and resolving the DCBX negotiation (either because the DCBX stack is embedded in the HW or the negotiation is handled by another agent in the host), but still needs to get the negotiated parameters. This functionality already exists for the IEEE flavor of the DCBX protocol and these patches add it to the older CEE flavor. The first patch extends the CEE attribute GET operation to include not only the peer information, but also all the pertinent local configuration (negotiated parameters). The second patch adds and export a CEE specific notification routine. Signed-off-by: Shmulik Ravid <shmulikr@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/dcb/dcbnl.c159
1 files changed, 152 insertions, 7 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index fc56e8546261..d5b45a201c1b 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1642,6 +1642,60 @@ err:
1642 return ret; 1642 return ret;
1643} 1643}
1644 1644
1645static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev,
1646 int dir)
1647{
1648 u8 pgid, up_map, prio, tc_pct;
1649 const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
1650 int i = dir ? DCB_ATTR_CEE_TX_PG : DCB_ATTR_CEE_RX_PG;
1651 struct nlattr *pg = nla_nest_start(skb, i);
1652
1653 if (!pg)
1654 goto nla_put_failure;
1655
1656 for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) {
1657 struct nlattr *tc_nest = nla_nest_start(skb, i);
1658
1659 if (!tc_nest)
1660 goto nla_put_failure;
1661
1662 pgid = DCB_ATTR_VALUE_UNDEFINED;
1663 prio = DCB_ATTR_VALUE_UNDEFINED;
1664 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
1665 up_map = DCB_ATTR_VALUE_UNDEFINED;
1666
1667 if (!dir)
1668 ops->getpgtccfgrx(dev, i - DCB_PG_ATTR_TC_0,
1669 &prio, &pgid, &tc_pct, &up_map);
1670 else
1671 ops->getpgtccfgtx(dev, i - DCB_PG_ATTR_TC_0,
1672 &prio, &pgid, &tc_pct, &up_map);
1673
1674 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_PGID, pgid);
1675 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map);
1676 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio);
1677 NLA_PUT_U8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct);
1678 nla_nest_end(skb, tc_nest);
1679 }
1680
1681 for (i = DCB_PG_ATTR_BW_ID_0; i <= DCB_PG_ATTR_BW_ID_7; i++) {
1682 tc_pct = DCB_ATTR_VALUE_UNDEFINED;
1683
1684 if (!dir)
1685 ops->getpgbwgcfgrx(dev, i - DCB_PG_ATTR_BW_ID_0,
1686 &tc_pct);
1687 else
1688 ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0,
1689 &tc_pct);
1690 NLA_PUT_U8(skb, i, tc_pct);
1691 }
1692 nla_nest_end(skb, pg);
1693 return 0;
1694
1695nla_put_failure:
1696 return -EMSGSIZE;
1697}
1698
1645/* Handle CEE DCBX GET commands. */ 1699/* Handle CEE DCBX GET commands. */
1646static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb, 1700static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1647 u32 pid, u32 seq, u16 flags) 1701 u32 pid, u32 seq, u16 flags)
@@ -1649,9 +1703,11 @@ static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1649 struct sk_buff *skb; 1703 struct sk_buff *skb;
1650 struct nlmsghdr *nlh; 1704 struct nlmsghdr *nlh;
1651 struct dcbmsg *dcb; 1705 struct dcbmsg *dcb;
1652 struct nlattr *cee; 1706 struct nlattr *cee, *app;
1707 struct dcb_app_type *itr;
1653 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; 1708 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1654 int err; 1709 int dcbx, i, err = -EMSGSIZE;
1710 u8 value;
1655 1711
1656 if (!ops) 1712 if (!ops)
1657 return -EOPNOTSUPP; 1713 return -EOPNOTSUPP;
@@ -1672,7 +1728,88 @@ static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1672 if (!cee) 1728 if (!cee)
1673 goto nla_put_failure; 1729 goto nla_put_failure;
1674 1730
1675 /* get peer info if available */ 1731 /* local pg */
1732 if (ops->getpgtccfgtx && ops->getpgbwgcfgtx) {
1733 err = dcbnl_cee_pg_fill(skb, netdev, 1);
1734 if (err)
1735 goto nla_put_failure;
1736 }
1737
1738 if (ops->getpgtccfgrx && ops->getpgbwgcfgrx) {
1739 err = dcbnl_cee_pg_fill(skb, netdev, 0);
1740 if (err)
1741 goto nla_put_failure;
1742 }
1743
1744 /* local pfc */
1745 if (ops->getpfccfg) {
1746 struct nlattr *pfc_nest = nla_nest_start(skb, DCB_ATTR_CEE_PFC);
1747
1748 if (!pfc_nest)
1749 goto nla_put_failure;
1750
1751 for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) {
1752 ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value);
1753 NLA_PUT_U8(skb, i, value);
1754 }
1755 nla_nest_end(skb, pfc_nest);
1756 }
1757
1758 /* local app */
1759 spin_lock(&dcb_lock);
1760 app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
1761 if (!app)
1762 goto nla_put_failure;
1763
1764 list_for_each_entry(itr, &dcb_app_list, list) {
1765 if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0) {
1766 struct nlattr *app_nest = nla_nest_start(skb,
1767 DCB_ATTR_APP);
1768 if (!app_nest)
1769 goto dcb_unlock;
1770
1771 err = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE,
1772 itr->app.selector);
1773 if (err)
1774 goto dcb_unlock;
1775
1776 err = nla_put_u16(skb, DCB_APP_ATTR_ID,
1777 itr->app.protocol);
1778 if (err)
1779 goto dcb_unlock;
1780
1781 err = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY,
1782 itr->app.priority);
1783 if (err)
1784 goto dcb_unlock;
1785
1786 nla_nest_end(skb, app_nest);
1787 }
1788 }
1789 nla_nest_end(skb, app);
1790
1791 if (netdev->dcbnl_ops->getdcbx)
1792 dcbx = netdev->dcbnl_ops->getdcbx(netdev);
1793 else
1794 dcbx = -EOPNOTSUPP;
1795
1796 spin_unlock(&dcb_lock);
1797
1798 /* features flags */
1799 if (ops->getfeatcfg) {
1800 struct nlattr *feat = nla_nest_start(skb, DCB_ATTR_CEE_FEAT);
1801 if (!feat)
1802 goto nla_put_failure;
1803
1804 for (i = DCB_FEATCFG_ATTR_ALL + 1; i <= DCB_FEATCFG_ATTR_MAX;
1805 i++)
1806 if (!ops->getfeatcfg(netdev, i, &value))
1807 NLA_PUT_U8(skb, i, value);
1808
1809 nla_nest_end(skb, feat);
1810 }
1811
1812 /* peer info if available */
1676 if (ops->cee_peer_getpg) { 1813 if (ops->cee_peer_getpg) {
1677 struct cee_pg pg; 1814 struct cee_pg pg;
1678 err = ops->cee_peer_getpg(netdev, &pg); 1815 err = ops->cee_peer_getpg(netdev, &pg);
@@ -1695,16 +1832,24 @@ static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1695 if (err) 1832 if (err)
1696 goto nla_put_failure; 1833 goto nla_put_failure;
1697 } 1834 }
1698
1699 nla_nest_end(skb, cee); 1835 nla_nest_end(skb, cee);
1700 nlmsg_end(skb, nlh);
1701 1836
1837 /* DCBX state */
1838 if (dcbx >= 0) {
1839 err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx);
1840 if (err)
1841 goto nla_put_failure;
1842 }
1843 nlmsg_end(skb, nlh);
1702 return rtnl_unicast(skb, &init_net, pid); 1844 return rtnl_unicast(skb, &init_net, pid);
1845
1846dcb_unlock:
1847 spin_unlock(&dcb_lock);
1703nla_put_failure: 1848nla_put_failure:
1704 nlmsg_cancel(skb, nlh); 1849 nlmsg_cancel(skb, nlh);
1705nlmsg_failure: 1850nlmsg_failure:
1706 kfree_skb(skb); 1851 nlmsg_free(skb);
1707 return -1; 1852 return err;
1708} 1853}
1709 1854
1710static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1855static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)