-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathtypes.go
202 lines (172 loc) · 5.3 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
Copyright (c) 2021-2022 Nordix Foundation
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 v1
import (
"fmt"
"net"
"strconv"
"strings"
)
// ConfigStatus describes the status of a meridio operator resource to indicate if the resource is ready to use or not
type ConfigStatus string
const (
// Normally when a resouce is not processed by the corresponding controller, the status will be NoStatus
NoPhase ConfigStatus = ""
// If the validation of a resource does not pass in the controller, the status will be Error
Error ConfigStatus = "error"
// Normally when a resource is not created in a correct sequence, the status will be Disengaged
Disengaged ConfigStatus = "disengaged"
// Engaged indicates the resouce is readly to be used.
Engaged ConfigStatus = "engaged"
)
// Protocol describes the routing choice of the frontend
type Protocol string
const (
// Static instructs the frontend to work with the static routing configured on the Edge Routers
Static Protocol = "static"
// BGP instructs the frontend to setup BGP sessions with the Edge Routers
BGP Protocol = "bgp"
)
// IPFamily describes the traffic type in the trench
// Only one of the following ip family can be specified.
// If the traffic is IPv4 only, use IPv4, similarly,
// use IPv6 if the traffic is IPv6 only, otherwise, use
// dualstack which handles both IPv4 and IPv6 traffic.
type IPFamily string
const (
IPv4 IPFamily = "ipv4"
IPv6 IPFamily = "ipv6"
Dualstack IPFamily = "dualstack"
)
// +kubebuilder:validation:Enum=tcp;udp;sctp
type TransportProtocol string
const (
TCP TransportProtocol = "tcp"
UDP TransportProtocol = "udp"
SCTP TransportProtocol = "sctp"
)
func TransportProtocolsToStrings(proto []TransportProtocol) []string {
var ret []string
for _, p := range proto {
ret = append(ret, string(p))
}
return ret
}
type NetworkServiceType string
const (
StatelessLB = "stateless-lb"
)
func validatePrefix(p string) (*net.IPNet, error) {
ip, n, err := net.ParseCIDR(p)
if err != nil {
return nil, err
}
if !ip.Equal(n.IP) {
return nil, fmt.Errorf("%s is not a valid prefix, probably %v should be used", p, n)
}
return n, nil
}
func validatePrefixAndRange(p string) error {
var err error
var network *net.IPNet
composite := strings.Split(p, ";")
for _, c := range composite {
if r := strings.SplitN(c, "-", 2); len(r) == 2 {
// validate IP range
firstip := net.ParseIP(r[0])
if firstip == nil {
return fmt.Errorf("'%s' is not a valid IP range start", r[0])
}
_, ipNet, err := net.ParseCIDR(r[1])
if err != nil {
return fmt.Errorf("'%s' is not a valid CIDR: %s", r[1], err)
}
if !ipNet.Contains(firstip) {
return fmt.Errorf("'%s' is not a valid IP range start for CIDR %s", ipNet.String(), firstip)
}
if network == nil {
network = ipNet
} else {
if !network.IP.Equal(ipNet.IP) {
return fmt.Errorf("network mismatch: '%s' != '%s'", network, ipNet)
}
netOnes, netBits := network.Mask.Size()
ones, bits := ipNet.Mask.Size()
if netOnes != ones || netBits != bits {
return fmt.Errorf("network mask mismatch: %v != %v", network.Mask, ipNet.Mask)
}
}
} else {
// validate prefix
if len(composite) > 1 {
return fmt.Errorf("%s composite subnet config is invalid", composite)
}
_, err = validatePrefix(c)
}
}
return err
}
type InterfaceType string
const (
NSMVlan = "nsm-vlan"
NAD = "network-attachment"
)
func subnetsOverlap(a, b *net.IPNet) bool {
return subnetContainsSubnet(a, b) || subnetContainsSubnet(b, a)
}
func subnetContainsSubnet(outer, inner *net.IPNet) bool {
ol, _ := outer.Mask.Size()
il, _ := inner.Mask.Size()
if ol == il && outer.IP.Equal(inner.IP) {
return true
}
if ol < il && outer.Contains(inner.IP) {
return true
}
return false
}
type Ports struct {
Start uint64
End uint64
}
func validPortsFormat(p string) (Ports, error) {
var ports []string
if strings.Contains(p, "-") {
ports = strings.Split(p, "-")
if len(ports) != 2 {
return Ports{}, fmt.Errorf("wrong format to define port range, <starting port>-<ending port>")
}
return NewPortFromString(ports[0], ports[1])
} else if p == "any" {
return NewPort(0, 65535)
} else {
return NewPortFromString(p, p)
}
}
func NewPortFromString(start, end string) (Ports, error) {
startInt, err := strconv.ParseUint(start, 10, 16)
if err != nil {
return Ports{}, fmt.Errorf("starting port %s is not a valid port number, an integer between 0 and 65535", start)
}
endInt, err := strconv.ParseUint(end, 10, 16)
if err != nil {
return Ports{}, fmt.Errorf("ending port %s is not a valid port number, an integer between 0 and 65535", end)
}
return NewPort(startInt, endInt)
}
func NewPort(start, end uint64) (Ports, error) {
if start > end {
return Ports{}, fmt.Errorf("starting port cannot be larger than ending port in the ports range")
}
return Ports{start, end}, nil
}