-
Notifications
You must be signed in to change notification settings - Fork 9
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
Dualstack Network Support #549
base: master
Are you sure you want to change the base?
Conversation
5919c8f
to
0c53831
Compare
0c53831
to
2389965
Compare
…o dualstack-support
d49d2c0
to
b65c835
Compare
23a3d1e
to
89096c0
Compare
…o dualstack-support
a3571a2
to
d9667d3
Compare
@@ -79,6 +80,21 @@ func (p *IPSearchQuery) generateTerm(rs *RethinkStore) *r.Term { | |||
}) | |||
} | |||
|
|||
if p.AddressFamily != nil { | |||
separator := "." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
separator := "." | |
var separator string |
if parsed.Addr().Is4() { | ||
af = metal.IPv4AddressFamily | ||
defaultChildPrefixLength[af] = 22 | ||
} | ||
if parsed.Addr().Is6() { | ||
af = metal.IPv6AddressFamily | ||
defaultChildPrefixLength[af] = 64 | ||
} | ||
|
||
if new.AddressFamilies == nil { | ||
new.AddressFamilies = metal.AddressFamilies{} | ||
} | ||
new.AddressFamilies = metal.AddressFamilies{af} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only required for private super networks and for those it's probably enough just to take the value from the partition for IPv4 and 64 for IPv6.
@@ -154,6 +155,25 @@ func (p *NetworkSearchQuery) generateTerm(rs *RethinkStore) (*r.Term, error) { | |||
}) | |||
} | |||
|
|||
if p.AddressFamily != nil { | |||
separator := "." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
separator := "." | |
var separator string |
separator = ":" | ||
} | ||
|
||
fmt.Printf("Separator:%s\n", separator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fmt.Printf("Separator:%s\n", separator) |
cmd/metal-api/internal/ipam/ipam.go
Outdated
if pfx.Addr().Is6() { | ||
af = metal.IPv6AddressFamily | ||
} | ||
availableIPs := metal.AddressFamilyUsage{ | ||
af: usage.Msg.AvailableIps, | ||
} | ||
usedIPs := metal.AddressFamilyUsage{ | ||
af: usage.Msg.AcquiredIps, | ||
} | ||
availablePrefixes := metal.AddressFamilyUsage{ | ||
af: usage.Msg.AvailableSmallestPrefixes, | ||
} | ||
usedPrefixes := metal.AddressFamilyUsage{ | ||
af: usage.Msg.AcquiredPrefixes, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is always the same address family and the map will never have different ones it might be okay to just return the usage without address family and handle in the caller where to put it
@@ -258,6 +286,49 @@ func TestAllocateIP(t *testing.T) { | |||
wantedStatus: http.StatusUnprocessableEntity, | |||
wantErr: errors.New("specific ip not contained in any of the defined prefixes"), | |||
}, | |||
{ | |||
name: "allocate a IPv4 address", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name: "allocate a IPv4 address", | |
name: "allocate an IPv4 address", |
wantedStatus: http.StatusCreated, | ||
}, | ||
{ | ||
name: "allocate a IPv6 address", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name: "allocate a IPv6 address", | |
name: "allocate an IPv6 address", |
wantErr: errors.New("there is no prefix for the given addressfamily:IPv6 present in network:4"), | ||
}, | ||
{ | ||
name: "allocate a IPv4 (no addressfamily specified) address from a IPv6 Only network", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name: "allocate a IPv4 (no addressfamily specified) address from a IPv6 Only network", | |
name: "allocate an IPv4 (no addressfamily specified) address from an IPv6 only network", |
if n == nil || n.network == nil { | ||
continue | ||
} | ||
if len(n.network.AddressFamilies) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if this is possible but can this be dynamically evaluated where the network was retrieved?
// We should support two private super per partition, one per addressfamily | ||
// the network allocate request must be configurable with addressfamily |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// We should support two private super per partition, one per addressfamily | |
// the network allocate request must be configurable with addressfamily |
PartitionID: &partition.ID, | ||
PrivateSuper: pointer.Pointer(true), | ||
}, &nw) | ||
r.log.Info("createnetwork", "found", nw) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r.log.Info("createnetwork", "found", nw) |
@@ -439,6 +456,79 @@ func validateAdditionalAnnouncableCIDRs(additionalCidrs []string, privateSuper b | |||
return nil | |||
} | |||
|
|||
func validatePrefixesAndAddressFamilies(prefixes, destinationPrefixes []string, defaultChildPrefixLength metal.ChildPrefixLength, privateSuper bool) (metal.Prefixes, metal.Prefixes, metal.AddressFamilies, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function signature does not imply the return values. Could be better to split validation functions from parsing functions to increase reusability.
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
// all DestinationPrefixes must be valid and from the same addressfamily |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still correct? Because I see different address families in the destination prefixes in our test environment.
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
if len(destinationAddressFamilies) > len(addressFamilies) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this check is insufficient, e.g. there are IPv6 destination prefixes but only IPv4 prefixes.
} | ||
|
||
for af, length := range defaultChildPrefixLength { | ||
fmt.Printf("af %s length:%d addressfamilies:%v", af, length, addressFamilies) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fmt.Printf("af %s length:%d addressfamilies:%v", af, length, addressFamilies) |
|
||
prefixes = append(prefixes, *prefix) | ||
var childPrefixLength = metal.ChildPrefixLength{} | ||
for af, length := range requestPayload.DefaultChildPrefixLength { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either this needs only to be done for private super or the validation must be extended to validate this field for non-private super networks, too.
return | ||
} | ||
if len(superNetwork.DefaultChildPrefixLength) == 0 { | ||
r.sendError(request, response, httperrors.BadRequest(fmt.Errorf("supernetwork %s has no defaultchildprefixlength specified", superNetwork.ID))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be an internal server error but I am not sure if we need these validation because we ensure this somewhere else in the code?
return nil, nil, nil, fmt.Errorf("private super network must always contain a defaultchildprefixlength") | ||
} | ||
|
||
for af, length := range defaultChildPrefixLength { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would also be good to check if the address family is actually IPv4 or IPv6.
r.sendError(request, response, httperrors.BadRequest(fmt.Errorf("supernetwork %s has no defaultchildprefixlength specified", superNetwork.ID))) | ||
return | ||
} | ||
r.log.Info("network allocate", "supernetwork", superNetwork.ID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log appears later in the code again
return nil, err | ||
} | ||
if childPrefix == nil { | ||
return nil, fmt.Errorf("could not allocate child prefix in parent network: %s for addressfamily: %s length:%d", parent.ID, af, childLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard to mitigate this but this is a potential leakage in case one child prefix could already be allocated.
) | ||
|
||
// ToAddressFamily will convert a string af to a AddressFamily | ||
func ToAddressFamily(af string) AddressFamily { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When returning an error with this function it would be helpful for validations because currently users can often try to send random stuff to the API and try to do something weird.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented ValidateAddressfamily as well
Closes #164
Actions Required
Depends on:
replaces #544
TODO: