diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 198 |
1 files changed, 103 insertions, 95 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 01ced4a889e0..dc004b1e1f85 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1328,10 +1328,6 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | |||
1328 | [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED }, | 1328 | [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED }, |
1329 | }; | 1329 | }; |
1330 | 1330 | ||
1331 | static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { | ||
1332 | [IFLA_VF_INFO] = { .type = NLA_NESTED }, | ||
1333 | }; | ||
1334 | |||
1335 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { | 1331 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { |
1336 | [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, | 1332 | [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, |
1337 | [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, | 1333 | [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, |
@@ -1488,96 +1484,98 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | |||
1488 | return 0; | 1484 | return 0; |
1489 | } | 1485 | } |
1490 | 1486 | ||
1491 | static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) | 1487 | static int do_setvfinfo(struct net_device *dev, struct nlattr **tb) |
1492 | { | 1488 | { |
1493 | int rem, err = -EINVAL; | ||
1494 | struct nlattr *vf; | ||
1495 | const struct net_device_ops *ops = dev->netdev_ops; | 1489 | const struct net_device_ops *ops = dev->netdev_ops; |
1490 | int err = -EINVAL; | ||
1496 | 1491 | ||
1497 | nla_for_each_nested(vf, attr, rem) { | 1492 | if (tb[IFLA_VF_MAC]) { |
1498 | switch (nla_type(vf)) { | 1493 | struct ifla_vf_mac *ivm = nla_data(tb[IFLA_VF_MAC]); |
1499 | case IFLA_VF_MAC: { | ||
1500 | struct ifla_vf_mac *ivm; | ||
1501 | ivm = nla_data(vf); | ||
1502 | err = -EOPNOTSUPP; | ||
1503 | if (ops->ndo_set_vf_mac) | ||
1504 | err = ops->ndo_set_vf_mac(dev, ivm->vf, | ||
1505 | ivm->mac); | ||
1506 | break; | ||
1507 | } | ||
1508 | case IFLA_VF_VLAN: { | ||
1509 | struct ifla_vf_vlan *ivv; | ||
1510 | ivv = nla_data(vf); | ||
1511 | err = -EOPNOTSUPP; | ||
1512 | if (ops->ndo_set_vf_vlan) | ||
1513 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
1514 | ivv->vlan, | ||
1515 | ivv->qos); | ||
1516 | break; | ||
1517 | } | ||
1518 | case IFLA_VF_TX_RATE: { | ||
1519 | struct ifla_vf_tx_rate *ivt; | ||
1520 | struct ifla_vf_info ivf; | ||
1521 | ivt = nla_data(vf); | ||
1522 | err = -EOPNOTSUPP; | ||
1523 | if (ops->ndo_get_vf_config) | ||
1524 | err = ops->ndo_get_vf_config(dev, ivt->vf, | ||
1525 | &ivf); | ||
1526 | if (err) | ||
1527 | break; | ||
1528 | err = -EOPNOTSUPP; | ||
1529 | if (ops->ndo_set_vf_rate) | ||
1530 | err = ops->ndo_set_vf_rate(dev, ivt->vf, | ||
1531 | ivf.min_tx_rate, | ||
1532 | ivt->rate); | ||
1533 | break; | ||
1534 | } | ||
1535 | case IFLA_VF_RATE: { | ||
1536 | struct ifla_vf_rate *ivt; | ||
1537 | ivt = nla_data(vf); | ||
1538 | err = -EOPNOTSUPP; | ||
1539 | if (ops->ndo_set_vf_rate) | ||
1540 | err = ops->ndo_set_vf_rate(dev, ivt->vf, | ||
1541 | ivt->min_tx_rate, | ||
1542 | ivt->max_tx_rate); | ||
1543 | break; | ||
1544 | } | ||
1545 | case IFLA_VF_SPOOFCHK: { | ||
1546 | struct ifla_vf_spoofchk *ivs; | ||
1547 | ivs = nla_data(vf); | ||
1548 | err = -EOPNOTSUPP; | ||
1549 | if (ops->ndo_set_vf_spoofchk) | ||
1550 | err = ops->ndo_set_vf_spoofchk(dev, ivs->vf, | ||
1551 | ivs->setting); | ||
1552 | break; | ||
1553 | } | ||
1554 | case IFLA_VF_LINK_STATE: { | ||
1555 | struct ifla_vf_link_state *ivl; | ||
1556 | ivl = nla_data(vf); | ||
1557 | err = -EOPNOTSUPP; | ||
1558 | if (ops->ndo_set_vf_link_state) | ||
1559 | err = ops->ndo_set_vf_link_state(dev, ivl->vf, | ||
1560 | ivl->link_state); | ||
1561 | break; | ||
1562 | } | ||
1563 | case IFLA_VF_RSS_QUERY_EN: { | ||
1564 | struct ifla_vf_rss_query_en *ivrssq_en; | ||
1565 | 1494 | ||
1566 | ivrssq_en = nla_data(vf); | 1495 | err = -EOPNOTSUPP; |
1567 | err = -EOPNOTSUPP; | 1496 | if (ops->ndo_set_vf_mac) |
1568 | if (ops->ndo_set_vf_rss_query_en) | 1497 | err = ops->ndo_set_vf_mac(dev, ivm->vf, |
1569 | err = ops->ndo_set_vf_rss_query_en(dev, | 1498 | ivm->mac); |
1570 | ivrssq_en->vf, | 1499 | if (err < 0) |
1571 | ivrssq_en->setting); | 1500 | return err; |
1572 | break; | 1501 | } |
1573 | } | 1502 | |
1574 | default: | 1503 | if (tb[IFLA_VF_VLAN]) { |
1575 | err = -EINVAL; | 1504 | struct ifla_vf_vlan *ivv = nla_data(tb[IFLA_VF_VLAN]); |
1576 | break; | 1505 | |
1577 | } | 1506 | err = -EOPNOTSUPP; |
1578 | if (err) | 1507 | if (ops->ndo_set_vf_vlan) |
1579 | break; | 1508 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, ivv->vlan, |
1509 | ivv->qos); | ||
1510 | if (err < 0) | ||
1511 | return err; | ||
1512 | } | ||
1513 | |||
1514 | if (tb[IFLA_VF_TX_RATE]) { | ||
1515 | struct ifla_vf_tx_rate *ivt = nla_data(tb[IFLA_VF_TX_RATE]); | ||
1516 | struct ifla_vf_info ivf; | ||
1517 | |||
1518 | err = -EOPNOTSUPP; | ||
1519 | if (ops->ndo_get_vf_config) | ||
1520 | err = ops->ndo_get_vf_config(dev, ivt->vf, &ivf); | ||
1521 | if (err < 0) | ||
1522 | return err; | ||
1523 | |||
1524 | err = -EOPNOTSUPP; | ||
1525 | if (ops->ndo_set_vf_rate) | ||
1526 | err = ops->ndo_set_vf_rate(dev, ivt->vf, | ||
1527 | ivf.min_tx_rate, | ||
1528 | ivt->rate); | ||
1529 | if (err < 0) | ||
1530 | return err; | ||
1531 | } | ||
1532 | |||
1533 | if (tb[IFLA_VF_RATE]) { | ||
1534 | struct ifla_vf_rate *ivt = nla_data(tb[IFLA_VF_RATE]); | ||
1535 | |||
1536 | err = -EOPNOTSUPP; | ||
1537 | if (ops->ndo_set_vf_rate) | ||
1538 | err = ops->ndo_set_vf_rate(dev, ivt->vf, | ||
1539 | ivt->min_tx_rate, | ||
1540 | ivt->max_tx_rate); | ||
1541 | if (err < 0) | ||
1542 | return err; | ||
1543 | } | ||
1544 | |||
1545 | if (tb[IFLA_VF_SPOOFCHK]) { | ||
1546 | struct ifla_vf_spoofchk *ivs = nla_data(tb[IFLA_VF_SPOOFCHK]); | ||
1547 | |||
1548 | err = -EOPNOTSUPP; | ||
1549 | if (ops->ndo_set_vf_spoofchk) | ||
1550 | err = ops->ndo_set_vf_spoofchk(dev, ivs->vf, | ||
1551 | ivs->setting); | ||
1552 | if (err < 0) | ||
1553 | return err; | ||
1580 | } | 1554 | } |
1555 | |||
1556 | if (tb[IFLA_VF_LINK_STATE]) { | ||
1557 | struct ifla_vf_link_state *ivl = nla_data(tb[IFLA_VF_LINK_STATE]); | ||
1558 | |||
1559 | err = -EOPNOTSUPP; | ||
1560 | if (ops->ndo_set_vf_link_state) | ||
1561 | err = ops->ndo_set_vf_link_state(dev, ivl->vf, | ||
1562 | ivl->link_state); | ||
1563 | if (err < 0) | ||
1564 | return err; | ||
1565 | } | ||
1566 | |||
1567 | if (tb[IFLA_VF_RSS_QUERY_EN]) { | ||
1568 | struct ifla_vf_rss_query_en *ivrssq_en; | ||
1569 | |||
1570 | err = -EOPNOTSUPP; | ||
1571 | ivrssq_en = nla_data(tb[IFLA_VF_RSS_QUERY_EN]); | ||
1572 | if (ops->ndo_set_vf_rss_query_en) | ||
1573 | err = ops->ndo_set_vf_rss_query_en(dev, ivrssq_en->vf, | ||
1574 | ivrssq_en->setting); | ||
1575 | if (err < 0) | ||
1576 | return err; | ||
1577 | } | ||
1578 | |||
1581 | return err; | 1579 | return err; |
1582 | } | 1580 | } |
1583 | 1581 | ||
@@ -1773,14 +1771,21 @@ static int do_setlink(const struct sk_buff *skb, | |||
1773 | } | 1771 | } |
1774 | 1772 | ||
1775 | if (tb[IFLA_VFINFO_LIST]) { | 1773 | if (tb[IFLA_VFINFO_LIST]) { |
1774 | struct nlattr *vfinfo[IFLA_VF_MAX + 1]; | ||
1776 | struct nlattr *attr; | 1775 | struct nlattr *attr; |
1777 | int rem; | 1776 | int rem; |
1777 | |||
1778 | nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { | 1778 | nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { |
1779 | if (nla_type(attr) != IFLA_VF_INFO) { | 1779 | if (nla_type(attr) != IFLA_VF_INFO || |
1780 | nla_len(attr) < NLA_HDRLEN) { | ||
1780 | err = -EINVAL; | 1781 | err = -EINVAL; |
1781 | goto errout; | 1782 | goto errout; |
1782 | } | 1783 | } |
1783 | err = do_setvfinfo(dev, attr); | 1784 | err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr, |
1785 | ifla_vf_policy); | ||
1786 | if (err < 0) | ||
1787 | goto errout; | ||
1788 | err = do_setvfinfo(dev, vfinfo); | ||
1784 | if (err < 0) | 1789 | if (err < 0) |
1785 | goto errout; | 1790 | goto errout; |
1786 | status |= DO_SETLINK_NOTIFY; | 1791 | status |= DO_SETLINK_NOTIFY; |
@@ -1799,10 +1804,13 @@ static int do_setlink(const struct sk_buff *skb, | |||
1799 | goto errout; | 1804 | goto errout; |
1800 | 1805 | ||
1801 | nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { | 1806 | nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) { |
1802 | if (nla_type(attr) != IFLA_VF_PORT) | 1807 | if (nla_type(attr) != IFLA_VF_PORT || |
1803 | continue; | 1808 | nla_len(attr) < NLA_HDRLEN) { |
1804 | err = nla_parse_nested(port, IFLA_PORT_MAX, | 1809 | err = -EINVAL; |
1805 | attr, ifla_port_policy); | 1810 | goto errout; |
1811 | } | ||
1812 | err = nla_parse_nested(port, IFLA_PORT_MAX, attr, | ||
1813 | ifla_port_policy); | ||
1806 | if (err < 0) | 1814 | if (err < 0) |
1807 | goto errout; | 1815 | goto errout; |
1808 | if (!port[IFLA_PORT_VF]) { | 1816 | if (!port[IFLA_PORT_VF]) { |