1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
16 from vstf.agent.env.vswitch_plugins import model
17 from vstf.common.utils import check_and_kill, check_and_rmmod, check_call, check_output, \
18 get_eth_by_bdf, my_mkdir, call
20 LOG = logging.getLogger(__name__)
23 class OvsPlugin(model.VswitchPlugin):
26 self.daemons = ['ovs-vswitchd', 'ovsdb-server']
27 self.mods = ['openvswitch']
28 self.dirs = {'db': "/usr/local/etc/openvswitch"}
30 self.cmds.append("mkdir -p /usr/local/etc/openvswitch")
32 "ovsdb-tool create /usr/local/etc/openvswitch/conf.db")
33 self.cmds.append("ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \
34 --remote=db:Open_vSwitch,Open_vSwitch,manager_options \
35 --private-key=db:Open_vSwitch,SSL,private_key \
36 --certificate=db:Open_vSwitch,SSL,certificate \
37 --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
39 self.cmds.append("ovs-vsctl --no-wait init")
40 self.cmds.append("ovs-vswitchd --pidfile --detach")
41 self.initialized = False
44 if not self.initialized:
46 self.initialized = True
49 """clean for ovs. Rmmod openvswitch.ko, kill openvswitch daemon process.
52 for process in self.daemons:
53 check_and_kill(process)
56 for _, directory in self.dirs.items():
57 if os.path.isdir(directory):
58 LOG.info('rm -rf %s', directory)
59 shutil.rmtree(directory, ignore_errors=True)
60 self.initialized = False
63 def create_br(self, br_cfg):
64 """Create a bridge(virtual switch). Return True for success, return False for failure.
66 :param dict br_cfg: configuration for bridge creation like
73 "vlan_mode": "access",
82 name, uplinks = br_cfg['name'], br_cfg['uplinks']
84 check_call("ovs-vsctl add-br %s" % (name), shell=True)
85 if br_cfg['vtep']: # vxlan supports
86 local_ip, remote_ip = br_cfg['vtep'][
87 'local_ip'], br_cfg['vtep']['remote_ip']
88 assert len(uplinks) == 1
90 device = get_eth_by_bdf(uplink['bdf'])
93 check_call("ifconfig %s %s up" % (device, local_ip), shell=True)
94 check_call("ovs-vsctl add-port %s %s" % (name, vtep), shell=True)
96 "ovs-vsctl set interface %s type=vxlan options:remote_ip=%s" %
97 (vtep, remote_ip), shell=True)
98 for uplink in uplinks:
99 device = get_eth_by_bdf(uplink['bdf'])
100 vlan_mode = uplink['vlan_mode']
101 vlan_id = uplink['vlan_id']
102 check_call("ip link set dev %s up" % device, shell=True)
103 call("ethtool -A %s rx off tx off " % device, shell=True)
104 check_call("ovs-vsctl add-port %s %s" % (name, device), shell=True)
105 if vlan_mode == 'trunk':
107 "ovs-vsctl set port %s trunks=%s" %
108 (device, vlan_id), shell=True)
109 elif vlan_mode == 'access':
111 "ovs-vsctl set port %s tag=%s" %
112 (device, vlan_id), shell=True)
114 raise Exception("unreconized vlan_mode:%s" % vlan_mode)
117 def set_tap_vid(self, tap_cfg):
118 """set vlan id or vxlan id for tap device(virtual nic for vm).
119 return True for success, return False for failure.
121 :param dict tap_cfg: dictionary config for tap device like
123 "tap_name": "tap_in",
124 "vlan_mode": "access",
129 port, vlan_mode, vlan = tap_cfg['tap_name'], tap_cfg[
130 'vlan_mode'], tap_cfg['vlan_id']
131 assert vlan_mode in ('access', 'vxlan')
132 if int(vlan) > '4095':
134 self.__set_tap_vid(port, "vxlan", vlan)
137 self.__set_tap_vid(port, vlan_mode, vlan)
140 def set_fastlink(self, br_cfg):
141 """connect two ports directly, so that packets comes from any one port be forwarded to the other.
142 return True for success, return False for failure.
144 :param dict br_cfg: dictionary configuration for linking ports.
155 br_name = br_cfg['name']
156 for fast_cfg in br_cfg['fastlink']:
157 p1, p2 = fast_cfg['inport'], fast_cfg['outport']
158 self.__fastlink(br_name, p1, p2)
161 def _start_servers(self):
162 for _, directory in self.dirs.items():
164 for mod in self.mods:
165 check_call("modprobe %s" % mod, shell=True)
166 for cmd in self.cmds:
167 check_call(cmd, shell=True)
170 def __set_tap_vid(self, port, vlan_mode, vlan_id):
171 if vlan_mode == 'vxlan':
172 raise Exception("don't support vxlan setting right now.")
173 elif vlan_mode == 'trunk':
175 "ovs-vsctl set port %s trunks=%s" %
176 (port, vlan_id), shell=True)
179 "ovs-vsctl set port %s tag=%s" %
180 (port, vlan_id), shell=True)
182 def __fastlink(self, br, p1, p2):
183 LOG.info("_fastlink(%s,%s,%s)", br, p1, p2)
184 p1 = p1.replace(' ', '')
185 p2 = p2.replace(' ', '')
187 "lspci |grep Eth | awk '{print $1}'",
188 shell=True).splitlines()
190 p1 = get_eth_by_bdf(p1)
192 p2 = get_eth_by_bdf(p2)
194 buf = check_output("ovs-ofctl show %s" % br, shell=True)
195 port_info = re.compile(r"[0-9]+\(.*\)", re.IGNORECASE | re.MULTILINE)
196 for s in port_info.findall(buf):
197 port_num, interface = s.replace('(', ' ').replace(')', ' ').split()
198 ovs_port[interface] = port_num
199 pn1, pn2 = ovs_port[p1], ovs_port[p2]
201 "ovs-ofctl add-flow %s in_port=%s,priority=100,action=output:%s" %
202 (br, pn1, pn2), shell=True)
204 "ovs-ofctl add-flow %s in_port=%s,priority=100,action=output:%s" %
205 (br, pn2, pn1), shell=True)