|
@@ -179,6 +179,9 @@ static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
|
|
|
[DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)},
|
|
|
};
|
|
|
|
|
|
+static LIST_HEAD(dcb_app_list);
|
|
|
+static DEFINE_SPINLOCK(dcb_lock);
|
|
|
+
|
|
|
/* standard netlink reply call */
|
|
|
static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
|
|
|
u32 seq, u16 flags)
|
|
@@ -634,12 +637,12 @@ out:
|
|
|
static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
|
|
|
u32 pid, u32 seq, u16 flags)
|
|
|
{
|
|
|
- int ret = -EINVAL;
|
|
|
+ int err, ret = -EINVAL;
|
|
|
u16 id;
|
|
|
u8 up, idtype;
|
|
|
struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];
|
|
|
|
|
|
- if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp)
|
|
|
+ if (!tb[DCB_ATTR_APP])
|
|
|
goto out;
|
|
|
|
|
|
ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
|
|
@@ -663,9 +666,18 @@ static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
|
|
|
id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
|
|
|
up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);
|
|
|
|
|
|
- ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up),
|
|
|
- RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
|
|
|
- pid, seq, flags);
|
|
|
+ if (netdev->dcbnl_ops->setapp) {
|
|
|
+ err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up);
|
|
|
+ } else {
|
|
|
+ struct dcb_app app;
|
|
|
+ app.selector = idtype;
|
|
|
+ app.protocol = id;
|
|
|
+ app.priority = up;
|
|
|
+ err = dcb_setapp(netdev, &app);
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
|
|
|
+ pid, seq, flags);
|
|
|
out:
|
|
|
return ret;
|
|
|
}
|
|
@@ -1164,7 +1176,7 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- if (ieee[DCB_ATTR_IEEE_APP_TABLE] && ops->ieee_setapp) {
|
|
|
+ if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
|
|
|
struct nlattr *attr;
|
|
|
int rem;
|
|
|
|
|
@@ -1173,7 +1185,10 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
|
|
|
if (nla_type(attr) != DCB_ATTR_IEEE_APP)
|
|
|
continue;
|
|
|
app_data = nla_data(attr);
|
|
|
- err = ops->ieee_setapp(netdev, app_data);
|
|
|
+ if (ops->ieee_setapp)
|
|
|
+ err = ops->ieee_setapp(netdev, app_data);
|
|
|
+ else
|
|
|
+ err = dcb_setapp(netdev, app_data);
|
|
|
if (err)
|
|
|
goto err;
|
|
|
}
|
|
@@ -1193,7 +1208,8 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
|
|
|
struct sk_buff *skb;
|
|
|
struct nlmsghdr *nlh;
|
|
|
struct dcbmsg *dcb;
|
|
|
- struct nlattr *ieee;
|
|
|
+ struct nlattr *ieee, *app;
|
|
|
+ struct dcb_app_type *itr;
|
|
|
const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
|
|
|
int err;
|
|
|
|
|
@@ -1230,6 +1246,19 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
|
|
|
NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc);
|
|
|
}
|
|
|
|
|
|
+ app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE);
|
|
|
+ if (!app)
|
|
|
+ goto nla_put_failure;
|
|
|
+
|
|
|
+ spin_lock(&dcb_lock);
|
|
|
+ list_for_each_entry(itr, &dcb_app_list, list) {
|
|
|
+ if (strncmp(itr->name, netdev->name, IFNAMSIZ) == 0)
|
|
|
+ NLA_PUT(skb, DCB_ATTR_IEEE_APP,
|
|
|
+ sizeof(itr->app), &itr->app);
|
|
|
+ }
|
|
|
+ spin_unlock(&dcb_lock);
|
|
|
+ nla_nest_end(skb, app);
|
|
|
+
|
|
|
nla_nest_end(skb, ieee);
|
|
|
nlmsg_end(skb, nlh);
|
|
|
|
|
@@ -1364,8 +1393,93 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * dcb_getapp - retrieve the DCBX application user priority
|
|
|
+ *
|
|
|
+ * On success returns a non-zero 802.1p user priority bitmap
|
|
|
+ * otherwise returns 0 as the invalid user priority bitmap to
|
|
|
+ * indicate an error.
|
|
|
+ */
|
|
|
+u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
|
|
|
+{
|
|
|
+ struct dcb_app_type *itr;
|
|
|
+ u8 prio = 0;
|
|
|
+
|
|
|
+ spin_lock(&dcb_lock);
|
|
|
+ list_for_each_entry(itr, &dcb_app_list, list) {
|
|
|
+ if (itr->app.selector == app->selector &&
|
|
|
+ itr->app.protocol == app->protocol &&
|
|
|
+ (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
|
|
|
+ prio = itr->app.priority;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ spin_unlock(&dcb_lock);
|
|
|
+
|
|
|
+ return prio;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(dcb_getapp);
|
|
|
+
|
|
|
+/**
|
|
|
+ * ixgbe_dcbnl_setapp - add dcb application data to app list
|
|
|
+ *
|
|
|
+ * Priority 0 is the default priority this removes applications
|
|
|
+ * from the app list if the priority is set to zero.
|
|
|
+ */
|
|
|
+u8 dcb_setapp(struct net_device *dev, struct dcb_app *new)
|
|
|
+{
|
|
|
+ struct dcb_app_type *itr;
|
|
|
+
|
|
|
+ spin_lock(&dcb_lock);
|
|
|
+ /* Search for existing match and replace */
|
|
|
+ list_for_each_entry(itr, &dcb_app_list, list) {
|
|
|
+ if (itr->app.selector == new->selector &&
|
|
|
+ itr->app.protocol == new->protocol &&
|
|
|
+ (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
|
|
|
+ if (new->priority)
|
|
|
+ itr->app.priority = new->priority;
|
|
|
+ else {
|
|
|
+ list_del(&itr->list);
|
|
|
+ kfree(itr);
|
|
|
+ }
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* App type does not exist add new application type */
|
|
|
+ if (new->priority) {
|
|
|
+ struct dcb_app_type *entry;
|
|
|
+ entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC);
|
|
|
+ if (!entry) {
|
|
|
+ spin_unlock(&dcb_lock);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&entry->app, new, sizeof(*new));
|
|
|
+ strncpy(entry->name, dev->name, IFNAMSIZ);
|
|
|
+ list_add(&entry->list, &dcb_app_list);
|
|
|
+ }
|
|
|
+out:
|
|
|
+ spin_unlock(&dcb_lock);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(dcb_setapp);
|
|
|
+
|
|
|
+void dcb_flushapp(void)
|
|
|
+{
|
|
|
+ struct dcb_app_type *app;
|
|
|
+
|
|
|
+ spin_lock(&dcb_lock);
|
|
|
+ list_for_each_entry(app, &dcb_app_list, list) {
|
|
|
+ list_del(&app->list);
|
|
|
+ kfree(app);
|
|
|
+ }
|
|
|
+ spin_unlock(&dcb_lock);
|
|
|
+}
|
|
|
+
|
|
|
static int __init dcbnl_init(void)
|
|
|
{
|
|
|
+ INIT_LIST_HEAD(&dcb_app_list);
|
|
|
+
|
|
|
rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL);
|
|
|
rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL);
|
|
|
|
|
@@ -1377,7 +1491,6 @@ static void __exit dcbnl_exit(void)
|
|
|
{
|
|
|
rtnl_unregister(PF_UNSPEC, RTM_GETDCB);
|
|
|
rtnl_unregister(PF_UNSPEC, RTM_SETDCB);
|
|
|
+ dcb_flushapp();
|
|
|
}
|
|
|
module_exit(dcbnl_exit);
|
|
|
-
|
|
|
-
|