* [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
* [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only 2019-01-30 2:25 [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only 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
* 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
* 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
* [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
* [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
* 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-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 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
* ipmr: ip6mr: Create new sockopt to clear mfc cache only @ 2019-02-07 2:08 Callum Sinclair 2019-02-07 2:08 ` [PATCH] " Callum Sinclair 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 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. Using the flags MRT_FLUSH_ENTRIES and MRT_FLUSH_VIFS, all multicast entries can be cleared, all multicast interfaces can be closed or both can be cleared using one sockopt call. Patch Set 2: - Fix Compile Errors Patch Set 3: - Fix Style Errors Patch Set 4: - Implemented a way to clear the entries or vifs based off an input flag. Callum Sinclair (1): ipmr: ip6mr: Create new sockopt to clear mfc cache only 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(-) -- 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-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-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
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-01-30 2:25 [PATCH] ipmr: ip6mr: Create new sockopt to clear mfc cache only 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 2019-01-30 20:52 Callum Sinclair 2019-01-30 20:52 ` Callum Sinclair 2019-02-03 3:42 ` David Miller 2019-02-05 2:57 Callum Sinclair 2019-02-05 2:58 ` Callum Sinclair 2019-02-05 19:52 ` Nikolay Aleksandrov 2019-02-07 2:08 Callum Sinclair 2019-02-07 2:08 ` [PATCH] " Callum Sinclair 2019-02-07 6:32 ` Nikolay Aleksandrov
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.