|
@@ -1451,6 +1451,52 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
|
|
|
|
|
|
return err;
|
|
|
}
|
|
|
+
|
|
|
+static int dcbnl_ieee_del(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 -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (!tb[DCB_ATTR_IEEE])
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ 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_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_delapp)
|
|
|
+ err = ops->ieee_delapp(netdev, app_data);
|
|
|
+ else
|
|
|
+ err = dcb_ieee_delapp(netdev, app_data);
|
|
|
+ if (err)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+err:
|
|
|
+ dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
|
|
|
+ pid, seq, flags);
|
|
|
+ dcbnl_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/* DCBX configuration */
|
|
|
static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
|
|
|
u32 pid, u32 seq, u16 flags)
|
|
@@ -1765,11 +1811,15 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
|
|
goto out;
|
|
|
case DCB_CMD_IEEE_SET:
|
|
|
ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
|
|
|
- nlh->nlmsg_flags);
|
|
|
+ nlh->nlmsg_flags);
|
|
|
goto out;
|
|
|
case DCB_CMD_IEEE_GET:
|
|
|
ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
|
|
|
- nlh->nlmsg_flags);
|
|
|
+ nlh->nlmsg_flags);
|
|
|
+ goto out;
|
|
|
+ case DCB_CMD_IEEE_DEL:
|
|
|
+ ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
|
|
|
+ nlh->nlmsg_flags);
|
|
|
goto out;
|
|
|
case DCB_CMD_GDCBX:
|
|
|
ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
|
|
@@ -1924,6 +1974,42 @@ out:
|
|
|
}
|
|
|
EXPORT_SYMBOL(dcb_ieee_setapp);
|
|
|
|
|
|
+/**
|
|
|
+ * dcb_ieee_delapp - delete IEEE dcb application data from list
|
|
|
+ *
|
|
|
+ * This removes a matching APP data from the APP list
|
|
|
+ */
|
|
|
+int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
|
|
|
+{
|
|
|
+ struct dcb_app_type *itr;
|
|
|
+ struct dcb_app_type event;
|
|
|
+ int err = -ENOENT;
|
|
|
+
|
|
|
+ memcpy(&event.name, dev->name, sizeof(event.name));
|
|
|
+ memcpy(&event.app, del, sizeof(event.app));
|
|
|
+
|
|
|
+ spin_lock(&dcb_lock);
|
|
|
+ /* Search for existing match and remove it. */
|
|
|
+ list_for_each_entry(itr, &dcb_app_list, list) {
|
|
|
+ if (itr->app.selector == del->selector &&
|
|
|
+ itr->app.protocol == del->protocol &&
|
|
|
+ itr->app.priority == del->priority &&
|
|
|
+ (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
|
|
|
+ list_del(&itr->list);
|
|
|
+ kfree(itr);
|
|
|
+ err = 0;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+out:
|
|
|
+ spin_unlock(&dcb_lock);
|
|
|
+ if (!err)
|
|
|
+ call_dcbevent_notifiers(DCB_APP_EVENT, &event);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(dcb_ieee_delapp);
|
|
|
+
|
|
|
static void dcb_flushapp(void)
|
|
|
{
|
|
|
struct dcb_app_type *app;
|