Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix] Dealt with small subnets #842 #860

Merged
merged 2 commits into from
May 31, 2024
Merged

Conversation

nemesifier
Copy link
Member

Supersedes #859.

Fixes #842

@pandafy @praptisharma28 please review.

@coveralls
Copy link

coveralls commented May 14, 2024

Coverage Status

coverage: 98.751% (+0.001%) from 98.75%
when pulling 0883dfc on issues/842-slash32-subnets
into c4a1683 on master.

Copy link
Member Author

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pandafy I am leaving some comments to make your review easier.

# the required number of generated subnets
available = 2 ** (self.size - master_subnet.prefixlen)
# Account for the reserved subnet
available -= 1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pandafy the reserved subnet was not taken into account in this calculation.
Therefore, if a master subnet has only 2 available slots but the number of subnets is 2, the first time the rule will run will try to take 3 slots (1 for the reserved subnet plus the 2 requested) and will fail.
Were you aware of this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch on accounting for the reserved subnet! That's a crucial detail I missed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nemesifier I was actually unaware of this bug. Thanks for catching this.

self.assertEqual(str(index.subnet.subnet), '10.0.0.1/32')
self.assertEqual(index.ip.ip_address, '10.0.0.1')

def test_slash_32_rule_ipv4_error(self):
Copy link
Member Author

@nemesifier nemesifier May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I try to create a subnet division rule for a /32 master subnet, which cannot work.

self.assertEqual(str(index.subnet.subnet), 'fd12:3456:7890::1/128')
self.assertEqual(index.ip.ip_address, 'fd12:3456:7890::1')

def test_slash_128_rule_ipv6_error(self):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here but for ipv6.

try:
next(
ip_network(str(self.master_subnet.subnet)).subnets(new_prefix=self.size)
)[self.number_of_ips]
)[self.number_of_ips - 1]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/32 and /128 subnets only have the zero index, trying to access 1 fails, therefore I had to subtract 1 here.

@@ -194,8 +194,7 @@ def get_max_subnet(master_subnet, division_rule):
subnet_obj.full_clean()
subnet_obj.save()
max_subnet = subnet_obj.subnet
finally:
return max_subnet
return max_subnet
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another problem I found here @pandafy was that line 194 above can fail if there's no space for the reserved subnet and when that happens, max_subnet is not defined, but finally will execute return max_subnet anyway (even if line 194 fails), so in that case the code fails because max_subnet is not defined.

I think we shouldn't use finally here. That statement is designed to be used in situations when it's imperative to call some cleanup operations even in case of unexpected failures.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will keep a note of this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will keep a note of this.

@praptisharma28
Copy link
Member

Supersedes #859.

Fixes #842

@pandafy @praptisharma28 please review.

I learnt a lot going through your PR. I initially tried to address the /32 subnet issue with a workaround, but I realize now that it wasn't the correct approach. I was too focused on simply preventing the error message without fully understanding the root cause and its implications.

Copy link
Member Author

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pandafy what if we change the implementation to account for a reserved subnet only when using big subnets, eg: only when master subnet is larger than 24 on ipv4, so from subnets having 512 addresses?

Or should we make this configurable with an additional flag in the subnet division rule?
I wonder why we did this in the first place?

I think it makes the implementation harder and I am not sure it's really useful. If this is the case I think we can create a new issue for this to fix it.

It's not uncommon for users to want to use this feature but getting stuck on erros like the one we are trying to fix here. If we manage to make this feature easier to use I am pretty sure it's a very useful feature to have in OpenWISP.

Copy link
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, I have found a bug in the current implementation. Try to create a subnet division rule with the following configuration

Screenshot from 2024-05-15 00-25-52
Screenshot from 2024-05-15 00-26-06

The automation generated the following IPs for this subnet

Screenshot from 2024-05-15 00-27-51

All 10.8.0.8

Copy link
Member Author

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My latest commit addresses the issue found during the review.

I wrote a new test which replicated the bug and was failing before applying the fix.

I also took advantage of this change to make one of the existing tests more detailed.

@pandafy when we write tests for features like these, we should not limit ourselves to check only for quantity of data generated, we have to make sure that the data we generate matches our expectations.

Copy link
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I have also performed manual testing.

@nemesifier nemesifier merged commit bf909cc into master May 31, 2024
12 checks passed
@nemesifier nemesifier deleted the issues/842-slash32-subnets branch May 31, 2024 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

[bug] Subnet division rule does not allow assigning only 1 ip in /32
4 participants