a0c8f0cc70443b1df7abc7832a30db3b791d277a
[openstack-build/neutron-build.git] / neutron / common / ipv6_utils.py
1 # Copyright 2013 IBM Corp.
2 # All Rights Reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15
16 """
17 IPv6-related utilities and helper functions.
18 """
19 import os
20
21 import netaddr
22 from oslo_log import log
23
24 from neutron._i18n import _, _LI
25 from neutron.common import constants
26
27
28 LOG = log.getLogger(__name__)
29 _IS_IPV6_ENABLED = None
30
31
32 def get_ipv6_addr_by_EUI64(prefix, mac):
33     # Check if the prefix is IPv4 address
34     isIPv4 = netaddr.valid_ipv4(prefix)
35     if isIPv4:
36         msg = _("Unable to generate IP address by EUI64 for IPv4 prefix")
37         raise TypeError(msg)
38     try:
39         eui64 = int(netaddr.EUI(mac).eui64())
40         prefix = netaddr.IPNetwork(prefix)
41         return netaddr.IPAddress(prefix.first + eui64 ^ (1 << 57))
42     except (ValueError, netaddr.AddrFormatError):
43         raise TypeError(_('Bad prefix or mac format for generating IPv6 '
44                           'address by EUI-64: %(prefix)s, %(mac)s:')
45                         % {'prefix': prefix, 'mac': mac})
46     except TypeError:
47         raise TypeError(_('Bad prefix type for generate IPv6 address by '
48                           'EUI-64: %s') % prefix)
49
50
51 def is_enabled():
52     global _IS_IPV6_ENABLED
53
54     if _IS_IPV6_ENABLED is None:
55         disabled_ipv6_path = "/proc/sys/net/ipv6/conf/default/disable_ipv6"
56         if os.path.exists(disabled_ipv6_path):
57             with open(disabled_ipv6_path, 'r') as f:
58                 disabled = f.read().strip()
59             _IS_IPV6_ENABLED = disabled == "0"
60         else:
61             _IS_IPV6_ENABLED = False
62         if not _IS_IPV6_ENABLED:
63             LOG.info(_LI("IPv6 is not enabled on this system."))
64     return _IS_IPV6_ENABLED
65
66
67 def is_auto_address_subnet(subnet):
68     """Check if subnet is an auto address subnet."""
69     modes = [constants.IPV6_SLAAC, constants.DHCPV6_STATELESS]
70     return (subnet['ipv6_address_mode'] in modes
71             or subnet['ipv6_ra_mode'] in modes)
72
73
74 def is_eui64_address(ip_address):
75     """Check if ip address is EUI64."""
76     ip = netaddr.IPAddress(ip_address)
77     # '0xfffe' addition is used to build EUI-64 from MAC (RFC4291)
78     # Look for it in the middle of the EUI-64 part of address
79     return ip.version == 6 and not ((ip & 0xffff000000) ^ 0xfffe000000)
80
81
82 def is_ipv6_pd_enabled(subnet):
83     """Returns True if the subnetpool_id of the given subnet is equal to
84        constants.IPV6_PD_POOL_ID
85     """
86     return subnet.get('subnetpool_id') == constants.IPV6_PD_POOL_ID