backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / bgp / utils / validation.py
1 # Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """
17  Module provides utilities for validation.
18 """
19 import numbers
20 import re
21 import socket
22
23 from ryu.lib import ip
24
25
26 def is_valid_mac(mac):
27     """Returns True if the given MAC address is valid.
28
29     The given MAC address should be a colon hexadecimal notation string.
30
31     Samples:
32         - valid address: aa:bb:cc:dd:ee:ff, 11:22:33:44:55:66
33         - invalid address: aa:bb:cc:dd, 11-22-33-44-55-66, etc.
34     """
35     return bool(re.match(r'^' + r'[\:\-]'.join([r'([0-9a-f]{2})'] * 6)
36                          + r'$', mac.lower()))
37
38
39 def is_valid_ip_prefix(prefix, bits):
40     """Returns True if *prefix* is a valid IPv4 or IPv6 address prefix.
41
42     *prefix* should be a number between 0 to *bits* length.
43     """
44     try:
45         # Prefix should be a number
46         prefix = int(prefix)
47     except ValueError:
48         return False
49
50     # Prefix should be a number between 0 to *bits*
51     return 0 <= prefix <= bits
52
53
54 def is_valid_ipv4(ipv4):
55     """Returns True if given is a valid ipv4 address.
56
57     Given value should be a dot-decimal notation string.
58
59     Samples:
60         - valid address: 10.0.0.1, 192.168.0.1
61         - invalid address: 11.0.0, 192:168:0:1, etc.
62     """
63     return ip.valid_ipv4(ipv4)
64
65
66 def is_valid_ipv4_prefix(ipv4_prefix):
67     """Returns True if *ipv4_prefix* is a valid prefix with mask.
68
69     Samples:
70         - valid prefix: 1.1.1.0/32, 244.244.244.1/10
71         - invalid prefix: 255.2.2.2/2, 2.2.2/22, etc.
72     """
73     if not isinstance(ipv4_prefix, str):
74         return False
75
76     tokens = ipv4_prefix.split('/')
77     if len(tokens) != 2:
78         return False
79
80     # Validate address/mask and return
81     return is_valid_ipv4(tokens[0]) and is_valid_ip_prefix(tokens[1], 32)
82
83
84 def is_valid_ipv6(ipv6):
85     """Returns True if given `ipv6` is a valid IPv6 address
86     """
87     return ip.valid_ipv6(ipv6)
88
89
90 def is_valid_ipv6_prefix(ipv6_prefix):
91     """Returns True if given `ipv6_prefix` is a valid IPv6 prefix."""
92
93     # Validate input type
94     if not isinstance(ipv6_prefix, str):
95         return False
96
97     tokens = ipv6_prefix.split('/')
98     if len(tokens) != 2:
99         return False
100
101     # Validate address/mask and return
102     return is_valid_ipv6(tokens[0]) and is_valid_ip_prefix(tokens[1], 128)
103
104
105 def is_valid_old_asn(asn):
106     """Returns True if the given AS number is Two Octet."""
107     return isinstance(asn, numbers.Integral) and 0 <= asn <= 0xffff
108
109
110 def is_valid_asn(asn):
111     """Returns True if the given AS number is Two or Four Octet."""
112     return isinstance(asn, numbers.Integral) and 0 <= asn <= 0xffffffff
113
114
115 def is_valid_vpnv4_prefix(prefix):
116     """Returns True if given prefix is a string represent vpnv4 prefix.
117
118     Vpnv4 prefix is made up of RD:Ipv4, where RD is represents route
119     distinguisher and Ipv4 represents valid dot-decimal ipv4 notation string.
120     """
121     if not isinstance(prefix, str):
122         return False
123
124     # Split the prefix into route distinguisher and IP
125     tokens = prefix.split(':', 2)
126     if len(tokens) != 3:
127         return False
128
129     # Validate route distinguisher
130     if not is_valid_route_dist(':'.join([tokens[0], tokens[1]])):
131         return False
132
133     # Validate IPv4 prefix and return
134     return is_valid_ipv4_prefix(tokens[2])
135
136
137 def is_valid_vpnv6_prefix(prefix):
138     """Returns True if given prefix is a string represent vpnv6 prefix.
139
140     Vpnv6 prefix is made up of RD:Ipv6, where RD is represents route
141     distinguisher and Ipv6 represents valid colon hexadecimal notation string.
142     """
143     if not isinstance(prefix, str):
144         return False
145
146     # Split the prefix into route distinguisher and IP
147     tokens = prefix.split(':', 2)
148     if len(tokens) != 3:
149         return False
150
151     # Validate route distinguisher
152     if not is_valid_route_dist(':'.join([tokens[0], tokens[1]])):
153         return False
154
155     # Validate IPv6 prefix and return
156     return is_valid_ipv6_prefix(tokens[2])
157
158
159 def is_valid_med(med):
160     """Returns True if value of *med* is valid as per RFC.
161
162     According to RFC MED is a four octet non-negative integer and
163     value '((2 ** 32) - 1) =  0xffffffff' denotes an "infinity" metric.
164     """
165     return isinstance(med, numbers.Integral) and 0 <= med <= 0xffffffff
166
167
168 def is_valid_mpls_label(label):
169     """Validates `label` according to MPLS label rules
170
171     RFC says:
172     This 20-bit field.
173     A value of 0 represents the "IPv4 Explicit NULL Label".
174     A value of 1 represents the "Router Alert Label".
175     A value of 2 represents the "IPv6 Explicit NULL Label".
176     A value of 3 represents the "Implicit NULL Label".
177     Values 4-15 are reserved.
178     """
179     if (not isinstance(label, numbers.Integral) or
180             (4 <= label <= 15) or
181             (label < 0 or label > 2 ** 20)):
182         return False
183
184     return True
185
186
187 def is_valid_mpls_labels(labels):
188     """Returns True if the given value is a list of valid MPLS labels.
189     """
190     if not isinstance(labels, (list, tuple)):
191         return False
192
193     for label in labels:
194         if not is_valid_mpls_label(label):
195             return False
196
197     return True
198
199
200 def is_valid_route_dist(route_dist):
201     """Validates *route_dist* as string representation of route distinguisher.
202
203     Returns True if *route_dist* is as per our convention of RD, else False.
204     Our convention is to represent RD as a string in format:
205     *admin_sub_field:assigned_num_field* and *admin_sub_field* can be valid
206     IPv4 string representation.
207     Valid examples: '65000:222', '1.2.3.4:4432'.
208     Invalid examples: '1.11.1: 333'
209     """
210     # TODO(PH): Provide complete implementation.
211     return is_valid_ext_comm_attr(route_dist)
212
213
214 def is_valid_ext_comm_attr(attr):
215     """Validates *attr* as string representation of RT or SOO.
216
217     Returns True if *attr* is as per our convention of RT or SOO, else
218     False. Our convention is to represent RT/SOO is a string with format:
219     *global_admin_part:local_admin_path*
220     """
221     if not isinstance(attr, str):
222         return False
223
224     tokens = attr.rsplit(':', 1)
225     if len(tokens) != 2:
226         return False
227
228     try:
229         if '.' in tokens[0]:
230             if not is_valid_ipv4(tokens[0]):
231                 return False
232         else:
233             int(tokens[0])
234         int(tokens[1])
235     except (ValueError, socket.error):
236         return False
237
238     return True
239
240
241 def is_valid_esi(esi):
242     """Returns True if the given EVPN Ethernet SegmentEthernet ID is valid."""
243     if isinstance(esi, numbers.Integral):
244         return 0 <= esi <= 0xffffffffffffffffff
245     return isinstance(esi, dict)
246
247
248 def is_valid_ethernet_tag_id(etag_id):
249     """Returns True if the given EVPN Ethernet Tag ID is valid.
250
251     Ethernet Tag ID should be a 32-bit field number.
252     """
253     return isinstance(etag_id, numbers.Integral) and 0 <= etag_id <= 0xffffffff
254
255
256 def is_valid_vni(vni):
257     """Returns True if the given Virtual Network Identifier for VXLAN
258     is valid.
259
260     Virtual Network Identifier should be a 24-bit field number.
261     """
262     return isinstance(vni, numbers.Integral) and 0 <= vni <= 0xffffff