1 # Copyright 2015 Intel Corporation.
2 # Copyright 2015 Isaku Yamahata <isaku.yamahata at intel com>
3 # <isaku.yamahata at gmail com>
7 # Licensed under the Apache License, Version 2.0 (the "License"); you may
8 # not use this file except in compliance with the License. You may obtain
9 # a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 # License for the specific language governing permissions and limitations
20 from oslo_log import log as logging
22 from neutron.agent.linux import ip_lib
23 from neutron.i18n import _LE
25 LOG = logging.getLogger(__name__)
27 # NOTE(toabctl): Don't use /sys/devices/virtual/net here because not all tap
28 # devices are listed here (i.e. when using Xen)
29 BRIDGE_FS = "/sys/class/net/"
30 BRIDGE_INTERFACE_FS = BRIDGE_FS + "%(bridge)s/brif/%(interface)s"
31 BRIDGE_INTERFACES_FS = BRIDGE_FS + "%s/brif/"
32 BRIDGE_PORT_FS_FOR_DEVICE = BRIDGE_FS + "%s/brport"
33 BRIDGE_PATH_FOR_DEVICE = BRIDGE_PORT_FS_FOR_DEVICE + '/bridge'
36 def is_bridged_interface(interface):
40 return os.path.exists(BRIDGE_PORT_FS_FOR_DEVICE % interface)
43 def get_bridge_names():
44 return os.listdir(BRIDGE_FS)
47 class BridgeDevice(ip_lib.IPDevice):
48 def _brctl(self, cmd):
50 ip_wrapper = ip_lib.IPWrapper(self.namespace)
51 return ip_wrapper.netns.execute(cmd, run_as_root=True)
53 def _sysctl(self, cmd):
54 """execute() doesn't return the exit status of the command it runs,
55 it returns stdout and stderr. Setting check_exit_code=True will cause
56 it to raise a RuntimeError if the exit status of the command is
57 non-zero, which in sysctl's case is an error. So we're normalizing
58 that into zero (success) and one (failure) here to mimic what
59 "echo $?" in a shell would be.
61 This is all because sysctl is too verbose and prints the value you
62 just set on success, unlike most other utilities that print nothing.
64 execute() will have dumped a message to the logs with the actual
65 output on failure, so it's not lost, and we don't need to print it
68 cmd = ['sysctl', '-w'] + cmd
69 ip_wrapper = ip_lib.IPWrapper(self.namespace)
71 ip_wrapper.netns.execute(cmd, run_as_root=True,
74 LOG.exception(_LE("Failed running %s"), cmd)
80 def addbr(cls, name, namespace=None):
81 bridge = cls(name, namespace)
82 bridge._brctl(['addbr', bridge.name])
86 def get_interface_bridge(cls, interface):
88 path = os.readlink(BRIDGE_PATH_FOR_DEVICE % interface)
92 name = path.rpartition('/')[-1]
96 return self._brctl(['delbr', self.name])
98 def addif(self, interface):
99 return self._brctl(['addif', self.name, interface])
101 def delif(self, interface):
102 return self._brctl(['delif', self.name, interface])
105 return self._brctl(['setfd', self.name, str(fd)])
107 def disable_stp(self):
108 return self._brctl(['stp', self.name, 'off'])
110 def disable_ipv6(self):
111 cmd = 'net.ipv6.conf.%s.disable_ipv6=1' % self.name
112 return self._sysctl([cmd])
114 def owns_interface(self, interface):
115 return os.path.exists(
116 BRIDGE_INTERFACE_FS % {'bridge': self.name,
117 'interface': interface})
119 def get_interfaces(self):
121 return os.listdir(BRIDGE_INTERFACES_FS % self.name)