* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
@ 2019-02-05 2:57 Callum Sinclair
2019-02-05 2:58 ` Callum Sinclair
0 siblings, 1 reply; 12+ messages in thread
From: Callum Sinclair @ 2019-02-05 2:57 UTC (permalink / raw)
To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
Created a way to clear the multicast forwarding cache on a socket
without having to either remove the entries manually using the delete
entry socket option or destroy and recreate the multicast socket.
Patch Set 2:
- Fix Compile Errors
Patch Set 3:
- Fix Style Errors
Callum Sinclair (1):
ipmr: ip6mr: Create new sockopt to clear mfc cache only
include/uapi/linux/mroute.h | 3 ++-
include/uapi/linux/mroute6.h | 3 ++-
net/ipv4/ipmr.c | 40 +++++++++++++++++++++----------
net/ipv6/ip6mr.c | 46 +++++++++++++++++++++++-------------
4 files changed, 61 insertions(+), 31 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-02-05 2:57 [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only Callum Sinclair
@ 2019-02-05 2:58 ` Callum Sinclair
2019-02-05 19:52 ` Nikolay Aleksandrov
0 siblings, 1 reply; 12+ messages in thread
From: Callum Sinclair @ 2019-02-05 2:58 UTC (permalink / raw)
To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
Currently the only way to clear the mfc cache was to delete the entries
one by one using the MRT_DEL_MFC socket option or to destroy and
recreate the socket.
Create a new socket option which will clear the multicast forwarding
cache on the socket without destroying the socket.
Signed-off-by: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
---
include/uapi/linux/mroute.h | 3 ++-
include/uapi/linux/mroute6.h | 3 ++-
net/ipv4/ipmr.c | 40 +++++++++++++++++++++----------
net/ipv6/ip6mr.c | 46 +++++++++++++++++++++++-------------
4 files changed, 61 insertions(+), 31 deletions(-)
diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
index 5d37a9ccce63..8a0beb885cd9 100644
--- a/include/uapi/linux/mroute.h
+++ b/include/uapi/linux/mroute.h
@@ -28,7 +28,8 @@
#define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */
#define MRT_ADD_MFC_PROXY (MRT_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT_DEL_MFC_PROXY (MRT_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT_MAX (MRT_BASE+11)
+#define MRT_DEL_MFC_ALL (MRT_BASE+12) /* Del all multicast entries */
+#define MRT_MAX (MRT_BASE+12)
#define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
index 9999cc006390..7def70cdf571 100644
--- a/include/uapi/linux/mroute6.h
+++ b/include/uapi/linux/mroute6.h
@@ -31,7 +31,8 @@
#define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */
#define MRT6_ADD_MFC_PROXY (MRT6_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT6_DEL_MFC_PROXY (MRT6_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT6_MAX (MRT6_BASE+11)
+#define MRT6_DEL_MFC_ALL (MRT6_BASE+12) /* Del all multicast entries */
+#define MRT6_MAX (MRT6_BASE+12)
#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ddbf8c9a1abb..ccfeebd38e1a 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1298,22 +1298,12 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
return 0;
}
-/* Close the multicast socket, and clear the vif tables etc */
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
{
struct net *net = read_pnet(&mrt->net);
- struct mr_mfc *c, *tmp;
struct mfc_cache *cache;
- LIST_HEAD(list);
- int i;
-
- /* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- vif_delete(mrt, i, 0, &list);
- }
- unregister_netdevice_many(&list);
+ struct mr_mfc *c, *tmp;
/* Wipe the cache */
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
@@ -1340,6 +1330,23 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
}
}
+/* Close the multicast socket, and clear the vif tables etc */
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+ LIST_HEAD(list);
+ int i;
+
+ /* Shut down all active vif entries */
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ vif_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
+
+ mroute_clean_cache(mrt, all);
+}
+
/* called from ip_ra_control(), before an RCU grace period,
* we dont need to call synchronize_rcu() here
*/
@@ -1482,6 +1489,13 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
sk == rtnl_dereference(mrt->mroute_sk),
parent);
break;
+ case MRT_DEL_MFC_ALL:
+ rtnl_lock();
+ ipmr_for_each_table(mrt, net) {
+ mroute_clean_cache(mrt, true);
+ }
+ rtnl_unlock();
+ break;
/* Control PIM assert. */
case MRT_ASSERT:
if (optlen != sizeof(val)) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 30337b38274b..0168420d217b 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1492,25 +1492,11 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
return 0;
}
-/*
- * Close the multicast socket, and clear the vif tables etc
- */
-
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
{
struct mr_mfc *c, *tmp;
- LIST_HEAD(list);
- int i;
-
- /* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- mif6_delete(mrt, i, 0, &list);
- }
- unregister_netdevice_many(&list);
- /* Wipe the cache */
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
if (!all && (c->mfc_flags & MFC_STATIC))
continue;
@@ -1536,6 +1522,27 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
}
}
+/*
+ * Close the multicast socket, and clear the vif tables etc
+ */
+
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+ LIST_HEAD(list);
+ int i;
+
+ /* Shut down all active vif entries */
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ mif6_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
+
+ /* Wipe the cache */
+ mroute_clean_cache(mrt, all);
+}
+
static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
{
int err = 0;
@@ -1703,6 +1710,13 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
parent);
rtnl_unlock();
return ret;
+ case MRT6_DEL_MFC_ALL:
+ rtnl_lock();
+ ip6mr_for_each_table(mrt, net) {
+ mroute_clean_cache(mrt, true);
+ }
+ rtnl_unlock();
+ return 0;
/*
* Control PIM assert (to activate pim will activate assert)
--
2.20.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-02-05 2:58 ` Callum Sinclair
@ 2019-02-05 19:52 ` Nikolay Aleksandrov
0 siblings, 0 replies; 12+ messages in thread
From: Nikolay Aleksandrov @ 2019-02-05 19:52 UTC (permalink / raw)
To: Callum Sinclair, davem, kuznet, yoshfuji, netdev, linux-kernel,
Roopa Prabhu
On 05/02/2019 04:58, Callum Sinclair wrote:
> Currently the only way to clear the mfc cache was to delete the entries
> one by one using the MRT_DEL_MFC socket option or to destroy and
> recreate the socket.
>
> Create a new socket option which will clear the multicast forwarding
> cache on the socket without destroying the socket.
>
> Signed-off-by: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
> ---
> include/uapi/linux/mroute.h | 3 ++-
> include/uapi/linux/mroute6.h | 3 ++-
> net/ipv4/ipmr.c | 40 +++++++++++++++++++++----------
> net/ipv6/ip6mr.c | 46 +++++++++++++++++++++++-------------
> 4 files changed, 61 insertions(+), 31 deletions(-)
>
Hi,
Why don't you do it per-table ? That is - use the selected table and flush
only its entries, I think that would be more useful. Also would be nice to
make the interface flush optional, e.g. depending on a user-supplied value.
Some people would like to flush only the MFC entries without deleting the
devices. Since it's called DEL_MFC_ALL, I'd expect this call to act only
on the MFC entries and not the device list, but it also flushes that.
I'd rename it to MRT_FLUSH with an argument which chooses to flush MFCs +
VIFs based on flags (so you could flush either one separately).
Thanks,
Nik
> diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
> index 5d37a9ccce63..8a0beb885cd9 100644
> --- a/include/uapi/linux/mroute.h
> +++ b/include/uapi/linux/mroute.h
> @@ -28,7 +28,8 @@
> #define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */
> #define MRT_ADD_MFC_PROXY (MRT_BASE+10) /* Add a (*,*|G) mfc entry */
> #define MRT_DEL_MFC_PROXY (MRT_BASE+11) /* Del a (*,*|G) mfc entry */
> -#define MRT_MAX (MRT_BASE+11)
> +#define MRT_DEL_MFC_ALL (MRT_BASE+12) /* Del all multicast entries */
> +#define MRT_MAX (MRT_BASE+12)
>
> #define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
> #define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
> diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
> index 9999cc006390..7def70cdf571 100644
> --- a/include/uapi/linux/mroute6.h
> +++ b/include/uapi/linux/mroute6.h
> @@ -31,7 +31,8 @@
> #define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */
> #define MRT6_ADD_MFC_PROXY (MRT6_BASE+10) /* Add a (*,*|G) mfc entry */
> #define MRT6_DEL_MFC_PROXY (MRT6_BASE+11) /* Del a (*,*|G) mfc entry */
> -#define MRT6_MAX (MRT6_BASE+11)
> +#define MRT6_DEL_MFC_ALL (MRT6_BASE+12) /* Del all multicast entries */
> +#define MRT6_MAX (MRT6_BASE+12)
>
> #define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
> #define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
> diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
> index ddbf8c9a1abb..ccfeebd38e1a 100644
> --- a/net/ipv4/ipmr.c
> +++ b/net/ipv4/ipmr.c
> @@ -1298,22 +1298,12 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
> return 0;
> }
>
> -/* Close the multicast socket, and clear the vif tables etc */
> -static void mroute_clean_tables(struct mr_table *mrt, bool all)
> +/* Clear the vif tables */
> +static void mroute_clean_cache(struct mr_table *mrt, bool all)
> {
> struct net *net = read_pnet(&mrt->net);
> - struct mr_mfc *c, *tmp;
> struct mfc_cache *cache;
> - LIST_HEAD(list);
> - int i;
> -
> - /* Shut down all active vif entries */
> - for (i = 0; i < mrt->maxvif; i++) {
> - if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> - continue;
> - vif_delete(mrt, i, 0, &list);
> - }
> - unregister_netdevice_many(&list);
> + struct mr_mfc *c, *tmp;
>
> /* Wipe the cache */
> list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
> @@ -1340,6 +1330,23 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
> }
> }
>
> +/* Close the multicast socket, and clear the vif tables etc */
> +static void mroute_clean_tables(struct mr_table *mrt, bool all)
> +{
> + LIST_HEAD(list);
> + int i;
> +
> + /* Shut down all active vif entries */
> + for (i = 0; i < mrt->maxvif; i++) {
> + if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> + continue;
> + vif_delete(mrt, i, 0, &list);
> + }
> + unregister_netdevice_many(&list);
> +
> + mroute_clean_cache(mrt, all);
> +}
> +
> /* called from ip_ra_control(), before an RCU grace period,
> * we dont need to call synchronize_rcu() here
> */
> @@ -1482,6 +1489,13 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
> sk == rtnl_dereference(mrt->mroute_sk),
> parent);
> break;
> + case MRT_DEL_MFC_ALL:
> + rtnl_lock();
> + ipmr_for_each_table(mrt, net) {
> + mroute_clean_cache(mrt, true);
> + }
> + rtnl_unlock();
> + break;
> /* Control PIM assert. */
> case MRT_ASSERT:
> if (optlen != sizeof(val)) {
> diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
> index 30337b38274b..0168420d217b 100644
> --- a/net/ipv6/ip6mr.c
> +++ b/net/ipv6/ip6mr.c
> @@ -1492,25 +1492,11 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
> return 0;
> }
>
> -/*
> - * Close the multicast socket, and clear the vif tables etc
> - */
> -
> -static void mroute_clean_tables(struct mr_table *mrt, bool all)
> +/* Clear the vif tables */
> +static void mroute_clean_cache(struct mr_table *mrt, bool all)
> {
> struct mr_mfc *c, *tmp;
> - LIST_HEAD(list);
> - int i;
> -
> - /* Shut down all active vif entries */
> - for (i = 0; i < mrt->maxvif; i++) {
> - if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> - continue;
> - mif6_delete(mrt, i, 0, &list);
> - }
> - unregister_netdevice_many(&list);
>
> - /* Wipe the cache */
> list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
> if (!all && (c->mfc_flags & MFC_STATIC))
> continue;
> @@ -1536,6 +1522,27 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
> }
> }
>
> +/*
> + * Close the multicast socket, and clear the vif tables etc
> + */
> +
> +static void mroute_clean_tables(struct mr_table *mrt, bool all)
> +{
> + LIST_HEAD(list);
> + int i;
> +
> + /* Shut down all active vif entries */
> + for (i = 0; i < mrt->maxvif; i++) {
> + if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> + continue;
> + mif6_delete(mrt, i, 0, &list);
> + }
> + unregister_netdevice_many(&list);
> +
> + /* Wipe the cache */
> + mroute_clean_cache(mrt, all);
> +}
> +
> static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
> {
> int err = 0;
> @@ -1703,6 +1710,13 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
> parent);
> rtnl_unlock();
> return ret;
> + case MRT6_DEL_MFC_ALL:
> + rtnl_lock();
> + ip6mr_for_each_table(mrt, net) {
> + mroute_clean_cache(mrt, true);
> + }
> + rtnl_unlock();
> + return 0;
>
> /*
> * Control PIM assert (to activate pim will activate assert)
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-02-07 2:08 ` [PATCH] " Callum Sinclair
@ 2019-02-07 6:32 ` Nikolay Aleksandrov
0 siblings, 0 replies; 12+ messages in thread
From: Nikolay Aleksandrov @ 2019-02-07 6:32 UTC (permalink / raw)
To: Callum Sinclair, davem, kuznet, yoshfuji, netdev, linux-kernel
On 07/02/2019 04:08, Callum Sinclair wrote:
> Currently the only way to clear the mfc cache was to delete the entries
> one by one using the MRT_DEL_MFC socket option or to destroy and
> recreate the socket.
>
> Create a new socket option which will clear the multicast forwarding
> cache on the socket without destroying the socket.
>
> Signed-off-by: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
> ---
> include/uapi/linux/mroute.h | 7 +++-
> include/uapi/linux/mroute6.h | 7 +++-
> net/ipv4/ipmr.c | 69 +++++++++++++++++++++-------------
> net/ipv6/ip6mr.c | 73 ++++++++++++++++++++++--------------
> 4 files changed, 99 insertions(+), 57 deletions(-)
>
Hi,
Thanks for working on this. I think you missed one comment, this still seems
to clean all tables even though the socket has a table assigned. Could it
act only on that table ? All of the MRT calls besides the init act only on
the initialized table.
Also you're not checking if optlen is proper size, and I wonder which kernel is this
based on ? Because in net-next ip_mroute_setsockopt() takes rtnl in the beginning
and releases it in the end with the exception of MRT_DONE which needs to release it
earlier, the code below would cause a deadlock trying to get rtnl again in MRT_FLUSH.
This patch should be targeted at net-next, please indicate that also in your subject:
e.g. [PATCH net-next].
Thanks,
Nik
> diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
> index 5d37a9ccce63..2d475edc3ec3 100644
> --- a/include/uapi/linux/mroute.h
> +++ b/include/uapi/linux/mroute.h
> @@ -28,12 +28,17 @@
> #define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */
> #define MRT_ADD_MFC_PROXY (MRT_BASE+10) /* Add a (*,*|G) mfc entry */
> #define MRT_DEL_MFC_PROXY (MRT_BASE+11) /* Del a (*,*|G) mfc entry */
> -#define MRT_MAX (MRT_BASE+11)
> +#define MRT_FLUSH (MRT_BASE+12) /* Flush all multicast entries and vifs */
> +#define MRT_MAX (MRT_BASE+12)
>
> #define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
> #define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
> #define SIOCGETRPF (SIOCPROTOPRIVATE+2)
>
> +/* Flags used for MRT_FLUSH */
> +#define MRT_FLUSH_ENTRIES 1 /* For flushing all multicast entries */
> +#define MRT_FLUSH_VIFS 2 /* For flushing all multicast vifs */
> +
> #define MAXVIFS 32
> typedef unsigned long vifbitmap_t; /* User mode code depends on this lot */
> typedef unsigned short vifi_t;
> diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
> index 9999cc006390..b04094d997c8 100644
> --- a/include/uapi/linux/mroute6.h
> +++ b/include/uapi/linux/mroute6.h
> @@ -31,12 +31,17 @@
> #define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */
> #define MRT6_ADD_MFC_PROXY (MRT6_BASE+10) /* Add a (*,*|G) mfc entry */
> #define MRT6_DEL_MFC_PROXY (MRT6_BASE+11) /* Del a (*,*|G) mfc entry */
> -#define MRT6_MAX (MRT6_BASE+11)
> +#define MRT6_FLUSH (MRT6_BASE+12) /* Flush all multicast entries and vifs */
> +#define MRT6_MAX (MRT6_BASE+12)
>
> #define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
> #define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
> #define SIOCGETRPF (SIOCPROTOPRIVATE+2)
>
> +/* Flags used for MRT6_FLUSH*/
> +#define MRT6_FLUSH_ENTRIES 1 /* For flushing all multicast entries */
> +#define MRT6_FLUSH_VIFS 2 /* For flushing all multicast vifs */
> +
> #define MAXMIFS 32
> typedef unsigned long mifbitmap_t; /* User mode code depends on this lot */
> typedef unsigned short mifi_t;
> diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
> index ddbf8c9a1abb..2eb569138569 100644
> --- a/net/ipv4/ipmr.c
> +++ b/net/ipv4/ipmr.c
> @@ -416,7 +416,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
> static void ipmr_free_table(struct mr_table *mrt)
> {
> del_timer_sync(&mrt->ipmr_expire_timer);
> - mroute_clean_tables(mrt, true);
> + mroute_clean_tables(mrt, true, MRT_FLUSH_VIFS | MRT_FLUSH_ENTRIES);
> rhltable_destroy(&mrt->mfc_hash);
> kfree(mrt);
> }
> @@ -1299,44 +1299,48 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
> }
>
> /* Close the multicast socket, and clear the vif tables etc */
> -static void mroute_clean_tables(struct mr_table *mrt, bool all)
> +static void mroute_clean_tables(struct mr_table *mrt, bool all, int flags)
> {
> struct net *net = read_pnet(&mrt->net);
> - struct mr_mfc *c, *tmp;
> struct mfc_cache *cache;
> + struct mr_mfc *c, *tmp;
> LIST_HEAD(list);
> int i;
>
> /* Shut down all active vif entries */
> - for (i = 0; i < mrt->maxvif; i++) {
> - if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> - continue;
> - vif_delete(mrt, i, 0, &list);
> + if (flags & MRT_FLUSH_VIFS) {
> + for (i = 0; i < mrt->maxvif; i++) {
> + if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> + continue;
> + vif_delete(mrt, i, 0, &list);
> + }
> + unregister_netdevice_many(&list);
> }
> - unregister_netdevice_many(&list);
>
> /* Wipe the cache */
> - list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
> - if (!all && (c->mfc_flags & MFC_STATIC))
> - continue;
> - rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
> - list_del_rcu(&c->list);
> - cache = (struct mfc_cache *)c;
> - call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
> - mrt->id);
> - mroute_netlink_event(mrt, cache, RTM_DELROUTE);
> - mr_cache_put(c);
> - }
> -
> - if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
> - spin_lock_bh(&mfc_unres_lock);
> - list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
> - list_del(&c->list);
> + if (flags & MRT_FLUSH_ENTRIES) {
> + list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
> + if (!all && (c->mfc_flags & MFC_STATIC))
> + continue;
> + rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
> + list_del_rcu(&c->list);
> cache = (struct mfc_cache *)c;
> + call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
> + mrt->id);
> mroute_netlink_event(mrt, cache, RTM_DELROUTE);
> - ipmr_destroy_unres(mrt, cache);
> + mr_cache_put(c);
> + }
> +
> + if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
> + spin_lock_bh(&mfc_unres_lock);
> + list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
> + list_del(&c->list);
> + cache = (struct mfc_cache *)c;
> + mroute_netlink_event(mrt, cache, RTM_DELROUTE);
> + ipmr_destroy_unres(mrt, cache);
> + }
> + spin_unlock_bh(&mfc_unres_lock);
> }
> - spin_unlock_bh(&mfc_unres_lock);
> }
> }
>
> @@ -1357,7 +1361,7 @@ static void mrtsock_destruct(struct sock *sk)
> NETCONFA_IFINDEX_ALL,
> net->ipv4.devconf_all);
> RCU_INIT_POINTER(mrt->mroute_sk, NULL);
> - mroute_clean_tables(mrt, false);
> + mroute_clean_tables(mrt, false, MRT_FLUSH_VIFS | MRT_FLUSH_ENTRIES);
> }
> }
> rtnl_unlock();
> @@ -1482,6 +1486,17 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
> sk == rtnl_dereference(mrt->mroute_sk),
> parent);
> break;
> + case MRT_FLUSH:
> + if (get_user(val, (int __user *)optval)) {
> + ret = -EFAULT;
> + break;
> + }
> + rtnl_lock();
> + ipmr_for_each_table(mrt, net) {
> + mroute_clean_tables(mrt, true, val);
> + }
> + rtnl_unlock();
> + break;
> /* Control PIM assert. */
> case MRT_ASSERT:
> if (optlen != sizeof(val)) {
> diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
> index 30337b38274b..473c83d197fe 100644
> --- a/net/ipv6/ip6mr.c
> +++ b/net/ipv6/ip6mr.c
> @@ -393,7 +393,7 @@ static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
> static void ip6mr_free_table(struct mr_table *mrt)
> {
> del_timer_sync(&mrt->ipmr_expire_timer);
> - mroute_clean_tables(mrt, true);
> + mroute_clean_tables(mrt, true, MRT6_FLUSH_VIFS | MRT6_FLUSH_ENTRIES);
> rhltable_destroy(&mrt->mfc_hash);
> kfree(mrt);
> }
> @@ -1496,43 +1496,47 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
> * Close the multicast socket, and clear the vif tables etc
> */
>
> -static void mroute_clean_tables(struct mr_table *mrt, bool all)
> +static void mroute_clean_tables(struct mr_table *mrt, bool all, int flags)
> {
> struct mr_mfc *c, *tmp;
> LIST_HEAD(list);
> int i;
>
> /* Shut down all active vif entries */
> - for (i = 0; i < mrt->maxvif; i++) {
> - if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> - continue;
> - mif6_delete(mrt, i, 0, &list);
> + if (flags & MRT6_FLUSH_VIFS) {
> + for (i = 0; i < mrt->maxvif; i++) {
> + if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> + continue;
> + mif6_delete(mrt, i, 0, &list);
> + }
> + unregister_netdevice_many(&list);
> }
> - unregister_netdevice_many(&list);
>
> /* Wipe the cache */
> - list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
> - if (!all && (c->mfc_flags & MFC_STATIC))
> - continue;
> - rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
> - list_del_rcu(&c->list);
> - mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
> - mr_cache_put(c);
> - }
> + if (flags & MRT6_FLUSH_ENTRIES) {
> + list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
> + if (!all && (c->mfc_flags & MFC_STATIC))
> + continue;
> + rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
> + list_del_rcu(&c->list);
> + mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
> + mr_cache_put(c);
> + }
>
> - if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
> - spin_lock_bh(&mfc_unres_lock);
> - list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
> - list_del(&c->list);
> - call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
> - FIB_EVENT_ENTRY_DEL,
> - (struct mfc6_cache *)c,
> - mrt->id);
> - mr6_netlink_event(mrt, (struct mfc6_cache *)c,
> - RTM_DELROUTE);
> - ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
> + if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
> + spin_lock_bh(&mfc_unres_lock);
> + list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
> + list_del(&c->list);
> + call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
> + FIB_EVENT_ENTRY_DEL,
> + (struct mfc6_cache *)c,
> + mrt->id);
> + mr6_netlink_event(mrt, (struct mfc6_cache *)c,
> + RTM_DELROUTE);
> + ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
> + }
> + spin_unlock_bh(&mfc_unres_lock);
> }
> - spin_unlock_bh(&mfc_unres_lock);
> }
> }
>
> @@ -1588,7 +1592,7 @@ int ip6mr_sk_done(struct sock *sk)
> NETCONFA_IFINDEX_ALL,
> net->ipv6.devconf_all);
>
> - mroute_clean_tables(mrt, false);
> + mroute_clean_tables(mrt, false, MRT6_FLUSH_VIFS | MRT6_FLUSH_ENTRIES);
> err = 0;
> break;
> }
> @@ -1703,6 +1707,19 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
> parent);
> rtnl_unlock();
> return ret;
> + case MRT6_DEL_MFC_ALL:
> + {
> + int flags;
> +
> + if (get_user(flags, (int __user *)optval))
> + return -EFAULT;
> + rtnl_lock();
> + ip6mr_for_each_table(mrt, net) {
> + mroute_clean_tables(mrt, true, flags);
> + }
> + rtnl_unlock();
> + return 0;
> + }
>
> /*
> * Control PIM assert (to activate pim will activate assert)
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-02-07 2:08 Callum Sinclair
@ 2019-02-07 2:08 ` Callum Sinclair
2019-02-07 6:32 ` Nikolay Aleksandrov
0 siblings, 1 reply; 12+ messages in thread
From: Callum Sinclair @ 2019-02-07 2:08 UTC (permalink / raw)
To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
Currently the only way to clear the mfc cache was to delete the entries
one by one using the MRT_DEL_MFC socket option or to destroy and
recreate the socket.
Create a new socket option which will clear the multicast forwarding
cache on the socket without destroying the socket.
Signed-off-by: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
---
include/uapi/linux/mroute.h | 7 +++-
include/uapi/linux/mroute6.h | 7 +++-
net/ipv4/ipmr.c | 69 +++++++++++++++++++++-------------
net/ipv6/ip6mr.c | 73 ++++++++++++++++++++++--------------
4 files changed, 99 insertions(+), 57 deletions(-)
diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
index 5d37a9ccce63..2d475edc3ec3 100644
--- a/include/uapi/linux/mroute.h
+++ b/include/uapi/linux/mroute.h
@@ -28,12 +28,17 @@
#define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */
#define MRT_ADD_MFC_PROXY (MRT_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT_DEL_MFC_PROXY (MRT_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT_MAX (MRT_BASE+11)
+#define MRT_FLUSH (MRT_BASE+12) /* Flush all multicast entries and vifs */
+#define MRT_MAX (MRT_BASE+12)
#define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
#define SIOCGETRPF (SIOCPROTOPRIVATE+2)
+/* Flags used for MRT_FLUSH */
+#define MRT_FLUSH_ENTRIES 1 /* For flushing all multicast entries */
+#define MRT_FLUSH_VIFS 2 /* For flushing all multicast vifs */
+
#define MAXVIFS 32
typedef unsigned long vifbitmap_t; /* User mode code depends on this lot */
typedef unsigned short vifi_t;
diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
index 9999cc006390..b04094d997c8 100644
--- a/include/uapi/linux/mroute6.h
+++ b/include/uapi/linux/mroute6.h
@@ -31,12 +31,17 @@
#define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */
#define MRT6_ADD_MFC_PROXY (MRT6_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT6_DEL_MFC_PROXY (MRT6_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT6_MAX (MRT6_BASE+11)
+#define MRT6_FLUSH (MRT6_BASE+12) /* Flush all multicast entries and vifs */
+#define MRT6_MAX (MRT6_BASE+12)
#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
#define SIOCGETRPF (SIOCPROTOPRIVATE+2)
+/* Flags used for MRT6_FLUSH*/
+#define MRT6_FLUSH_ENTRIES 1 /* For flushing all multicast entries */
+#define MRT6_FLUSH_VIFS 2 /* For flushing all multicast vifs */
+
#define MAXMIFS 32
typedef unsigned long mifbitmap_t; /* User mode code depends on this lot */
typedef unsigned short mifi_t;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ddbf8c9a1abb..2eb569138569 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -416,7 +416,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
static void ipmr_free_table(struct mr_table *mrt)
{
del_timer_sync(&mrt->ipmr_expire_timer);
- mroute_clean_tables(mrt, true);
+ mroute_clean_tables(mrt, true, MRT_FLUSH_VIFS | MRT_FLUSH_ENTRIES);
rhltable_destroy(&mrt->mfc_hash);
kfree(mrt);
}
@@ -1299,44 +1299,48 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
}
/* Close the multicast socket, and clear the vif tables etc */
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+static void mroute_clean_tables(struct mr_table *mrt, bool all, int flags)
{
struct net *net = read_pnet(&mrt->net);
- struct mr_mfc *c, *tmp;
struct mfc_cache *cache;
+ struct mr_mfc *c, *tmp;
LIST_HEAD(list);
int i;
/* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- vif_delete(mrt, i, 0, &list);
+ if (flags & MRT_FLUSH_VIFS) {
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ vif_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
}
- unregister_netdevice_many(&list);
/* Wipe the cache */
- list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
- if (!all && (c->mfc_flags & MFC_STATIC))
- continue;
- rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
- list_del_rcu(&c->list);
- cache = (struct mfc_cache *)c;
- call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
- mrt->id);
- mroute_netlink_event(mrt, cache, RTM_DELROUTE);
- mr_cache_put(c);
- }
-
- if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
- spin_lock_bh(&mfc_unres_lock);
- list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
- list_del(&c->list);
+ if (flags & MRT_FLUSH_ENTRIES) {
+ list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
+ if (!all && (c->mfc_flags & MFC_STATIC))
+ continue;
+ rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
+ list_del_rcu(&c->list);
cache = (struct mfc_cache *)c;
+ call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
+ mrt->id);
mroute_netlink_event(mrt, cache, RTM_DELROUTE);
- ipmr_destroy_unres(mrt, cache);
+ mr_cache_put(c);
+ }
+
+ if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
+ spin_lock_bh(&mfc_unres_lock);
+ list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
+ list_del(&c->list);
+ cache = (struct mfc_cache *)c;
+ mroute_netlink_event(mrt, cache, RTM_DELROUTE);
+ ipmr_destroy_unres(mrt, cache);
+ }
+ spin_unlock_bh(&mfc_unres_lock);
}
- spin_unlock_bh(&mfc_unres_lock);
}
}
@@ -1357,7 +1361,7 @@ static void mrtsock_destruct(struct sock *sk)
NETCONFA_IFINDEX_ALL,
net->ipv4.devconf_all);
RCU_INIT_POINTER(mrt->mroute_sk, NULL);
- mroute_clean_tables(mrt, false);
+ mroute_clean_tables(mrt, false, MRT_FLUSH_VIFS | MRT_FLUSH_ENTRIES);
}
}
rtnl_unlock();
@@ -1482,6 +1486,17 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
sk == rtnl_dereference(mrt->mroute_sk),
parent);
break;
+ case MRT_FLUSH:
+ if (get_user(val, (int __user *)optval)) {
+ ret = -EFAULT;
+ break;
+ }
+ rtnl_lock();
+ ipmr_for_each_table(mrt, net) {
+ mroute_clean_tables(mrt, true, val);
+ }
+ rtnl_unlock();
+ break;
/* Control PIM assert. */
case MRT_ASSERT:
if (optlen != sizeof(val)) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 30337b38274b..473c83d197fe 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -393,7 +393,7 @@ static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
static void ip6mr_free_table(struct mr_table *mrt)
{
del_timer_sync(&mrt->ipmr_expire_timer);
- mroute_clean_tables(mrt, true);
+ mroute_clean_tables(mrt, true, MRT6_FLUSH_VIFS | MRT6_FLUSH_ENTRIES);
rhltable_destroy(&mrt->mfc_hash);
kfree(mrt);
}
@@ -1496,43 +1496,47 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
* Close the multicast socket, and clear the vif tables etc
*/
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+static void mroute_clean_tables(struct mr_table *mrt, bool all, int flags)
{
struct mr_mfc *c, *tmp;
LIST_HEAD(list);
int i;
/* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- mif6_delete(mrt, i, 0, &list);
+ if (flags & MRT6_FLUSH_VIFS) {
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ mif6_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
}
- unregister_netdevice_many(&list);
/* Wipe the cache */
- list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
- if (!all && (c->mfc_flags & MFC_STATIC))
- continue;
- rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
- list_del_rcu(&c->list);
- mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
- mr_cache_put(c);
- }
+ if (flags & MRT6_FLUSH_ENTRIES) {
+ list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
+ if (!all && (c->mfc_flags & MFC_STATIC))
+ continue;
+ rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
+ list_del_rcu(&c->list);
+ mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
+ mr_cache_put(c);
+ }
- if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
- spin_lock_bh(&mfc_unres_lock);
- list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
- list_del(&c->list);
- call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
- FIB_EVENT_ENTRY_DEL,
- (struct mfc6_cache *)c,
- mrt->id);
- mr6_netlink_event(mrt, (struct mfc6_cache *)c,
- RTM_DELROUTE);
- ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
+ if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
+ spin_lock_bh(&mfc_unres_lock);
+ list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
+ list_del(&c->list);
+ call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
+ FIB_EVENT_ENTRY_DEL,
+ (struct mfc6_cache *)c,
+ mrt->id);
+ mr6_netlink_event(mrt, (struct mfc6_cache *)c,
+ RTM_DELROUTE);
+ ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
+ }
+ spin_unlock_bh(&mfc_unres_lock);
}
- spin_unlock_bh(&mfc_unres_lock);
}
}
@@ -1588,7 +1592,7 @@ int ip6mr_sk_done(struct sock *sk)
NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all);
- mroute_clean_tables(mrt, false);
+ mroute_clean_tables(mrt, false, MRT6_FLUSH_VIFS | MRT6_FLUSH_ENTRIES);
err = 0;
break;
}
@@ -1703,6 +1707,19 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
parent);
rtnl_unlock();
return ret;
+ case MRT6_DEL_MFC_ALL:
+ {
+ int flags;
+
+ if (get_user(flags, (int __user *)optval))
+ return -EFAULT;
+ rtnl_lock();
+ ip6mr_for_each_table(mrt, net) {
+ mroute_clean_tables(mrt, true, flags);
+ }
+ rtnl_unlock();
+ return 0;
+ }
/*
* Control PIM assert (to activate pim will activate assert)
--
2.20.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-01-30 20:52 ` Callum Sinclair
@ 2019-02-03 3:42 ` David Miller
0 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2019-02-03 3:42 UTC (permalink / raw)
To: callum.sinclair; +Cc: kuznet, yoshfuji, nikolay, netdev, linux-kernel
From: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
Date: Thu, 31 Jan 2019 09:52:09 +1300
>
> -/* Close the multicast socket, and clear the vif tables etc */
> -static void mroute_clean_tables(struct mr_table *mrt, bool all)
> +/* Clear the vif tables */
> +static void mroute_clean_cache(struct mr_table *mrt, bool all)
> {
> - struct net *net = read_pnet(&mrt->net);
> struct mr_mfc *c, *tmp;
> struct mfc_cache *cache;
> - LIST_HEAD(list);
> - int i;
> -
> - /* Shut down all active vif entries */
> - for (i = 0; i < mrt->maxvif; i++) {
> - if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
> - continue;
> - vif_delete(mrt, i, 0, &list);
> - }
> - unregister_netdevice_many(&list);
> + struct net *net = read_pnet(&mrt->net);
Please do not change the order of local variables like this, you're breaking
the correct reverse christmas tree ordering of longest to shortest line for
local variable declarations.
Thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-01-30 20:52 Callum Sinclair
@ 2019-01-30 20:52 ` Callum Sinclair
2019-02-03 3:42 ` David Miller
0 siblings, 1 reply; 12+ messages in thread
From: Callum Sinclair @ 2019-01-30 20:52 UTC (permalink / raw)
To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
Currently the only way to clear the mfc cache was to delete the entries
one by one using the MRT_DEL_MFC socket option or to destroy and
recreate the socket.
Create a new socket option which will clear the multicast forwarding
cache on the socket without destroying the socket.
Signed-off-by: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
---
include/uapi/linux/mroute.h | 3 ++-
include/uapi/linux/mroute6.h | 3 ++-
net/ipv4/ipmr.c | 40 +++++++++++++++++++++----------
net/ipv6/ip6mr.c | 46 +++++++++++++++++++++++-------------
4 files changed, 61 insertions(+), 31 deletions(-)
diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
index 5d37a9ccce63..8a0beb885cd9 100644
--- a/include/uapi/linux/mroute.h
+++ b/include/uapi/linux/mroute.h
@@ -28,7 +28,8 @@
#define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */
#define MRT_ADD_MFC_PROXY (MRT_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT_DEL_MFC_PROXY (MRT_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT_MAX (MRT_BASE+11)
+#define MRT_DEL_MFC_ALL (MRT_BASE+12) /* Del all multicast entries */
+#define MRT_MAX (MRT_BASE+12)
#define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
index 9999cc006390..7def70cdf571 100644
--- a/include/uapi/linux/mroute6.h
+++ b/include/uapi/linux/mroute6.h
@@ -31,7 +31,8 @@
#define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */
#define MRT6_ADD_MFC_PROXY (MRT6_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT6_DEL_MFC_PROXY (MRT6_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT6_MAX (MRT6_BASE+11)
+#define MRT6_DEL_MFC_ALL (MRT6_BASE+12) /* Del all multicast entries */
+#define MRT6_MAX (MRT6_BASE+12)
#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ddbf8c9a1abb..b996d0f70e5c 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1298,22 +1298,12 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
return 0;
}
-/* Close the multicast socket, and clear the vif tables etc */
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
{
- struct net *net = read_pnet(&mrt->net);
struct mr_mfc *c, *tmp;
struct mfc_cache *cache;
- LIST_HEAD(list);
- int i;
-
- /* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- vif_delete(mrt, i, 0, &list);
- }
- unregister_netdevice_many(&list);
+ struct net *net = read_pnet(&mrt->net);
/* Wipe the cache */
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
@@ -1340,6 +1330,23 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
}
}
+/* Close the multicast socket, and clear the vif tables etc */
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+ LIST_HEAD(list);
+ int i;
+
+ /* Shut down all active vif entries */
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ vif_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
+
+ mroute_clean_cache(mrt, all);
+}
+
/* called from ip_ra_control(), before an RCU grace period,
* we dont need to call synchronize_rcu() here
*/
@@ -1482,6 +1489,13 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
sk == rtnl_dereference(mrt->mroute_sk),
parent);
break;
+ case MRT_DEL_MFC_ALL:
+ rtnl_lock();
+ ipmr_for_each_table(mrt, net) {
+ mroute_clean_cache(mrt, true);
+ }
+ rtnl_unlock();
+ break;
/* Control PIM assert. */
case MRT_ASSERT:
if (optlen != sizeof(val)) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 30337b38274b..0168420d217b 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1492,25 +1492,11 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
return 0;
}
-/*
- * Close the multicast socket, and clear the vif tables etc
- */
-
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
{
struct mr_mfc *c, *tmp;
- LIST_HEAD(list);
- int i;
-
- /* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- mif6_delete(mrt, i, 0, &list);
- }
- unregister_netdevice_many(&list);
- /* Wipe the cache */
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
if (!all && (c->mfc_flags & MFC_STATIC))
continue;
@@ -1536,6 +1522,27 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
}
}
+/*
+ * Close the multicast socket, and clear the vif tables etc
+ */
+
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+ LIST_HEAD(list);
+ int i;
+
+ /* Shut down all active vif entries */
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ mif6_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
+
+ /* Wipe the cache */
+ mroute_clean_cache(mrt, all);
+}
+
static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
{
int err = 0;
@@ -1703,6 +1710,13 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
parent);
rtnl_unlock();
return ret;
+ case MRT6_DEL_MFC_ALL:
+ rtnl_lock();
+ ip6mr_for_each_table(mrt, net) {
+ mroute_clean_cache(mrt, true);
+ }
+ rtnl_unlock();
+ return 0;
/*
* Control PIM assert (to activate pim will activate assert)
--
2.20.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
@ 2019-01-30 20:52 Callum Sinclair
2019-01-30 20:52 ` Callum Sinclair
0 siblings, 1 reply; 12+ messages in thread
From: Callum Sinclair @ 2019-01-30 20:52 UTC (permalink / raw)
To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
Created a way to clear the multicast forwarding cache on a socket
without having to either remove the entries manually using the delete
entry socket option or destroy and recreate the multicast socket.
Patch Set 2:
- Fix Compile Errors
Callum Sinclair (1):
ipmr: ip6mr: Create new sockopt to clear mfc cache only
include/uapi/linux/mroute.h | 3 ++-
include/uapi/linux/mroute6.h | 3 ++-
net/ipv4/ipmr.c | 40 +++++++++++++++++++++----------
net/ipv6/ip6mr.c | 46 +++++++++++++++++++++++-------------
4 files changed, 61 insertions(+), 31 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-01-30 2:25 ` Callum Sinclair
2019-01-30 5:42 ` kbuild test robot
@ 2019-01-30 7:13 ` kbuild test robot
1 sibling, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2019-01-30 7:13 UTC (permalink / raw)
To: Callum Sinclair
Cc: kbuild-all, davem, kuznet, yoshfuji, nikolay, netdev,
linux-kernel, Callum Sinclair
[-- Attachment #1: Type: text/plain, Size: 4146 bytes --]
Hi Callum,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on net/master]
[also build test ERROR on v5.0-rc4 next-20190129]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Callum-Sinclair/ipmr-ip6mr-Create-new-sockopt-to-clear-mfc-cache-only/20190130-104146
config: i386-defconfig (attached as .config)
compiler: gcc-8 (Debian 8.2.0-14) 8.2.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
net/ipv4/ipmr.c: In function 'mroute_clean_cache':
>> net/ipv4/ipmr.c:1312:3: error: 'cache' undeclared (first use in this function); did you mean 'hh_cache'?
cache = (struct mfc_cache *)c;
^~~~~
hh_cache
net/ipv4/ipmr.c:1312:3: note: each undeclared identifier is reported only once for each function it appears in
>> net/ipv4/ipmr.c:1313:33: error: 'net' undeclared (first use in this function)
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
^~~
net/ipv4/ipmr.c: In function 'mroute_clean_tables':
net/ipv4/ipmr.c:1334:14: warning: unused variable 'net' [-Wunused-variable]
struct net *net = read_pnet(&mrt->net);
^~~
vim +1312 net/ipv4/ipmr.c
^1da177e4 Linus Torvalds 2005-04-16 1300
7ba7b80d1 Callum Sinclair 2019-01-30 1301 /* Clear the vif tables */
7ba7b80d1 Callum Sinclair 2019-01-30 1302 static void mroute_clean_cache(struct mr_table *mrt, bool all)
^1da177e4 Linus Torvalds 2005-04-16 1303 {
494fff563 Yuval Mintz 2018-02-28 1304 struct mr_mfc *c, *tmp;
^1da177e4 Linus Torvalds 2005-04-16 1305
a8cb16dd9 Eric Dumazet 2010-10-01 1306 /* Wipe the cache */
8fb472c09 Nikolay Aleksandrov 2017-01-12 1307 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
0e615e960 Nikolay Aleksandrov 2015-11-20 1308 if (!all && (c->mfc_flags & MFC_STATIC))
^1da177e4 Linus Torvalds 2005-04-16 1309 continue;
8fb472c09 Nikolay Aleksandrov 2017-01-12 1310 rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
a8c9486b8 Eric Dumazet 2010-10-01 1311 list_del_rcu(&c->list);
494fff563 Yuval Mintz 2018-02-28 @1312 cache = (struct mfc_cache *)c;
494fff563 Yuval Mintz 2018-02-28 @1313 call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
b362053a7 Yotam Gigi 2017-09-27 1314 mrt->id);
494fff563 Yuval Mintz 2018-02-28 1315 mroute_netlink_event(mrt, cache, RTM_DELROUTE);
8c13af2a2 Yuval Mintz 2018-03-26 1316 mr_cache_put(c);
^1da177e4 Linus Torvalds 2005-04-16 1317 }
^1da177e4 Linus Torvalds 2005-04-16 1318
0c12295a7 Patrick McHardy 2010-04-13 1319 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
^1da177e4 Linus Torvalds 2005-04-16 1320 spin_lock_bh(&mfc_unres_lock);
8fb472c09 Nikolay Aleksandrov 2017-01-12 1321 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
862465f2e Patrick McHardy 2010-04-13 1322 list_del(&c->list);
494fff563 Yuval Mintz 2018-02-28 1323 cache = (struct mfc_cache *)c;
494fff563 Yuval Mintz 2018-02-28 1324 mroute_netlink_event(mrt, cache, RTM_DELROUTE);
494fff563 Yuval Mintz 2018-02-28 1325 ipmr_destroy_unres(mrt, cache);
^1da177e4 Linus Torvalds 2005-04-16 1326 }
^1da177e4 Linus Torvalds 2005-04-16 1327 spin_unlock_bh(&mfc_unres_lock);
^1da177e4 Linus Torvalds 2005-04-16 1328 }
^1da177e4 Linus Torvalds 2005-04-16 1329 }
^1da177e4 Linus Torvalds 2005-04-16 1330
:::::: The code at line 1312 was first introduced by commit
:::::: 494fff56379c4ad5b8fe36a5b7ffede4044ca7bb ipmr, ip6mr: Make mfc_cache a common structure
:::::: TO: Yuval Mintz <yuvalm@mellanox.com>
:::::: CC: David S. Miller <davem@davemloft.net>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 26942 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-01-30 2:25 ` Callum Sinclair
@ 2019-01-30 5:42 ` kbuild test robot
2019-01-30 7:13 ` kbuild test robot
1 sibling, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2019-01-30 5:42 UTC (permalink / raw)
To: Callum Sinclair
Cc: kbuild-all, davem, kuznet, yoshfuji, nikolay, netdev,
linux-kernel, Callum Sinclair
[-- Attachment #1: Type: text/plain, Size: 4325 bytes --]
Hi Callum,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on net/master]
[also build test ERROR on v5.0-rc4 next-20190129]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Callum-Sinclair/ipmr-ip6mr-Create-new-sockopt-to-clear-mfc-cache-only/20190130-104146
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 8.2.0-11) 8.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.2.0 make.cross ARCH=arm
All errors (new ones prefixed by >>):
net/ipv4/ipmr.c: In function 'mroute_clean_cache':
>> net/ipv4/ipmr.c:1312:3: error: 'cache' undeclared (first use in this function); did you mean 'cacheid'?
cache = (struct mfc_cache *)c;
^~~~~
cacheid
net/ipv4/ipmr.c:1312:3: note: each undeclared identifier is reported only once for each function it appears in
net/ipv4/ipmr.c:1313:33: error: 'net' undeclared (first use in this function)
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
^~~
net/ipv4/ipmr.c: In function 'mroute_clean_tables':
net/ipv4/ipmr.c:1334:14: warning: unused variable 'net' [-Wunused-variable]
struct net *net = read_pnet(&mrt->net);
^~~
vim +1312 net/ipv4/ipmr.c
^1da177e4 Linus Torvalds 2005-04-16 1300
7ba7b80d1 Callum Sinclair 2019-01-30 1301 /* Clear the vif tables */
7ba7b80d1 Callum Sinclair 2019-01-30 1302 static void mroute_clean_cache(struct mr_table *mrt, bool all)
^1da177e4 Linus Torvalds 2005-04-16 1303 {
494fff563 Yuval Mintz 2018-02-28 1304 struct mr_mfc *c, *tmp;
^1da177e4 Linus Torvalds 2005-04-16 1305
a8cb16dd9 Eric Dumazet 2010-10-01 1306 /* Wipe the cache */
8fb472c09 Nikolay Aleksandrov 2017-01-12 1307 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
0e615e960 Nikolay Aleksandrov 2015-11-20 1308 if (!all && (c->mfc_flags & MFC_STATIC))
^1da177e4 Linus Torvalds 2005-04-16 1309 continue;
8fb472c09 Nikolay Aleksandrov 2017-01-12 1310 rhltable_remove(&mrt->mfc_hash, &c->mnode, ipmr_rht_params);
a8c9486b8 Eric Dumazet 2010-10-01 1311 list_del_rcu(&c->list);
494fff563 Yuval Mintz 2018-02-28 @1312 cache = (struct mfc_cache *)c;
494fff563 Yuval Mintz 2018-02-28 1313 call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, cache,
b362053a7 Yotam Gigi 2017-09-27 1314 mrt->id);
494fff563 Yuval Mintz 2018-02-28 1315 mroute_netlink_event(mrt, cache, RTM_DELROUTE);
8c13af2a2 Yuval Mintz 2018-03-26 1316 mr_cache_put(c);
^1da177e4 Linus Torvalds 2005-04-16 1317 }
^1da177e4 Linus Torvalds 2005-04-16 1318
0c12295a7 Patrick McHardy 2010-04-13 1319 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
^1da177e4 Linus Torvalds 2005-04-16 1320 spin_lock_bh(&mfc_unres_lock);
8fb472c09 Nikolay Aleksandrov 2017-01-12 1321 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
862465f2e Patrick McHardy 2010-04-13 1322 list_del(&c->list);
494fff563 Yuval Mintz 2018-02-28 1323 cache = (struct mfc_cache *)c;
494fff563 Yuval Mintz 2018-02-28 1324 mroute_netlink_event(mrt, cache, RTM_DELROUTE);
494fff563 Yuval Mintz 2018-02-28 1325 ipmr_destroy_unres(mrt, cache);
^1da177e4 Linus Torvalds 2005-04-16 1326 }
^1da177e4 Linus Torvalds 2005-04-16 1327 spin_unlock_bh(&mfc_unres_lock);
^1da177e4 Linus Torvalds 2005-04-16 1328 }
^1da177e4 Linus Torvalds 2005-04-16 1329 }
^1da177e4 Linus Torvalds 2005-04-16 1330
:::::: The code at line 1312 was first introduced by commit
:::::: 494fff56379c4ad5b8fe36a5b7ffede4044ca7bb ipmr, ip6mr: Make mfc_cache a common structure
:::::: TO: Yuval Mintz <yuvalm@mellanox.com>
:::::: CC: David S. Miller <davem@davemloft.net>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 68417 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
2019-01-30 2:25 Callum Sinclair
@ 2019-01-30 2:25 ` Callum Sinclair
2019-01-30 5:42 ` kbuild test robot
2019-01-30 7:13 ` kbuild test robot
0 siblings, 2 replies; 12+ messages in thread
From: Callum Sinclair @ 2019-01-30 2:25 UTC (permalink / raw)
To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
Currently the only way to clear the mfc cache was to delete the entries
one by one using the MRT_DEL_MFC socket option or to destroy and
recreate the socket.
Create a new socket option which will clear the multicast forwarding
cache on the socket without destroying the socket.
Signed-off-by: Callum Sinclair <callum.sinclair@alliedtelesis.co.nz>
---
include/uapi/linux/mroute.h | 3 ++-
include/uapi/linux/mroute6.h | 3 ++-
net/ipv4/ipmr.c | 41 +++++++++++++++++++++-----------
net/ipv6/ip6mr.c | 45 +++++++++++++++++++++++-------------
4 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
index 5d37a9ccce63..8a0beb885cd9 100644
--- a/include/uapi/linux/mroute.h
+++ b/include/uapi/linux/mroute.h
@@ -28,7 +28,8 @@
#define MRT_TABLE (MRT_BASE+9) /* Specify mroute table ID */
#define MRT_ADD_MFC_PROXY (MRT_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT_DEL_MFC_PROXY (MRT_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT_MAX (MRT_BASE+11)
+#define MRT_DEL_MFC_ALL (MRT_BASE+12) /* Del all multicast entries */
+#define MRT_MAX (MRT_BASE+12)
#define SIOCGETVIFCNT SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h
index 9999cc006390..7def70cdf571 100644
--- a/include/uapi/linux/mroute6.h
+++ b/include/uapi/linux/mroute6.h
@@ -31,7 +31,8 @@
#define MRT6_TABLE (MRT6_BASE+9) /* Specify mroute table ID */
#define MRT6_ADD_MFC_PROXY (MRT6_BASE+10) /* Add a (*,*|G) mfc entry */
#define MRT6_DEL_MFC_PROXY (MRT6_BASE+11) /* Del a (*,*|G) mfc entry */
-#define MRT6_MAX (MRT6_BASE+11)
+#define MRT6_DEL_MFC_ALL (MRT6_BASE+12) /* Del all multicast entries */
+#define MRT6_MAX (MRT6_BASE+12)
#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ddbf8c9a1abb..bbbce5ec8a0c 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1298,22 +1298,10 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
return 0;
}
-/* Close the multicast socket, and clear the vif tables etc */
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
{
- struct net *net = read_pnet(&mrt->net);
struct mr_mfc *c, *tmp;
- struct mfc_cache *cache;
- LIST_HEAD(list);
- int i;
-
- /* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- vif_delete(mrt, i, 0, &list);
- }
- unregister_netdevice_many(&list);
/* Wipe the cache */
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
@@ -1340,6 +1328,24 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
}
}
+/* Close the multicast socket, and clear the vif tables etc */
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+ struct net *net = read_pnet(&mrt->net);
+ LIST_HEAD(list);
+ int i;
+
+ /* Shut down all active vif entries */
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ vif_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
+
+ mroute_clean_cache (mrt, all);
+}
+
/* called from ip_ra_control(), before an RCU grace period,
* we dont need to call synchronize_rcu() here
*/
@@ -1482,6 +1488,13 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
sk == rtnl_dereference(mrt->mroute_sk),
parent);
break;
+ case MRT_DEL_MFC_ALL:
+ rtnl_lock();
+ ipmr_for_each_table(mrt, net) {
+ mroute_clean_cache(mrt, true);
+ }
+ rtnl_unlock();
+ break;
/* Control PIM assert. */
case MRT_ASSERT:
if (optlen != sizeof(val)) {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 30337b38274b..64631f85dcf4 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1492,25 +1492,11 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
return 0;
}
-/*
- * Close the multicast socket, and clear the vif tables etc
- */
-
-static void mroute_clean_tables(struct mr_table *mrt, bool all)
+/* Clear the vif tables */
+static void mroute_clean_cache(struct mr_table *mrt, bool all)
{
struct mr_mfc *c, *tmp;
- LIST_HEAD(list);
- int i;
-
- /* Shut down all active vif entries */
- for (i = 0; i < mrt->maxvif; i++) {
- if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
- continue;
- mif6_delete(mrt, i, 0, &list);
- }
- unregister_netdevice_many(&list);
- /* Wipe the cache */
list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
if (!all && (c->mfc_flags & MFC_STATIC))
continue;
@@ -1535,6 +1521,26 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
spin_unlock_bh(&mfc_unres_lock);
}
}
+/*
+ * Close the multicast socket, and clear the vif tables etc
+ */
+
+static void mroute_clean_tables(struct mr_table *mrt, bool all)
+{
+ LIST_HEAD(list);
+ int i;
+
+ /* Shut down all active vif entries */
+ for (i = 0; i < mrt->maxvif; i++) {
+ if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
+ continue;
+ mif6_delete(mrt, i, 0, &list);
+ }
+ unregister_netdevice_many(&list);
+
+ /* Wipe the cache */
+ mroute_clean_cache(mrt, all);
+}
static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
{
@@ -1703,6 +1709,13 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
parent);
rtnl_unlock();
return ret;
+ case MRT6_DEL_MFC_ALL:
+ rtnl_lock();
+ ip6mr_for_each_table(mrt, net) {
+ mroute_clean_cache(mrt, true);
+ }
+ rtnl_unlock();
+ return 0;
/*
* Control PIM assert (to activate pim will activate assert)
--
2.20.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only
@ 2019-01-30 2:25 Callum Sinclair
2019-01-30 2:25 ` Callum Sinclair
0 siblings, 1 reply; 12+ messages in thread
From: Callum Sinclair @ 2019-01-30 2:25 UTC (permalink / raw)
To: davem, kuznet, yoshfuji, nikolay, netdev, linux-kernel; +Cc: Callum Sinclair
Created a way to clear the multicast forwarding cache on a socket
without having to either remove the entries manually using the delete
entry socket option or destroy and recreate the multicast socket.
Callum Sinclair (1):
ipmr: ip6mr: Create new sockopt to clear mfc cache only
include/uapi/linux/mroute.h | 3 ++-
include/uapi/linux/mroute6.h | 3 ++-
net/ipv4/ipmr.c | 41 +++++++++++++++++++++-----------
net/ipv6/ip6mr.c | 45 +++++++++++++++++++++++-------------
4 files changed, 60 insertions(+), 32 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2019-02-07 6:32 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-05 2:57 [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only Callum Sinclair
2019-02-05 2:58 ` Callum Sinclair
2019-02-05 19:52 ` Nikolay Aleksandrov
-- strict thread matches above, loose matches on Subject: below --
2019-02-07 2:08 Callum Sinclair
2019-02-07 2:08 ` [PATCH] " Callum Sinclair
2019-02-07 6:32 ` Nikolay Aleksandrov
2019-01-30 20:52 Callum Sinclair
2019-01-30 20:52 ` Callum Sinclair
2019-02-03 3:42 ` David Miller
2019-01-30 2:25 Callum Sinclair
2019-01-30 2:25 ` Callum Sinclair
2019-01-30 5:42 ` kbuild test robot
2019-01-30 7:13 ` kbuild test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.