LLDP OVS enablement: puppet configuration
This commit introduces puppet configuration enabling LLDP to operate over OVS. Specifically, separate ports flows are configured to handle LLDP traffic. In addition, we restrict the lldpd daemon from operating over bridge, tap, and ovs-netdev devices. Story: 2002946 Task: 22940 Change-Id: Ibadc9c082425412b5b68b02a55e8c02692de0e17 Signed-off-by: Steven Webster <steven.webster@windriver.com>
This commit is contained in:
parent
08010aff21
commit
da1110a3d8
@ -35,6 +35,7 @@ define platform::vswitch::ovs::device(
|
||||
|
||||
define platform::vswitch::ovs::bridge(
|
||||
$datapath_type = 'netdev',
|
||||
$attributes = [],
|
||||
) {
|
||||
exec { "ovs-add-br: ${title}":
|
||||
command => template("platform/ovs.add-bridge.erb")
|
||||
@ -69,11 +70,24 @@ define platform::vswitch::ovs::address(
|
||||
}
|
||||
|
||||
|
||||
define platform::vswitch::ovs::flow(
|
||||
$bridge,
|
||||
$attributes = [],
|
||||
$actions,
|
||||
) {
|
||||
exec { "ovs-add-flow: ${title}":
|
||||
command => template("platform/ovs.add-flow.erb"),
|
||||
logoutput => true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class platform::vswitch::ovs(
|
||||
$devices = {},
|
||||
$bridges = {},
|
||||
$ports = {},
|
||||
$addresses = {},
|
||||
$flows = {},
|
||||
) inherits ::platform::vswitch::params {
|
||||
|
||||
if $::platform::params::vswitch_type == 'ovs' {
|
||||
@ -116,6 +130,7 @@ class platform::vswitch::ovs(
|
||||
|
||||
Platform::Vswitch::Ovs::Bridge<||> -> Platform::Vswitch::Ovs::Port<||>
|
||||
Platform::Vswitch::Ovs::Bridge<||> -> Platform::Vswitch::Ovs::Address<||>
|
||||
Platform::Vswitch::Ovs::Port<||> -> Platform::Vswitch::Ovs::Flow<||>
|
||||
}
|
||||
|
||||
create_resources('platform::vswitch::ovs::bridge', $bridges, {
|
||||
@ -129,4 +144,8 @@ class platform::vswitch::ovs(
|
||||
create_resources('platform::vswitch::ovs::address', $addresses, {
|
||||
require => Service['openvswitch']
|
||||
})
|
||||
|
||||
create_resources('platform::vswitch::ovs::flow', $flows, {
|
||||
require => Service['openvswitch']
|
||||
})
|
||||
}
|
||||
|
@ -2,3 +2,4 @@ configure system hostname '<%= @hostname %>:<%= @system %>'
|
||||
configure system description 'Titanium Cloud version <%= @version %>'
|
||||
configure lldp tx-interval <%= @tx_interval %>
|
||||
configure lldp tx-hold <%= @tx_hold %>
|
||||
configure system interface pattern *,!br*,!ovs*,!tap*
|
||||
|
@ -1,2 +1,6 @@
|
||||
ovs-vsctl --timeout 10 -- --may-exist add-br <%= @name -%>
|
||||
-- set bridge <%= @name -%> datapath_type=<%= @datapath_type -%>
|
||||
-- set bridge <%= @name -%>
|
||||
<%- @attributes.each do |attribute| -%>
|
||||
<%= attribute -%>
|
||||
<%- end -%>
|
||||
datapath_type=<%= @datapath_type -%>
|
||||
|
@ -0,0 +1,9 @@
|
||||
ovs-ofctl add-flow <%= @bridge -%>
|
||||
<%- @attributes.each_with_index do |attrib, idx| -%>
|
||||
<% if idx == 0 %> <% else -%>,<% end -%>
|
||||
<%= attrib[0] -%>=<%= attrib[1] -%>
|
||||
<%- end -%>
|
||||
,actions=<%- @actions.each_with_index do |action, idx| -%>
|
||||
<%- if idx > 0 -%>,<%- end -%>
|
||||
<%= action['type'] -%>:<%= action['value'] -%>
|
||||
<%- end -%>
|
@ -13,4 +13,9 @@ ovs-vsctl --timeout 10 -- --may-exist add-<%= @type -%> <%= @bridge -%> <%= @nam
|
||||
<%- interface['attributes'].each do |attribute| -%>
|
||||
<%= attribute -%>
|
||||
<%- end -%>
|
||||
<%- end %>
|
||||
<%- @interfaces.each do |interface| -%>
|
||||
<%- if interface['type'] == 'internal' -%>
|
||||
ip link set <%= interface['name'] -%> up
|
||||
<%- end -%>
|
||||
<%- end -%>
|
||||
|
@ -17,7 +17,8 @@
|
||||
class sysinv::agent (
|
||||
$agent_driver = false,
|
||||
$package_ensure = 'latest',
|
||||
$enabled = true
|
||||
$enabled = true,
|
||||
$lldp_drivers = []
|
||||
) {
|
||||
|
||||
include sysinv::params
|
||||
@ -32,6 +33,10 @@ class sysinv::agent (
|
||||
}
|
||||
}
|
||||
|
||||
sysinv_config {
|
||||
'lldp/drivers': value => join($lldp_drivers,",");
|
||||
}
|
||||
|
||||
if $::sysinv::params::agent_package {
|
||||
Package['sysinv-agent'] -> Sysinv_config<||>
|
||||
Package['sysinv-agent'] -> Sysinv_api_paste_ini<||>
|
||||
|
@ -1041,6 +1041,10 @@ UPGRADE_ABORT_COMPLETING = 'abort-completing'
|
||||
UPGRADE_ABORTING_ROLLBACK = 'aborting-reinstall'
|
||||
|
||||
# LLDP
|
||||
LLDP_OVS_PORT_PREFIX = 'lldp'
|
||||
LLDP_OVS_PORT_NAME_LEN = 15
|
||||
LLDP_MULTICAST_ADDRESS = '01:80:c2:00:00:0e'
|
||||
LLDP_ETHER_TYPE = '0x88cc'
|
||||
LLDP_TLV_TYPE_CHASSIS_ID = 'chassis_id'
|
||||
LLDP_TLV_TYPE_PORT_ID = 'port_identifier'
|
||||
LLDP_TLV_TYPE_TTL = 'ttl'
|
||||
|
@ -2039,6 +2039,15 @@ class ConductorManager(service.PeriodicService):
|
||||
LOG.info("Updating port name: %s to %s" % (port_name, updated_name))
|
||||
self.dbapi.ethernet_port_update(port['uuid'], {'name': updated_name})
|
||||
|
||||
def lldp_id_to_port(self, id, ports):
|
||||
ovs_id = re.sub(r'^{}'.format(constants.LLDP_OVS_PORT_PREFIX), '', id)
|
||||
for port in ports:
|
||||
if (port['name'] == id or
|
||||
port['uuid'] == id or
|
||||
port['uuid'].find(ovs_id) == 0):
|
||||
return port
|
||||
return None
|
||||
|
||||
def lldp_tlv_dict(self, agent_neighbour_dict):
|
||||
tlv_dict = {}
|
||||
for k, v in agent_neighbour_dict.iteritems():
|
||||
@ -2156,14 +2165,8 @@ class ConductorManager(service.PeriodicService):
|
||||
"Error getting LLDP agents for host %s") % host_uuid)
|
||||
|
||||
for agent in agent_dict_array:
|
||||
port_found = None
|
||||
for db_port in db_ports:
|
||||
if (db_port['name'] == agent['name_or_uuid'] or
|
||||
db_port['uuid'] == agent['name_or_uuid']):
|
||||
port_found = db_port
|
||||
break
|
||||
|
||||
if not port_found:
|
||||
db_port = self.lldp_id_to_port(agent['name_or_uuid'], db_ports)
|
||||
if not db_port:
|
||||
LOG.debug("Could not find port for agent %s",
|
||||
agent['name_or_uuid'])
|
||||
return
|
||||
@ -2269,16 +2272,10 @@ class ConductorManager(service.PeriodicService):
|
||||
neighbour['uuid'])
|
||||
|
||||
for neighbour in neighbour_dict_array:
|
||||
port_found = None
|
||||
for db_port in db_ports:
|
||||
if (db_port['name'] == neighbour['name_or_uuid'] or
|
||||
db_port['uuid'] == neighbour['name_or_uuid']):
|
||||
port_found = db_port
|
||||
break
|
||||
|
||||
if not port_found:
|
||||
db_port = self.lldp_id_to_port(neighbour['name_or_uuid'], db_ports)
|
||||
if not db_port:
|
||||
LOG.debug("Could not find port for neighbour %s",
|
||||
neighbour['name'])
|
||||
neighbour['name_or_uuid'])
|
||||
return
|
||||
|
||||
LOG.debug("Processing lldp neighbour %s" % neighbour)
|
||||
|
@ -26,6 +26,7 @@ class OVSPuppet(base.BasePuppet):
|
||||
config.update(self._get_port_config(host))
|
||||
config.update(self._get_virtual_config(host))
|
||||
config.update(self._get_neutron_config(host))
|
||||
config.update(self._get_lldp_config(host))
|
||||
return config
|
||||
|
||||
def _get_port_config(self, host):
|
||||
@ -33,6 +34,7 @@ class OVSPuppet(base.BasePuppet):
|
||||
ovs_bridges = {}
|
||||
ovs_ports = {}
|
||||
ovs_addresses = {}
|
||||
ovs_flows = {}
|
||||
|
||||
index = 0
|
||||
for iface in sorted(self.context['interfaces'].values(),
|
||||
@ -61,6 +63,31 @@ class OVSPuppet(base.BasePuppet):
|
||||
ovs_ports.update({port['name']: port})
|
||||
ovs_devices.update({d['pci_addr']: d for d in devices})
|
||||
|
||||
if iface['iftype'] == constants.INTERFACE_TYPE_ETHERNET:
|
||||
ovs_ifname = port['interfaces'][0]['name']
|
||||
lldp_port = self._get_lldp_port(
|
||||
iface, brname, ovs_ifname=ovs_ifname)
|
||||
ovs_ports.update({lldp_port['name']: lldp_port})
|
||||
flow = self._get_lldp_flow(
|
||||
brname, ovs_ifname, lldp_port['name'])
|
||||
ovs_flows.update({port['name']: flow})
|
||||
|
||||
if iface['iftype'] == constants.INTERFACE_TYPE_AE:
|
||||
slaves = interface.get_bond_interface_slaves(
|
||||
self.context, iface)
|
||||
for member, slave in enumerate(slaves):
|
||||
ovs_ifname = port['interfaces'][member]['name']
|
||||
|
||||
lldp_port = self._get_lldp_port(
|
||||
slave, brname, ovs_ifname=ovs_ifname)
|
||||
ovs_ports.update({lldp_port['name']: lldp_port})
|
||||
flow = self._get_lldp_flow(
|
||||
brname, ovs_ifname, lldp_port['name'])
|
||||
ovs_flows.update({flow['name']: flow})
|
||||
flow = self._get_lldp_flow(
|
||||
brname, lldp_port['name'], ovs_ifname)
|
||||
ovs_flows.update({flow['name']: flow})
|
||||
|
||||
index += 1
|
||||
|
||||
# currently only one provider network is supported per
|
||||
@ -83,6 +110,7 @@ class OVSPuppet(base.BasePuppet):
|
||||
'platform::vswitch::ovs::bridges': ovs_bridges,
|
||||
'platform::vswitch::ovs::ports': ovs_ports,
|
||||
'platform::vswitch::ovs::addresses': ovs_addresses,
|
||||
'platform::vswitch::ovs::flows': ovs_flows,
|
||||
}
|
||||
|
||||
def _get_ethernet_device(self, iface):
|
||||
@ -147,6 +175,74 @@ class OVSPuppet(base.BasePuppet):
|
||||
|
||||
return port, devices
|
||||
|
||||
def _get_lldp_interface(self, ifname, peer_ifname):
|
||||
attributes = []
|
||||
|
||||
iftype = 'internal'
|
||||
|
||||
attributes.append("other_config:lldp_phy_peer=%s" % peer_ifname)
|
||||
|
||||
return {
|
||||
'name': ifname,
|
||||
'type': iftype,
|
||||
'attributes': attributes,
|
||||
}
|
||||
|
||||
def _get_lldp_port(self, iface, lldp_brname, ovs_ifname=None):
|
||||
interfaces = []
|
||||
|
||||
port = interface.get_interface_port(self.context, iface)
|
||||
|
||||
# Limit port name length to the maximum supported by ovs-ofctl to
|
||||
# reference a port with a name rather than ofport number
|
||||
# when creating flows.
|
||||
|
||||
port_name_len = constants.LLDP_OVS_PORT_NAME_LEN
|
||||
uuid_len = port_name_len - len(constants.LLDP_OVS_PORT_PREFIX)
|
||||
|
||||
port_name = '{}{}'.format(constants.LLDP_OVS_PORT_PREFIX,
|
||||
port.uuid[:uuid_len])
|
||||
|
||||
if ovs_ifname:
|
||||
interfaces.append(self._get_lldp_interface(port_name, ovs_ifname))
|
||||
else:
|
||||
interfaces.append(self._get_lldp_interface(port_name, iface['name']))
|
||||
|
||||
port = {
|
||||
'name': port_name,
|
||||
'bridge': lldp_brname,
|
||||
'interfaces': interfaces,
|
||||
}
|
||||
|
||||
return port
|
||||
|
||||
def _get_lldp_flow(self, bridge, in_port, out_port):
|
||||
actions = []
|
||||
|
||||
attributes = {
|
||||
'idle_timeout': 0,
|
||||
'hard_timeout': 0,
|
||||
'in_port': in_port,
|
||||
'dl_dst': constants.LLDP_MULTICAST_ADDRESS,
|
||||
'dl_type': constants.LLDP_ETHER_TYPE
|
||||
}
|
||||
|
||||
action = {
|
||||
'type': 'output',
|
||||
'value': out_port
|
||||
}
|
||||
|
||||
actions.append(action)
|
||||
|
||||
flow = {
|
||||
'name': '{}-{}-{}'.format(bridge, in_port, out_port),
|
||||
'bridge': bridge,
|
||||
'attributes': attributes,
|
||||
'actions': actions
|
||||
}
|
||||
|
||||
return flow
|
||||
|
||||
def _get_bond_port(self, host, iface, bridge, index):
|
||||
devices = []
|
||||
interfaces = []
|
||||
@ -294,3 +390,11 @@ class OVSPuppet(base.BasePuppet):
|
||||
def _is_vxlan_providernet(self, name):
|
||||
providernet_type = self._get_providernet_type(name)
|
||||
return bool(providernet_type == constants.NEUTRON_PROVIDERNET_VXLAN)
|
||||
|
||||
def _get_lldp_config(self, host):
|
||||
driver_list = self.context['_lldp_drivers']
|
||||
driver_list.append('ovs')
|
||||
|
||||
return {
|
||||
'sysinv::agent::lldp_drivers': driver_list
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ class PlatformPuppet(base.BasePuppet):
|
||||
config.update(self._get_host_tpm_config(host))
|
||||
config.update(self._get_host_cpu_config(host))
|
||||
config.update(self._get_host_memory_config(host))
|
||||
config.update(self._get_host_lldp_config(host))
|
||||
return config
|
||||
|
||||
def _get_static_software_config(self):
|
||||
@ -818,3 +819,15 @@ class PlatformPuppet(base.BasePuppet):
|
||||
def _get_platform_cpu_count(self, host):
|
||||
cpus = self._get_host_cpu_list(host, constants.PLATFORM_FUNCTION, True)
|
||||
return len(cpus)
|
||||
|
||||
def _get_host_lldp_config(self, host):
|
||||
driver_list = []
|
||||
|
||||
# Default is lldpd
|
||||
driver_list.append('lldpd')
|
||||
|
||||
self.context['_lldp_drivers'] = driver_list
|
||||
|
||||
return {
|
||||
'sysinv::agent::lldp_drivers': driver_list
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user