summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ipoe/ipoe.c54
-rw-r--r--drivers/ipoe/ipoe.h1
2 files changed, 55 insertions, 0 deletions
diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c
index 73926994..8f1c852b 100644
--- a/drivers/ipoe/ipoe.c
+++ b/drivers/ipoe/ipoe.c
@@ -1420,6 +1420,52 @@ out_unlock:
return ret;
}
+static int ipoe_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info)
+{
+ struct ipoe_session *ses;
+ LIST_HEAD(list);
+ LIST_HEAD(kill_list);
+
+ down(&ipoe_wlock);
+
+ list_splice_init(&ipoe_list2, &list);
+
+ list_for_each_entry(ses, &list, entry2) {
+ if (ses->peer_addr)
+ list_del_rcu(&ses->entry);
+ if (ses->u.hwaddr_u)
+ list_del_rcu(&ses->entry3);
+ }
+
+ up(&ipoe_wlock);
+
+ if (list_empty(&list))
+ return 0;
+
+ /* a single grace period covers the whole batch */
+ synchronize_rcu();
+
+ list_for_each_entry(ses, &list, entry2) {
+ while (atomic_read(&ses->refs))
+ schedule_timeout_uninterruptible(1);
+
+ if (ses->link_dev) {
+ dev_put(ses->link_dev);
+ ses->link_dev = NULL;
+ }
+ }
+
+ rtnl_lock();
+ list_for_each_entry(ses, &list, entry2)
+ unregister_netdevice_queue(ses->dev, &kill_list);
+ unregister_netdevice_many(&kill_list);
+ rtnl_unlock();
+
+ /* the sessions are freed by now, do not touch 'list' again */
+
+ return 0;
+}
+
static int ipoe_nl_cmd_modify(struct sk_buff *skb, struct genl_info *info)
{
int ret = -EINVAL, r = 0;
@@ -1896,6 +1942,14 @@ static const struct genl_ops ipoe_nl_ops[] = {
.policy = ipoe_nl_policy,
#endif
},
+ {
+ .cmd = IPOE_CMD_FLUSH,
+ .doit = ipoe_nl_cmd_flush,
+ .flags = GENL_ADMIN_PERM,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)
+ .policy = ipoe_nl_policy,
+#endif
+ },
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) && RHEL_MAJOR < 7
diff --git a/drivers/ipoe/ipoe.h b/drivers/ipoe/ipoe.h
index 4097e2da..2d041c50 100644
--- a/drivers/ipoe/ipoe.h
+++ b/drivers/ipoe/ipoe.h
@@ -16,6 +16,7 @@ enum {
IPOE_CMD_DEL_EXCLUDE,
IPOE_CMD_ADD_NET,
IPOE_CMD_DEL_NET,
+ IPOE_CMD_FLUSH,
__IPOE_CMD_MAX,
};