charm-neutron-openvswitch/hooks/pci.py
James Page acd617f4ca Add support for DPDK userspace networking
Add full support for DPDK; this includes a number of configuration
options to allow the number of cores and memory allocated per
NUMA node to be changed.  By default, the first core and 1024MB of
RAM of each NUMA node will be configured for DPDK use.

When DPDK is enabled, OVS bridges are configured as datapath type
'netdev' rather than type 'system' to allow use of userspace
DPDK packet processing; Security groups are also disabled, as
iptables based rules cannot be applied against userspace sockets.

DPDK device binding is undertaken using /etc/dpdk/interfaces and
the dpdk init script provided as part of the DPDK package; device
resolution is determined using the data-port configuration option
using the <bridge:<mac address> format - MAC addresses are used
to resolve underlying PCI device names for binding with DPDK.

It's assumed that hugepage memory configuration is either done as
part of system boot as kernel command line options (set via MAAS)
or using the hugepages configuration option on the nova-compute
charm.

Change-Id: Ieb2ac522b07e495f1855e304d31eef59c316c0e4
2016-04-07 12:42:16 +01:00

119 lines
3.7 KiB
Python

#!/usr/bin/python
import os
import glob
import subprocess
import shlex
from charmhelpers.core.hookenv import(
log,
)
def format_pci_addr(pci_addr):
domain, bus, slot_func = pci_addr.split(':')
slot, func = slot_func.split('.')
return '{}:{}:{}.{}'.format(domain.zfill(4), bus.zfill(2), slot.zfill(2),
func)
class PCINetDevice(object):
def __init__(self, pci_address):
self.pci_address = pci_address
self.interface_name = None
self.mac_address = None
self.state = None
self.update_attributes()
def update_attributes(self):
self.update_interface_info()
def update_interface_info(self):
self.update_interface_info_eth()
def update_interface_info_eth(self):
net_devices = self.get_sysnet_interfaces_and_macs()
for interface in net_devices:
if self.pci_address == interface['pci_address']:
self.interface_name = interface['interface']
self.mac_address = interface['mac_address']
self.state = interface['state']
def get_sysnet_interfaces_and_macs(self):
net_devs = []
for sdir in glob.glob('/sys/class/net/*'):
sym_link = sdir + "/device"
if os.path.islink(sym_link):
fq_path = os.path.realpath(sym_link)
path = fq_path.split('/')
if 'virtio' in path[-1]:
pci_address = path[-2]
else:
pci_address = path[-1]
net_devs.append({
'interface': self.get_sysnet_interface(sdir),
'mac_address': self.get_sysnet_mac(sdir),
'pci_address': pci_address,
'state': self.get_sysnet_device_state(sdir),
})
return net_devs
def get_sysnet_mac(self, sysdir):
mac_addr_file = sysdir + '/address'
with open(mac_addr_file, 'r') as f:
read_data = f.read()
mac = read_data.strip()
log('mac from {} is {}'.format(mac_addr_file, mac))
return mac
def get_sysnet_device_state(self, sysdir):
state_file = sysdir + '/operstate'
with open(state_file, 'r') as f:
read_data = f.read()
state = read_data.strip()
log('state from {} is {}'.format(state_file, state))
return state
def get_sysnet_interface(self, sysdir):
return sysdir.split('/')[-1]
class PCINetDevices(object):
def __init__(self):
pci_addresses = self.get_pci_ethernet_addresses()
self.pci_devices = [PCINetDevice(dev) for dev in pci_addresses]
def get_pci_ethernet_addresses(self):
cmd = ['lspci', '-m', '-D']
lspci_output = subprocess.check_output(cmd)
pci_addresses = []
for line in lspci_output.split('\n'):
columns = shlex.split(line)
if len(columns) > 1 and columns[1] == 'Ethernet controller':
pci_address = columns[0]
pci_addresses.append(format_pci_addr(pci_address))
return pci_addresses
def update_devices(self):
for pcidev in self.pci_devices:
pcidev.update_attributes()
def get_macs(self):
macs = []
for pcidev in self.pci_devices:
if pcidev.mac_address:
macs.append(pcidev.mac_address)
return macs
def get_device_from_mac(self, mac):
for pcidev in self.pci_devices:
if pcidev.mac_address == mac:
return pcidev
return None
def get_device_from_pci_address(self, pci_addr):
for pcidev in self.pci_devices:
if pcidev.pci_address == pci_addr:
return pcidev
return None