2020-07-09 23:30:36

by Mark Tomlinson

[permalink] [raw]
Subject: [PATCH] ipv6: Support more than 32 MIFS

The function ip6mr_mfc_add() declared an array of ttls. If MAXMIFS is
large, this would create a large stack frame. This is fixed, and made
more efficient, by passing mf6cc_ifset to ip6mr_update_thresholds().

Signed-off-by: Mark Tomlinson <[email protected]>
---

As background to this patch, we have MAXMIFS set to 1025 in our kernel.
This creates other issues apart from what this patch fixes, but this
change does make the IPv4 and IPv6 code look more similar, and reduces
total amount of code. Without the double handling of TTLs, I think it is
also easier to understand. Hence I thought it could still become part of
the main kernel.

net/ipv6/ip6mr.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 1f4d20e97c07..7123849d201b 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -836,7 +836,7 @@ static void ipmr_expire_process(struct timer_list *t)

static void ip6mr_update_thresholds(struct mr_table *mrt,
struct mr_mfc *cache,
- unsigned char *ttls)
+ struct if_set *ifset)
{
int vifi;

@@ -845,9 +845,8 @@ static void ip6mr_update_thresholds(struct mr_table *mrt,
memset(cache->mfc_un.res.ttls, 255, MAXMIFS);

for (vifi = 0; vifi < mrt->maxvif; vifi++) {
- if (VIF_EXISTS(mrt, vifi) &&
- ttls[vifi] && ttls[vifi] < 255) {
- cache->mfc_un.res.ttls[vifi] = ttls[vifi];
+ if (VIF_EXISTS(mrt, vifi) && IF_ISSET(vifi, ifset)) {
+ cache->mfc_un.res.ttls[vifi] = 1;
if (cache->mfc_un.res.minvif > vifi)
cache->mfc_un.res.minvif = vifi;
if (cache->mfc_un.res.maxvif <= vifi)
@@ -1406,21 +1405,14 @@ void ip6_mr_cleanup(void)
static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
struct mf6cctl *mfc, int mrtsock, int parent)
{
- unsigned char ttls[MAXMIFS];
struct mfc6_cache *uc, *c;
struct mr_mfc *_uc;
bool found;
- int i, err;
+ int err;

if (mfc->mf6cc_parent >= MAXMIFS)
return -ENFILE;

- memset(ttls, 255, MAXMIFS);
- for (i = 0; i < MAXMIFS; i++) {
- if (IF_ISSET(i, &mfc->mf6cc_ifset))
- ttls[i] = 1;
- }
-
/* The entries are added/deleted only under RTNL */
rcu_read_lock();
c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
@@ -1429,7 +1421,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
if (c) {
write_lock_bh(&mrt_lock);
c->_c.mfc_parent = mfc->mf6cc_parent;
- ip6mr_update_thresholds(mrt, &c->_c, ttls);
+ ip6mr_update_thresholds(mrt, &c->_c, &mfc->mf6cc_ifset);
if (!mrtsock)
c->_c.mfc_flags |= MFC_STATIC;
write_unlock_bh(&mrt_lock);
@@ -1450,7 +1442,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
c->_c.mfc_parent = mfc->mf6cc_parent;
- ip6mr_update_thresholds(mrt, &c->_c, ttls);
+ ip6mr_update_thresholds(mrt, &c->_c, &mfc->mf6cc_ifset);
if (!mrtsock)
c->_c.mfc_flags |= MFC_STATIC;

--
2.27.0


2020-07-09 23:33:32

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] ipv6: Support more than 32 MIFS

From: Mark Tomlinson <[email protected]>
Date: Fri, 10 Jul 2020 11:27:34 +1200

> As background to this patch, we have MAXMIFS set to 1025 in our kernel.

This patch is pointless without that adjustment, so it really doesn't
belong upstream until you tackle the whole entire problem and therefore
make the limit able to be set higher or at run time.

I'm not applying this.