basic support for Linux tap devices
our project needs to deploy taps using os-net-config utility. leverage a dedicated type from ifcfg implementation. Change-Id: Iaf4294bec6c21f130c7a149d0f45d3be53c1c9cc
This commit is contained in:
parent
1a1b1b710f
commit
da7614bc48
|
@ -0,0 +1,8 @@
|
||||||
|
{ "network_config": [
|
||||||
|
{
|
||||||
|
"type": "linux_tap",
|
||||||
|
"name": "tap0",
|
||||||
|
"use_dhcp": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
network_config:
|
||||||
|
-
|
||||||
|
type: linux_tap
|
||||||
|
name: tap0
|
||||||
|
use_dhcp: true
|
||||||
|
|
|
@ -118,6 +118,8 @@ class NetConfig(object):
|
||||||
self.add_contrail_vrouter(obj)
|
self.add_contrail_vrouter(obj)
|
||||||
elif isinstance(obj, objects.ContrailVrouterDpdk):
|
elif isinstance(obj, objects.ContrailVrouterDpdk):
|
||||||
self.add_contrail_vrouter_dpdk(obj)
|
self.add_contrail_vrouter_dpdk(obj)
|
||||||
|
elif isinstance(obj, objects.LinuxTap):
|
||||||
|
self.add_linux_tap(obj)
|
||||||
|
|
||||||
def add_route_table(self, route_table):
|
def add_route_table(self, route_table):
|
||||||
"""Add a route table object to the net config object.
|
"""Add a route table object to the net config object.
|
||||||
|
@ -284,6 +286,15 @@ class NetConfig(object):
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"add_contrail_vrouter_dpdk is not implemented.")
|
"add_contrail_vrouter_dpdk is not implemented.")
|
||||||
|
|
||||||
|
def add_linux_tap(self, linux_tap):
|
||||||
|
"""Add a LinuxTap object to the net config object.
|
||||||
|
|
||||||
|
:param linux_tap:
|
||||||
|
The LinuxTap object to add.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError(
|
||||||
|
"add_linux_tap is not implemented.")
|
||||||
|
|
||||||
def apply(self, cleanup=False):
|
def apply(self, cleanup=False):
|
||||||
"""Apply the network configuration.
|
"""Apply the network configuration.
|
||||||
|
|
||||||
|
|
|
@ -1114,6 +1114,18 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||||
self._add_rules(contrail_vrouter_dpdk.name,
|
self._add_rules(contrail_vrouter_dpdk.name,
|
||||||
contrail_vrouter_dpdk.rules)
|
contrail_vrouter_dpdk.rules)
|
||||||
|
|
||||||
|
def add_linux_tap(self, linux_tap):
|
||||||
|
"""Add a LinuxTap object to the net config object
|
||||||
|
|
||||||
|
:param linux_tap:
|
||||||
|
The LinuxTap object to add
|
||||||
|
"""
|
||||||
|
logger.info('adding Linux TAP interface: %s'
|
||||||
|
% linux_tap.name)
|
||||||
|
data = self._add_common(linux_tap)
|
||||||
|
data += "TYPE=Tap\n"
|
||||||
|
self.interface_data[linux_tap.name] = data
|
||||||
|
|
||||||
def generate_ivs_config(self, ivs_uplinks, ivs_interfaces):
|
def generate_ivs_config(self, ivs_uplinks, ivs_interfaces):
|
||||||
"""Generate configuration content for ivs."""
|
"""Generate configuration content for ivs."""
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,8 @@ def object_from_json(json):
|
||||||
return SriovPF.from_json(json)
|
return SriovPF.from_json(json)
|
||||||
elif obj_type == "sriov_vf":
|
elif obj_type == "sriov_vf":
|
||||||
return SriovVF.from_json(json)
|
return SriovVF.from_json(json)
|
||||||
|
elif obj_type == "linux_tap":
|
||||||
|
return LinuxTap.from_json(json)
|
||||||
|
|
||||||
|
|
||||||
def _get_required_field(json, name, object_name, datatype=None):
|
def _get_required_field(json, name, object_name, datatype=None):
|
||||||
|
@ -1848,3 +1850,37 @@ class ContrailVrouterDpdk(_BaseOpts):
|
||||||
bond_mode=bond_mode,
|
bond_mode=bond_mode,
|
||||||
bond_policy=bond_policy, driver=driver,
|
bond_policy=bond_policy, driver=driver,
|
||||||
cpu_list=cpu_list, vlan_id=vlan_id)
|
cpu_list=cpu_list, vlan_id=vlan_id)
|
||||||
|
|
||||||
|
|
||||||
|
class LinuxTap(_BaseOpts):
|
||||||
|
"""Base class for Linux tap Interface.
|
||||||
|
|
||||||
|
TAP, namely network TAP, simulates a link layer device and operates in
|
||||||
|
layer 2 carrying Ethernet frames.
|
||||||
|
A user space program may also pass packets into a TAP device. In this
|
||||||
|
case the TAP device delivers (or "injects") these packets to the
|
||||||
|
operating-system network stack thus emulating their reception from an
|
||||||
|
external source.
|
||||||
|
"""
|
||||||
|
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
|
||||||
|
routes=None, rules=None, mtu=None, primary=False,
|
||||||
|
nic_mapping=None, persist_mapping=False, defroute=True,
|
||||||
|
dhclient_args=None, dns_servers=None, nm_controlled=False,
|
||||||
|
onboot=True, domain=None, members=None):
|
||||||
|
super(LinuxTap, self).__init__(name, use_dhcp, use_dhcpv6,
|
||||||
|
addresses, routes, rules, mtu,
|
||||||
|
primary, nic_mapping,
|
||||||
|
persist_mapping, defroute,
|
||||||
|
dhclient_args, dns_servers,
|
||||||
|
nm_controlled, onboot, domain)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(json):
|
||||||
|
name = _get_required_field(json, 'name', 'LinuxTap')
|
||||||
|
|
||||||
|
(_use_dhcp, _use_dhcpv6, _addresses, _routes, _rules, _mtu, _primary,
|
||||||
|
nic_mapping, persist_mapping, _defroute, _dhclient_args, _dns_servers,
|
||||||
|
_nm_controlled, _onboot,
|
||||||
|
_domain) = opts = _BaseOpts.base_opts_from_json(json)
|
||||||
|
|
||||||
|
return LinuxTap(name, *opts)
|
||||||
|
|
|
@ -1077,6 +1077,43 @@ definitions:
|
||||||
- members
|
- members
|
||||||
additionalProperties: False
|
additionalProperties: False
|
||||||
|
|
||||||
|
linux_tap:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
enum: ["linux_tap"]
|
||||||
|
name:
|
||||||
|
$ref: "#/definitions/string_or_param"
|
||||||
|
# common options:
|
||||||
|
use_dhcp:
|
||||||
|
$ref: "#/definitions/bool_or_param"
|
||||||
|
use_dhcpv6:
|
||||||
|
$ref: "#/definitions/bool_or_param"
|
||||||
|
addresses:
|
||||||
|
$ref: "#/definitions/list_of_address"
|
||||||
|
routes:
|
||||||
|
$ref: "#/definitions/list_of_route"
|
||||||
|
rules:
|
||||||
|
$ref: "#/definitions/list_of_rule"
|
||||||
|
mtu:
|
||||||
|
$ref: "#/definitions/int_or_param"
|
||||||
|
nic_mapping:
|
||||||
|
$ref: "#/definitions/nic_mapping"
|
||||||
|
persist_mapping:
|
||||||
|
$ref: "#/definitions/bool_or_param"
|
||||||
|
defroute:
|
||||||
|
$ref: "#/definitions/bool_or_param"
|
||||||
|
dhclient_args:
|
||||||
|
$ref: "#/definitions/string_or_param"
|
||||||
|
dns_servers:
|
||||||
|
$ref: "#/definitions/list_of_ip_address_string_or_param"
|
||||||
|
nm_controlled:
|
||||||
|
$ref: "#/definitions/bool_or_param"
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
- name
|
||||||
|
additionalProperties: False
|
||||||
|
|
||||||
linux_bridge:
|
linux_bridge:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1533,4 +1570,5 @@ items:
|
||||||
- $ref: "#/definitions/vpp_bond"
|
- $ref: "#/definitions/vpp_bond"
|
||||||
- $ref: "#/definitions/contrail_vrouter"
|
- $ref: "#/definitions/contrail_vrouter"
|
||||||
- $ref: "#/definitions/contrail_vrouter_dpdk"
|
- $ref: "#/definitions/contrail_vrouter_dpdk"
|
||||||
|
- $ref: "#/definitions/linux_tap"
|
||||||
minItems: 1
|
minItems: 1
|
||||||
|
|
|
@ -603,6 +603,15 @@ DRIVER=uio_pci_generic
|
||||||
CPU_LIST=2,3
|
CPU_LIST=2,3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_LINUX_TAP_IFACE = """# This file is autogenerated by os-net-config
|
||||||
|
DEVICE=tap0
|
||||||
|
ONBOOT=yes
|
||||||
|
HOTPLUG=no
|
||||||
|
NM_CONTROLLED=no
|
||||||
|
PEERDNS=no
|
||||||
|
BOOTPROTO=none
|
||||||
|
TYPE=Tap
|
||||||
|
"""
|
||||||
_SRIOV_PF_IFCFG = """# This file is autogenerated by os-net-config
|
_SRIOV_PF_IFCFG = """# This file is autogenerated by os-net-config
|
||||||
DEVICE=enp3s0f0
|
DEVICE=enp3s0f0
|
||||||
ONBOOT=yes
|
ONBOOT=yes
|
||||||
|
@ -1142,6 +1151,13 @@ class TestIfcfgNetConfig(base.TestCase):
|
||||||
self.provider.interface_data['vhost0'])
|
self.provider.interface_data['vhost0'])
|
||||||
self.assertEqual('', self.get_route_config('vhost0'))
|
self.assertEqual('', self.get_route_config('vhost0'))
|
||||||
|
|
||||||
|
def test_add_linux_tap(self):
|
||||||
|
tap = objects.LinuxTap('tap0', nm_controlled=False)
|
||||||
|
self.provider.add_linux_tap(tap)
|
||||||
|
self.assertEqual(
|
||||||
|
_LINUX_TAP_IFACE,
|
||||||
|
self.provider.interface_data['tap0'])
|
||||||
|
|
||||||
def test_add_vlan(self):
|
def test_add_vlan(self):
|
||||||
vlan = objects.Vlan('em1', 5)
|
vlan = objects.Vlan('em1', 5)
|
||||||
self.provider.add_vlan(vlan)
|
self.provider.add_vlan(vlan)
|
||||||
|
|
|
@ -2443,3 +2443,18 @@ class TestOvsRequiredObjects(base.TestCase):
|
||||||
expected = 'OvsDpdkPort cannot be created as OpenvSwitch is not ' \
|
expected = 'OvsDpdkPort cannot be created as OpenvSwitch is not ' \
|
||||||
'installed.'
|
'installed.'
|
||||||
self.assertIn(expected, six.text_type(err))
|
self.assertIn(expected, six.text_type(err))
|
||||||
|
|
||||||
|
|
||||||
|
class TestLinuxTap(base.TestCase):
|
||||||
|
|
||||||
|
def test_linux_tap_from_json(self):
|
||||||
|
data = """{
|
||||||
|
"type": "linux_tap",
|
||||||
|
"name": "tap0",
|
||||||
|
"nm_controlled": false
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
linux_tap = objects.object_from_json(json.loads(data))
|
||||||
|
self.assertEqual("tap0", linux_tap.name)
|
||||||
|
self.assertEqual(False, linux_tap.nm_controlled)
|
||||||
|
|
Loading…
Reference in New Issue