neutron/agent/common/ovs_lib.py
实现了 linux 上 ovs 命令的操作。
class VifPort(object):
def __init__(self, port_name, ofport, vif_id, vif_mac, switch):
self.port_name = port_name
self.ofport = ofport
self.vif_id = vif_id
self.vif_mac = vif_mac
self.switch = switch
def __str__(self):
return ("iface-id=%s, vif_mac=%s, port_name=%s, ofport=%s, "
"bridge_name=%s") % (
self.vif_id, self.vif_mac,
self.port_name, self.ofport,
self.switch.br_name)
对 OvsdbIdl
和 command 的封装
class BaseOVS(object):
def __init__(self):
self.vsctl_timeout = cfg.CONF.ovs_vsctl_timeout
self.ovsdb = ovsdb.API.get(self)
ovs_vsctl_timeout
在 dhcp_agent.ini
和 l3_agent.ini
中都有设定:ovs_vsctl_timeout = 10
。指的是 ovs-vsctl 命令的超时时间。
ovsdb
:OvsdbIdl
的实例
调用 ovsdb 增加 manager
调用 ovsdb 获取 manager
调用 ovsdb 删除 manager
调用 ovsdb 增加 bridge,并返回以 OVSBridge
封装的 bridge
调用 ovsdb 删除 bridge
调用 ovsdb 判断 bridger 是否存在
调用 ovsdb 查询 Port,判断 port 是否存在
调用 ovsdb 根据接口名称获取其所在的 bridge
获取 bridge 列表
获取 bridge 的 bridge-id。
相当于执行命令:ovs-vsctl br-get-external-id br-int bridge-id
设置 ovsdb 中某些别的记录值
调用 ovsdb 清除某个表中某个记录的某个属性的值
调用 ovsdb 获取某个表中某个记录的某个属性的值
属性方法
读取 Open_vSwitch 表中的记录
属性方法。
{
'datapath_types': [system],
'iface_types': [u'geneve', u'gre', u'internal', u'ipsec_gre', u'lisp', u'patch', u'stt', u'system', u'tap', u'vxlan'],
}
构造这个字典。
对名称为 name 的 bridge 的封装
def __init__(self, br_name, datapath_type=constants.OVS_DATAPATH_SYSTEM):
super(OVSBridge, self).__init__()
self.br_name = br_name
self.datapath_type = datapath_type
self._default_cookie = generate_random_cookie()
_default_cookie 代表了对当前 bridge flow 操作的 cookie 值
属性方法,返回 self._default_cookie
def set_agent_uuid_stamp(self, val):
self._default_cookie = val
def __enter__(self):
self.create()
return self
def __exit__(self, exc_type, exc_value, exc_tb):
self.destroy()
创建一个以 self.name
为名称的 bridge,并设置 fail mode 为 secure
删除以 self.name
为名称的 bridge
为该 bridge 设置 controller
为该 bridge 删除 controller
读取该 bridge 的 controller
设置该 bridge 的 fail mode
将该 bridge 的 fail mode 设置为 security
将该 bridge 的 fail mode 设置为 standalone
设置该 bridge 的 protocols 属性
执行如下命令:
ovs-vsctl get Bridge br-int protocols
返回值:
["OpenFlow10", "OpenFlow13"]
获取一个接口的 ofport。
ovs-vsctl get Interface br-ex ofport
65534
将该 port 的 interface 的 ofport 作为自己的 ofport
为该 Bridge 增加 port,并设置 port 对应 Interface 的属性
删除该 bridge 上名称为 port_name 的 port 重新增加名称为 port_name 的 port 设置该 Port 的 Interface 的属性
删除该 bridge 上的一个 port
运行 ovs-ofctl
的命令。
通过运行 ovs-ofctl dump-flows self.name
统计该 bridge 上流表的数量
通过运行 ovs-ofctl del-flows self.name
删除该 bridge 上所有的流表
获取该 bridge 的 datapath_id
调用 ovs-ofctl 执行添加、删除、修改流表的动作。
例如:
ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
ovs-ofctl add-flow ovs-switch "table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
调用 ovs-ofctl add-flow 来增加流表
调用 ovs-ofctl mod-flow 来修改流表
调用 ovs-ofctl del-flow 来删除该 bridge 的流表记录
根据参数调用 ovs-ofctl dump-flows 命令查询该 bridge 上的流表。
查询该 bridge 上某个流表内的记录
查询改 bridge 上的所有流表记录
构造一个 DeferredOVSBridge
实例
def add_tunnel_port(self, port_name, remote_ip, local_ip, tunnel_type=p_const.TYPE_GRE, vxlan_udp_port=p_const.VXLAN_UDP_PORT, dont_fragment=True, tunnel_csum=False)
增加一个 tunnel 类型的接口。
如同执行如下命令:
# ovs-vsctl add-port br1 vx1 -- set interface vx1 type=vxlan options:remote_ip=192.168.146.136
为当前的 bridge 增加一个 patch port
ovs-vsctl \
-- add-port br0 patch-ovs-1 \
-- set interface patch0 type=patch options:peer=patch-ovs-2 \
-- add-port br1 patch-ovs-2 \
-- set interface patch1 type=patch options:peer=patch-ovs-1
获取该 bridge 上所有的 interface 名称
获取该 bridge 上所有的 port 名称
通过获取 interface 的 statistics
属性来用作 Port 的状态
调用 xe 命令
def get_ports_attributes(self, table, columns=None, ports=None, check_error=True, log_errors=True, if_exists=False)
通过读取数据库中的 table,获取指定 ports 的属性(column)。
获取 VIF port,并用 VifPort
封装,并且过滤掉在 ofport_filter 中声明的 port。
在 interface 的 external_ids 的属性中获取 iface_id 或者 xs-vif-uuid
构造一个映射。{iface_id:ofport}
获取有效的 vif port 集合(以 iface_id
标识 vif port)。
构造一个 port 的名称与 vlan tag 的集合
通过检查 Interface 的 ofport 判断该 port 是够正常
通过 port_id 构造该 port 封装 VifPort
(批量获取)
通过 port_id 构造该 port 封装 VifPort
(单个获取)
若 all_ports 为真则删除所有 port 若为假则删除 vif port
获取该 bridge 的 local port 的 mac 地址(br-ex 的 local port 为 br-ex)
设定该 bridge controller 的 connection_mode
设定该 interface 的 ingress_policing_rate
和 ingress_policing_burst
直接调用 _set_egress_bw_limit_for_port
获取该 interface 的 ingress_policing_rate
和 ingress_policing_burst
设定该 interface 的 ingress_policing_rate
和 ingress_policing_burst
为0
class DeferredOVSBridge(object):
'''Deferred OVSBridge.
This class wraps add_flow, mod_flow and delete_flows calls to an OVSBridge
and defers their application until apply_flows call in order to perform
bulk calls. It wraps also ALLOWED_PASSTHROUGHS calls to avoid mixing
OVSBridge and DeferredOVSBridge uses.
This class can be used as a context, in such case apply_flows is called on
__exit__ except if an exception is raised.
This class is not thread-safe, that's why for every use a new instance
must be implemented.
'''
ALLOWED_PASSTHROUGHS = 'add_port', 'add_tunnel_port', 'delete_port'
def __init__(self, br, full_ordered=False,
order=('add', 'mod', 'del')):
'''Constructor.
:param br: wrapped bridge
:param full_ordered: Optional, disable flow reordering (slower)
:param order: Optional, define in which order flow are applied
'''
self.br = br
self.full_ordered = full_ordered
self.order = order
if not self.full_ordered:
self.weights = dict((y, x) for x, y in enumerate(self.order))
self.action_flow_tuples = []
def __getattr__(self, name):
if name in self.ALLOWED_PASSTHROUGHS:
return getattr(self.br, name)
raise AttributeError(name)
def add_flow(self, **kwargs):
self.action_flow_tuples.append(('add', kwargs))
def mod_flow(self, **kwargs):
self.action_flow_tuples.append(('mod', kwargs))
def delete_flows(self, **kwargs):
self.action_flow_tuples.append(('del', kwargs))
def apply_flows(self):
action_flow_tuples = self.action_flow_tuples
self.action_flow_tuples = []
if not action_flow_tuples:
return
if not self.full_ordered:
action_flow_tuples.sort(key=lambda af: self.weights[af[0]])
grouped = itertools.groupby(action_flow_tuples,
key=operator.itemgetter(0))
itemgetter_1 = operator.itemgetter(1)
for action, action_flow_list in grouped:
flows = list(map(itemgetter_1, action_flow_list))
self.br.do_action_flows(action, flows)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None:
self.apply_flows()
else:
LOG.exception(_LE("OVS flows could not be applied on bridge %s"),
self.br.br_name)
def generate_random_cookie():
return uuid.uuid4().int & UINT64_BITMASK
构建 ovs-ofctl 命令中的流表。