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:
shrike 2020-12-07 14:51:33 +00:00
parent 1a1b1b710f
commit da7614bc48
8 changed files with 142 additions and 0 deletions

View File

@ -0,0 +1,8 @@
{ "network_config": [
{
"type": "linux_tap",
"name": "tap0",
"use_dhcp": true
}
]
}

View File

@ -0,0 +1,6 @@
network_config:
-
type: linux_tap
name: tap0
use_dhcp: true

View File

@ -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.

View File

@ -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."""

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)