|
@@ -1166,64 +1166,6 @@ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
|
|
|
- * be completed the entire msg is aborted and error value is returned.
|
|
|
- * No attempt is made to reconcile the case where only part of the
|
|
|
- * cmd can be completed.
|
|
|
- */
|
|
|
-static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
|
|
|
- u32 pid, u32 seq, u16 flags)
|
|
|
-{
|
|
|
- const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
|
|
|
- struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
|
|
|
- int err = -EOPNOTSUPP;
|
|
|
-
|
|
|
- if (!ops)
|
|
|
- goto err;
|
|
|
-
|
|
|
- err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
|
|
|
- tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
|
|
|
- if (err)
|
|
|
- goto err;
|
|
|
-
|
|
|
- if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
|
|
|
- struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
|
|
|
- err = ops->ieee_setets(netdev, ets);
|
|
|
- if (err)
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
|
|
|
- struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
|
|
|
- err = ops->ieee_setpfc(netdev, pfc);
|
|
|
- if (err)
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
|
|
|
- struct nlattr *attr;
|
|
|
- int rem;
|
|
|
-
|
|
|
- nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
|
|
|
- struct dcb_app *app_data;
|
|
|
- if (nla_type(attr) != DCB_ATTR_IEEE_APP)
|
|
|
- continue;
|
|
|
- app_data = nla_data(attr);
|
|
|
- if (ops->ieee_setapp)
|
|
|
- err = ops->ieee_setapp(netdev, app_data);
|
|
|
- else
|
|
|
- err = dcb_setapp(netdev, app_data);
|
|
|
- if (err)
|
|
|
- goto err;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-err:
|
|
|
- dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
|
|
|
- pid, seq, flags);
|
|
|
- return err;
|
|
|
-}
|
|
|
-
|
|
|
static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
|
|
|
int app_nested_type, int app_info_type,
|
|
|
int app_entry_type)
|
|
@@ -1279,30 +1221,13 @@ nla_put_failure:
|
|
|
}
|
|
|
|
|
|
/* Handle IEEE 802.1Qaz GET commands. */
|
|
|
-static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
|
|
|
- u32 pid, u32 seq, u16 flags)
|
|
|
+static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
|
|
|
{
|
|
|
- struct sk_buff *skb;
|
|
|
- struct nlmsghdr *nlh;
|
|
|
- struct dcbmsg *dcb;
|
|
|
struct nlattr *ieee, *app;
|
|
|
struct dcb_app_type *itr;
|
|
|
const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
|
|
|
int dcbx;
|
|
|
- int err;
|
|
|
-
|
|
|
- if (!ops)
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
- if (!skb)
|
|
|
- return -ENOBUFS;
|
|
|
-
|
|
|
- nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
|
|
|
-
|
|
|
- dcb = NLMSG_DATA(nlh);
|
|
|
- dcb->dcb_family = AF_UNSPEC;
|
|
|
- dcb->cmd = DCB_CMD_IEEE_GET;
|
|
|
+ int err = -EMSGSIZE;
|
|
|
|
|
|
NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
|
|
|
|
|
@@ -1378,16 +1303,154 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
|
|
|
if (err)
|
|
|
goto nla_put_failure;
|
|
|
}
|
|
|
- nlmsg_end(skb, nlh);
|
|
|
|
|
|
- return rtnl_unicast(skb, &init_net, pid);
|
|
|
+ return 0;
|
|
|
+
|
|
|
nla_put_failure:
|
|
|
- nlmsg_cancel(skb, nlh);
|
|
|
-nlmsg_failure:
|
|
|
- kfree_skb(skb);
|
|
|
- return -1;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
+int dcbnl_notify(struct net_device *dev, int event, int cmd,
|
|
|
+ u32 seq, u32 pid)
|
|
|
+{
|
|
|
+ struct net *net = dev_net(dev);
|
|
|
+ struct sk_buff *skb;
|
|
|
+ struct nlmsghdr *nlh;
|
|
|
+ struct dcbmsg *dcb;
|
|
|
+ const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (!ops)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
+ if (!skb)
|
|
|
+ return -ENOBUFS;
|
|
|
+
|
|
|
+ nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0);
|
|
|
+ if (nlh == NULL) {
|
|
|
+ kfree(skb);
|
|
|
+ return -EMSGSIZE;
|
|
|
+ }
|
|
|
+
|
|
|
+ dcb = NLMSG_DATA(nlh);
|
|
|
+ dcb->dcb_family = AF_UNSPEC;
|
|
|
+ dcb->cmd = cmd;
|
|
|
+
|
|
|
+ err = dcbnl_ieee_fill(skb, dev);
|
|
|
+ if (err < 0) {
|
|
|
+ /* Report error to broadcast listeners */
|
|
|
+ nlmsg_cancel(skb, nlh);
|
|
|
+ kfree_skb(skb);
|
|
|
+ rtnl_set_sk_err(net, RTNLGRP_DCB, err);
|
|
|
+ } else {
|
|
|
+ /* End nlmsg and notify broadcast listeners */
|
|
|
+ nlmsg_end(skb, nlh);
|
|
|
+ rtnl_notify(skb, net, 0, RTNLGRP_DCB, NULL, GFP_KERNEL);
|
|
|
+ }
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(dcbnl_notify);
|
|
|
+
|
|
|
+/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
|
|
|
+ * be completed the entire msg is aborted and error value is returned.
|
|
|
+ * No attempt is made to reconcile the case where only part of the
|
|
|
+ * cmd can be completed.
|
|
|
+ */
|
|
|
+static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
|
|
|
+ u32 pid, u32 seq, u16 flags)
|
|
|
+{
|
|
|
+ const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
|
|
|
+ struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
|
|
|
+ int err = -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (!ops)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
|
|
|
+ tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
|
|
|
+ struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
|
|
|
+ err = ops->ieee_setets(netdev, ets);
|
|
|
+ if (err)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setpfc) {
|
|
|
+ struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
|
|
|
+ err = ops->ieee_setpfc(netdev, pfc);
|
|
|
+ if (err)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
|
|
|
+ struct nlattr *attr;
|
|
|
+ int rem;
|
|
|
+
|
|
|
+ nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
|
|
|
+ struct dcb_app *app_data;
|
|
|
+ if (nla_type(attr) != DCB_ATTR_IEEE_APP)
|
|
|
+ continue;
|
|
|
+ app_data = nla_data(attr);
|
|
|
+ if (ops->ieee_setapp)
|
|
|
+ err = ops->ieee_setapp(netdev, app_data);
|
|
|
+ else
|
|
|
+ err = dcb_setapp(netdev, app_data);
|
|
|
+ if (err)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+err:
|
|
|
+ dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
|
|
|
+ pid, seq, flags);
|
|
|
+ dcbnl_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
|
|
|
+ u32 pid, u32 seq, u16 flags)
|
|
|
+{
|
|
|
+ struct net *net = dev_net(netdev);
|
|
|
+ struct sk_buff *skb;
|
|
|
+ struct nlmsghdr *nlh;
|
|
|
+ struct dcbmsg *dcb;
|
|
|
+ const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (!ops)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
+ if (!skb)
|
|
|
+ return -ENOBUFS;
|
|
|
+
|
|
|
+ nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
|
|
|
+ if (nlh == NULL) {
|
|
|
+ kfree(skb);
|
|
|
+ return -EMSGSIZE;
|
|
|
+ }
|
|
|
+
|
|
|
+ dcb = NLMSG_DATA(nlh);
|
|
|
+ dcb->dcb_family = AF_UNSPEC;
|
|
|
+ dcb->cmd = DCB_CMD_IEEE_GET;
|
|
|
+
|
|
|
+ err = dcbnl_ieee_fill(skb, netdev);
|
|
|
+
|
|
|
+ if (err < 0) {
|
|
|
+ nlmsg_cancel(skb, nlh);
|
|
|
+ kfree_skb(skb);
|
|
|
+ } else {
|
|
|
+ nlmsg_end(skb, nlh);
|
|
|
+ err = rtnl_unicast(skb, net, pid);
|
|
|
+ }
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
/* DCBX configuration */
|
|
|
static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
|
|
|
u32 pid, u32 seq, u16 flags)
|