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

Bump CIDR limit on older kernels. #3119

Merged
merged 4 commits into from
Mar 14, 2018

Conversation

joestringer
Copy link
Member

@joestringer joestringer commented Mar 13, 2018

Fixes: #2920

Support a larger number of CIDR prefixes when running on older kernels. Now limited by the number of unique prefix lengths in the policies for an endpoint, which should be less than forty. 

@joestringer joestringer added wip sig/datapath Impacts bpf/ or low-level forwarding details, including map management and monitor messages. area/bugtool Impacts gathering of data for debugging purposes. labels Mar 13, 2018
@joestringer joestringer requested a review from a team as a code owner March 13, 2018 01:19
@joestringer joestringer requested a review from a team March 13, 2018 01:19
@joestringer joestringer requested review from a team as code owners March 13, 2018 01:19
@joestringer joestringer requested a review from a team March 13, 2018 01:19
pkg/policy/l3.go Outdated
} else {
m.IPv4Count++
m.IPv4PrefixCount[ones] += 1

Choose a reason for hiding this comment

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

should replace m.IPv4PrefixCount[ones] += 1 with m.IPv4PrefixCount[ones]++

pkg/policy/l3.go Outdated
@@ -74,10 +74,16 @@ func (m *CIDRPolicyMap) Insert(cidr string, ruleLabels labels.LabelArray) int {
if _, found := m.Map[key]; !found {
m.Map[key] = &CIDRPolicyMapRule{Prefix: *ipnet, DerivedFromRules: labels.LabelArrayList{ruleLabels}}
if ipnet.IP.To4() == nil {
m.IPv6Count++
m.IPv6PrefixCount[ones] += 1

Choose a reason for hiding this comment

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

should replace m.IPv6PrefixCount[ones] += 1 with m.IPv6PrefixCount[ones]++

@joestringer joestringer added sig/policy Impacts whether traffic is allowed or denied based on user-defined policies. and removed area/bugtool Impacts gathering of data for debugging purposes. labels Mar 13, 2018

// FIXME GH-1781 count coalesced CIDRs and restrict the number of
// prefix lengths based on the CIDRSet exclusions.
if l := len(prefixLengths); l > MaxCIDRPrefixLengths {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is not particularly useful, because the number that matters is the number of CIDRs across all the rules relevant for each specific endpoint.
It's OK to check here anyway.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you think we should just drop this validation and rely on the generation errors propagating to endpoint log?

Copy link
Member Author

Choose a reason for hiding this comment

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

We can keep it here, there's also checking when L3Policy is Validate()d just before attempting to push it into BPF.

pkg/policy/l3.go Outdated
}

if len(m.IPv6PrefixCount) > api.MaxCIDRPrefixLengths {
log.Infof("Inserting CIDR with prefix length %d/%d, generation may fail",
Copy link
Contributor

Choose a reason for hiding this comment

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

Info level seems very noisy a priori. Change to Debug?

Copy link
Contributor

Choose a reason for hiding this comment

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

Can't you return an error and add expose that through the endpoint's log?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not from here, this is during CIDRPolicyMap construction which is divorced from endpoints. I could signal it when we attempt to apply the policy to the endpoint and generate the BPF.

Copy link
Member

Choose a reason for hiding this comment

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

Please file a GH to clean this up. It's not ideal but I don't want to hold up this PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed this log.

@@ -0,0 +1,40 @@
// Copyright 2016-2017 Authors of Cilium
Copy link
Contributor

Choose a reason for hiding this comment

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

2018

This test needs rethinking with the upcoming expansion of CIDR limits.
Remove it for now. We should be able to achieve this with just unit
testing.

Signed-off-by: Joe Stringer <joe@covalent.io>
Signed-off-by: Joe Stringer <joe@covalent.io>
Signed-off-by: Joe Stringer <joe@covalent.io>
On older kernels that do not support the BPF_MAP_TYPE_LPM, we have
previously supported defining an array of up to about forty CIDRs for
which the datapath would allow traffic. However, if a user wished to
write CIDR policies with more than this number of possible CIDR matches,
then the only option to support this would be to upgrade the kernel.

This commit relaxes this constraint by replacing the array-based
implementation in the BPF datapath with a hashtable-based approach
instead. The entries in the hash table start with a 32-bit unsigned
integer indicating the prefix length followed by the CIDR with a zeroed
suffix.

The implementation iterates through CIDR{4,6}_{E,IN}GRESS_PREFIXES to
perform the lookup, so if there are many CIDRs but they all use the same
prefix it will only require one lookup. This list of prefix lengths is
expected to be ordered from longest prefix to shortest.

With datapath complexity and clang-7.0 it appears that up to about
ninety prefix lengths with any number of CIDRs (defined by LPM_MAP_SIZE)
may be supported while also supporting the rest of the datapath logic.
However, when upcoming CIDR-dependent L4 matching support is added this
is expected to drop, so for the moment restrict configuration of CIDRs
with more than 40 prefix lengths. This should cover all IPv4 cases, and
the majority of IPv6 use cases for the moment.

Based on outline from Jarno Rajahalme.

Signed-off-by: Joe Stringer <joe@covalent.io>
@joestringer
Copy link
Member Author

test-me-please

Ingress: []api.IngressRule{{FromCIDR: cidrs}},
}
err := apiRule1.Sanitize()
c.Assert(err, Not(IsNil))
Copy link
Member

Choose a reason for hiding this comment

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

I feel a bit uneasy about this behaviour but I understand given the current implementation.

@tgraf tgraf merged commit cc7a4cb into cilium:master Mar 14, 2018
@joestringer joestringer deleted the submit/cidr-limit-bump branch March 14, 2018 01:46
@joestringer joestringer added the release-note/minor This PR changes functionality that users may find relevant to operating Cilium. label Mar 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note/minor This PR changes functionality that users may find relevant to operating Cilium. sig/datapath Impacts bpf/ or low-level forwarding details, including map management and monitor messages. sig/policy Impacts whether traffic is allowed or denied based on user-defined policies.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove CIDR limit on older kernels
5 participants