Skip to content

Commit

Permalink
Fix for IPv6 cluster
Browse files Browse the repository at this point in the history
Related issue: deployments-k8s/5775
Related PRs:
cmd-nsmgr/488
cmd-nse-remote-vlan/49

Signed-off-by: Laszlo Kiraly <laszlo.kiraly@est.tech>
  • Loading branch information
ljkiraly committed May 12, 2022
1 parent 41196bd commit 38d0d3e
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 0 deletions.
58 changes: 58 additions & 0 deletions pkg/tools/listenonurl/listenonurl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2021-2022 Nordix and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package listenonurl providesfunctions to set public url to register NSM
package listenonurl

import (
"net"
"net/url"
)

// GetPublicURL - constructs an URL from an address accessible
// clusterwide and a given port
// defaults to the given URL if no such address can be found
func GetPublicURL(addrs []net.Addr, defaultURL *url.URL) *url.URL {
if defaultURL.Port() == "" || len(defaultURL.Host) != len(":")+len(defaultURL.Port()) {
return defaultURL
}

if listenIP := getIP(addrs); listenIP != nil {
return &url.URL{
Scheme: "tcp",
Host: net.JoinHostPort(listenIP.String(), defaultURL.Port()),
}
}
return defaultURL
}

func getIP(addrs []net.Addr) net.IP {
var ret net.IP
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
// defaults to IPv4 address if available
if ipnet.IP.To4() != nil {
return ipnet.IP
}
// accept all IPv6 Global Unicats addresses
// including Unique-Local Address (which starts with ‘fd’)
if ret == nil && ipnet.IP.IsGlobalUnicast() {
ret = ipnet.IP
}
}
}
return ret
}
129 changes: 129 additions & 0 deletions pkg/tools/listenonurl/listenonurl_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright (c) 2021-2022 Nordix and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package listenonurl_test

import (
"net"
"net/url"
"testing"

"github.com/networkservicemesh/sdk/pkg/tools/listenonurl"
)

func TestGetPublicURL(t *testing.T) {
test := []struct {
u *url.URL
ips []net.Addr
exp string
}{
{
u: &url.URL{
Scheme: "file",
Host: "",
Path: "/local-path"},
ips: []net.Addr{ // 10.244.2.13/24
&net.IPNet{IP: net.IPv4(10, 244, 2, 13), Mask: net.IPv4Mask(255, 255, 255, 0)},
},
exp: "file:///local-path",
}, {
u: &url.URL{
Scheme: "tcp",
Host: "172.17.11.1:5009",
},
ips: []net.Addr{ // 10.244.2.13/24
&net.IPNet{IP: net.IPv4(10, 244, 2, 13), Mask: net.IPv4Mask(255, 255, 255, 0)},
},
exp: "tcp://172.17.11.1:5009",
}, {
u: &url.URL{
Scheme: "tcp",
Host: ":5009",
},
ips: []net.Addr{ // 10.244.2.13/24
&net.IPNet{IP: net.IPv4(10, 244, 2, 13), Mask: net.IPv4Mask(255, 255, 255, 0)},
},
exp: "tcp://10.244.2.13:5009",
}, {
u: &url.URL{
Scheme: "tcp",
Host: ":5009",
},
ips: []net.Addr{ // 127.0.0.1/8
&net.IPNet{IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)},
},
exp: "tcp://:5009",
}, {
u: &url.URL{
Scheme: "tcp",
Host: ":5009",
},
ips: []net.Addr{
// 10.244.2.13/24, 127.0.0.1/8, 135.104.0.0/24
&net.IPNet{IP: net.IPv4(10, 244, 2, 13), Mask: net.IPv4Mask(255, 255, 255, 0)},
&net.IPNet{IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)},
&net.IPNet{IP: net.IPv4(135, 104, 0, 0), Mask: net.IPv4Mask(255, 255, 255, 0)},
},
exp: "tcp://10.244.2.13:5009",
}, {
u: &url.URL{
Scheme: "tcp",
Host: ":5009",
},
ips: []net.Addr{
// fd00:10:244:1::9/32, 10.244.2.13/24
&net.IPNet{IP: net.ParseIP("fd00:10:244:1::9"), Mask: net.CIDRMask(32, 128)},
&net.IPNet{IP: net.IPv4(10, 244, 2, 13), Mask: net.IPv4Mask(255, 255, 255, 0)},
},
exp: "tcp://10.244.2.13:5009",
}, {
u: &url.URL{
Scheme: "tcp",
Host: ":5009",
},
ips: []net.Addr{ // fd00:10:244:1::9/32
&net.IPNet{IP: net.ParseIP("fd00:10:244:1::9"), Mask: net.CIDRMask(32, 128)},
},
exp: "tcp://[fd00:10:244:1::9]:5009",
}, {
u: &url.URL{
Scheme: "tcp",
Host: ":5009",
},
ips: []net.Addr{ // 2001:DB8::1/48, fd00:10:244:1::9/32
&net.IPNet{IP: net.ParseIP("2001:DB8::1"), Mask: net.CIDRMask(48, 128)},
&net.IPNet{IP: net.ParseIP("fd00:10:244:1::9"), Mask: net.CIDRMask(32, 128)},
},
exp: "tcp://[2001:db8::1]:5009",
}, {
u: &url.URL{
Scheme: "tcp",
Host: ":5009",
},
ips: []net.Addr{ // fe80::1/48
&net.IPNet{IP: net.ParseIP("fe80::1"), Mask: net.CIDRMask(48, 128)},
},
exp: "tcp://:5009",
},
}

for _, tt := range test {
actual := listenonurl.GetPublicURL(tt.ips, tt.u)
if tt.exp != actual.String() {
t.Errorf("GetPublicURL(%q, %q) = %q, want %q", tt.ips, tt.u, actual, tt.exp)
}
}
}

0 comments on commit 38d0d3e

Please sign in to comment.