diff options
author | Marcel Enguehard <mengueha+fdio@cisco.com> | 2017-10-09 08:44:59 +0200 |
---|---|---|
committer | Marcel Enguehard <mengueha+fdio@cisco.com> | 2017-10-09 08:55:46 +0200 |
commit | 5f8867a3454164ad20ae427dc9d2c7d65ea00a90 (patch) | |
tree | c8ff40fb147a76af2baa77790ba8a6ac968e51b4 /vicn | |
parent | af2dd545d04cfca7e7ec066035abf78c3d541915 (diff) |
Several fixes related to async_set, ip addressing, and memif interfaces for VPP
Change-Id: I26b7928751f41ea66ba47bb1becac33cf5195915
Signed-off-by: Marcel Enguehard <mengueha+fdio@cisco.com>
Diffstat (limited to 'vicn')
-rw-r--r-- | vicn/core/resource.py | 9 | ||||
-rw-r--r-- | vicn/core/resource_mgr.py | 12 | ||||
-rw-r--r-- | vicn/resource/icn/central.py | 6 | ||||
-rw-r--r-- | vicn/resource/icn/cicn.py | 7 | ||||
-rw-r--r-- | vicn/resource/ip/central.py | 4 | ||||
-rw-r--r-- | vicn/resource/lxd/lxc_container.py | 1 | ||||
-rw-r--r-- | vicn/resource/vpp/interface.py | 74 | ||||
-rw-r--r-- | vicn/resource/vpp/memif_link.py | 2 | ||||
-rw-r--r-- | vicn/resource/vpp/scripts.py | 2 | ||||
-rw-r--r-- | vicn/resource/vpp/vpp.py | 5 | ||||
-rw-r--r-- | vicn/resource/vpp/vpp_commands.py | 3 |
11 files changed, 91 insertions, 34 deletions
diff --git a/vicn/core/resource.py b/vicn/core/resource.py index 878a8108..a80e09ed 100644 --- a/vicn/core/resource.py +++ b/vicn/core/resource.py @@ -467,7 +467,7 @@ class BaseResource(Object): #, ABC, metaclass=ResourceMetaclass): self._state.manager.attribute_set(self, attribute_name, value) async def async_set(self, attribute_name, value, current=False, - set_reverse=True, blocking=None): + set_reverse=True): """ Example: - setting the ip address on a node's interface @@ -478,7 +478,12 @@ class BaseResource(Object): #, ABC, metaclass=ResourceMetaclass): """ value = self._set(attribute_name, value, current=current, set_reverse=set_reverse) - await self._state.manager.attribute_set_async(self, attribute_name, value) + if self.is_local_attribute(attribute_name) or current: + if value is None: + attribute = self.get_attribute(attribute_name) + vars(self)[attribute_name] = value + else: + await self._state.manager.attribute_async_set(self, attribute_name, value) def set_many(self, attribute_dict, current=False): if not attribute_dict: diff --git a/vicn/core/resource_mgr.py b/vicn/core/resource_mgr.py index 8db7f04d..b4aa6bb7 100644 --- a/vicn/core/resource_mgr.py +++ b/vicn/core/resource_mgr.py @@ -587,7 +587,7 @@ class ResourceManager(metaclass=Singleton): await self.wait_attr_init(resource, attribute) return resource.get(attribute) - async def _attribute_set(self, resource, attribute_name, value): + async def _attribute_set(self, resource, attribute_name, value, blocking=False): with await resource._state.write_lock: attr_state = resource._state.attr_state[attribute_name] @@ -632,8 +632,8 @@ class ResourceManager(metaclass=Singleton): raise RuntimeError("Resource cannot be in state".format( resource_state)) -# if blocking: -# await self.wait_attr_clean(resource, attribute_name) + if blocking: + await self.wait_attr_clean(resource, attribute_name) def attribute_set(self, resource, attribute_name, value): # Add the current operation to the pending list @@ -643,15 +643,13 @@ class ResourceManager(metaclass=Singleton): value) asyncio.ensure_future(self._attribute_set(resource, attribute_name, value)) - async def attribute_set_async(self, resource, attribute_name, value): + async def attribute_async_set(self, resource, attribute_name, value): # Add the current operation to the pending list # NOTE: collections are unordered and can be updated concurrently #self._attribute_set_pending_value(resource, attribute_name) resource._state.dirty[attribute_name].trigger(Operations.SET, value) - await self._attribute_set(resource, attribute_name, value) - - + await self._attribute_set(resource, attribute_name, value, blocking=True) #--------------------------------------------------------------------------- # Resource dependency management diff --git a/vicn/resource/icn/central.py b/vicn/resource/icn/central.py index aa8ea357..fd272bf6 100644 --- a/vicn/resource/icn/central.py +++ b/vicn/resource/icn/central.py @@ -81,6 +81,8 @@ class ICNFaces(Resource): def __delete__(self): raise NotImplementedError + def __after__(self): + return ("VPPInterface",) #-------------------------------------------------------------------------- # Internal methods #-------------------------------------------------------------------------- @@ -102,7 +104,11 @@ class ICNFaces(Resource): map_ = data['map_node_interface'] src = self._state.manager.by_uuid(map_[src_node_uuid]) + if src.has_vpp_child: + src = src.vppinterface dst = self._state.manager.by_uuid(map_[dst_node_uuid]) + if dst.has_vpp_child: + dst = dst.vppinterface log.debug('{} -> {} ({} -> {})'.format(src_node_uuid, dst_node_uuid, src.device_name, dst.device_name)) diff --git a/vicn/resource/icn/cicn.py b/vicn/resource/icn/cicn.py index 8ab36ec9..597692c8 100644 --- a/vicn/resource/icn/cicn.py +++ b/vicn/resource/icn/cicn.py @@ -71,7 +71,7 @@ class CICNForwarder(Forwarder): @inherit_parent def __get__(self): def parse(rv): - if rv.return_value > 0 or 'cicn: not enabled' in rv.stdout: + if rv.return_value > 0 or 'cicn: not enabled' in rv.stdout or "Forwarder : disabled" in rv.stdout: raise ResourceNotFound return BashTask(self.node, CMD_VPP_CICN_GET, lock = self.node.vpp.vppctl_lock, parse=parse) @@ -134,6 +134,9 @@ class CICNForwarder(Forwarder): def _get_cache_size(self): def parse(rv): - return int(rv.stdout) + if not rv.stdout: + return 0 + else: + return int(rv.stdout) return BashTask(self.node, CMD_VPP_CICN_GET_CACHE_SIZE, parse=parse, lock = self.node.vpp.vppctl_lock) diff --git a/vicn/resource/ip/central.py b/vicn/resource/ip/central.py index 0c397728..75b590e1 100644 --- a/vicn/resource/ip/central.py +++ b/vicn/resource/ip/central.py @@ -82,7 +82,8 @@ class IPRoutes(Resource): node_uuid = interface.node._state.uuid if not node_uuid in origins: origins[node_uuid] = list() - origins[node_uuid].append(interface.ip4_address.canonical_prefix()) + if interface.ip4_address: + origins[node_uuid].append(interface.ip4_address.canonical_prefix()) if interface.ip6_address: origins[node_uuid].append(interface.ip6_address.canonical_prefix()) return origins @@ -113,7 +114,6 @@ class IPRoutes(Resource): # Avoid duplicate routes due to multiple paths in the network if not src_node in ip_routes: ip_routes[src_node] = set() - #XXX Untested for VPP #When you set up an IP address ip/prefix_len (ip addr add), you already create a route #towards ip/prefix_len for interface in src_node.interfaces: diff --git a/vicn/resource/lxd/lxc_container.py b/vicn/resource/lxd/lxc_container.py index a9f8483d..3222cc8a 100644 --- a/vicn/resource/lxd/lxc_container.py +++ b/vicn/resource/lxd/lxc_container.py @@ -19,6 +19,7 @@ import logging import shlex import time +import requests # Suppress logging from pylxd dependency on ws4py # (this needs to be included before pylxd) diff --git a/vicn/resource/vpp/interface.py b/vicn/resource/vpp/interface.py index 9dbd7fc3..f845e2df 100644 --- a/vicn/resource/vpp/interface.py +++ b/vicn/resource/vpp/interface.py @@ -34,11 +34,18 @@ from vicn.resource.vpp.vpp_commands import CMD_VPP_CREATE_IFACE, CMD_VPP_CREATE_ from vicn.resource.vpp.vpp_commands import CMD_VPP_SET_IP, CMD_VPP_SET_UP from vicn.resource.vpp.memif_device import MemifDevice +VPP_vers = (17, 7) + GREP_MEMIF_INFO = 'vppctl_wrapper show memif | grep interface --no-group-separator -A 1' def parse_memif(rv, vppinterface): kw_interface = pp.CaselessKeyword('interface') kw_key = pp.CaselessKeyword('key') + kw_remote_name = pp.CaselessKeyword('remote-name') + kw_remote_if = pp.CaselessKeyword('remote-interface') + kw_id = pp.CaselessKeyword('id') + kw_mode = pp.CaselessKeyword('mode') + kw_ethernet = pp.CaselessKeyword('ethernet') kw_file = pp.CaselessKeyword('file') kw_listener = pp.CaselessKeyword('listener') kw_connfd = pp.CaselessKeyword('conn-fd') @@ -51,20 +58,41 @@ def parse_memif(rv, vppinterface): r_path = ' *(/[a-zA-Z0-9_\-]*)*\.[a-zA-Z0-9_\-]*' r_id = ' *-+[0-9]*' - single = kw_interface.suppress() + pp.Word(pp.alphanums).setResultsName('interface') + \ - kw_key.suppress() + pp.Word(pp.alphanums).setResultsName('key') + \ - kw_file.suppress() + pp.Regex(r_path).setResultsName('path') # + \ - # kw_listener.suppress() + pp.Word(pp.alphanums).setResultsName('listener') + \ - # kw_connfd.suppress() + pp.Regex(r_id).setResultsName('conn-fd') + \ - # kw_intfd.suppress() + pp.Regex(r_id).setResultsName('int-fd') + \ - # kw_ringsize.suppress() + pp.Word(pp.nums).setResultsName('ring-size') + \ - # kw_numc2srings.suppress() + pp.Word(pp.nums).setResultsName('num-c2s-rings') + \ - # kw_nums2crings.suppress() + pp.Word(pp.nums).setResultsName('num-s2c-rings') + \ - # kw_buffersize.suppress() + pp.Word(pp.nums).setResultsName('buffer-size') + r_remote_name = '"[A-Z]+ [0-9\.]+-[a-z]+"' + r_remote_if = '"[a-zA-Z0-9_\-]+"' + + if VPP_vers >= (17, 7): + single = kw_interface.suppress() + pp.Word(pp.alphanums).setResultsName('interface') + \ + pp.Optional(kw_remote_name.suppress() + pp.Regex(r_remote_name).setResultsName('remote_name') + \ + kw_remote_if.suppress() + pp.Regex(r_remote_if).setResultsName('remote_if')) + \ + kw_id.suppress() + pp.Word(pp.alphanums).setResultsName('key') + \ + kw_mode.suppress() + kw_ethernet.suppress() + \ + kw_file.suppress() + pp.Regex(r_path).setResultsName('path') # + \ + # kw_listener.suppress() + pp.Word(pp.alphanums).setResultsName('listener') + \ + # kw_connfd.suppress() + pp.Regex(r_id).setResultsName('conn-fd') + \ + # kw_intfd.suppress() + pp.Regex(r_id).setResultsName('int-fd') + \ + # kw_ringsize.suppress() + pp.Word(pp.nums).setResultsName('ring-size') + \ + # kw_numc2srings.suppress() + pp.Word(pp.nums).setResultsName('num-c2s-rings') + \ + # kw_nums2crings.suppress() + pp.Word(pp.nums).setResultsName('num-s2c-rings') + \ + # kw_buffersize.suppress() + pp.Word(pp.nums).setResultsName('buffer-size') + else: + single = kw_interface.suppress() + pp.Word(pp.alphanums).setResultsName('interface') + \ + kw_key.suppress() + pp.Word(pp.alphanums).setResultsName('key') + \ + kw_file.suppress() + pp.Regex(r_path).setResultsName('path') # + \ + # kw_listener.suppress() + pp.Word(pp.alphanums).setResultsName('listener') + \ + # kw_connfd.suppress() + pp.Regex(r_id).setResultsName('conn-fd') + \ + # kw_intfd.suppress() + pp.Regex(r_id).setResultsName('int-fd') + \ + # kw_ringsize.suppress() + pp.Word(pp.nums).setResultsName('ring-size') + \ + # kw_numc2srings.suppress() + pp.Word(pp.nums).setResultsName('num-c2s-rings') + \ + # kw_nums2crings.suppress() + pp.Word(pp.nums).setResultsName('num-s2c-rings') + \ + # kw_buffersize.suppress() + pp.Word(pp.nums).setResultsName('buffer-size') multiple = pp.OneOrMore(pp.Group(single)) - results = multiple.parseString(rv.stdout) + try: + results = multiple.parseString(rv.stdout) + except Exception as e: + import pdb; pdb.set_trace() for interface in results: if interface['path'] == vppinterface.parent.path_unix_socket + vppinterface.parent.socket_name: @@ -108,7 +136,7 @@ class VPPInterface(Resource): """ We need CentralIP to get the parent interface IP address """ - return ['CentralIP'] + return ['CentralIP', 'IpAssignment'] @inherit_parent @inline_task @@ -126,9 +154,23 @@ class VPPInterface(Resource): self.parent.has_vpp_child = True self.up = True + self.ip4_address = self.parent.ip4_address + self.ip6_address = self.parent.ip6_address + if isinstance(self.parent, MemifDevice): + self.device_name = self.parent.device_name + #TODO: add output parsing to get the interface name - create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_MEMIFACE, { + if VPP_vers >= (17, 7): + create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_MEMIFACE, { + 'key_label': 'id', + 'key': self.parent.key, + 'vpp_interface': self, + 'master_slave': 'master' if self.parent.master else 'slave'}, + lock = self.vpp.vppctl_lock) + else: + create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_MEMIFACE, { + 'key_label': 'key', 'key': hex(self.parent.key), 'vpp_interface': self, 'master_slave': 'master' if self.parent.master else 'slave'}, @@ -143,8 +185,8 @@ class VPPInterface(Resource): # Remove ip address in the parent device, it must only be set in # the vpp interface otherwise vpp and the linux kernel will reply # to non-icn request (e.g., ARP replies, port ureachable etc) - self.ip4_address = self.parent.ip4_address - self.ip6_address = self.parent.ip6_address + self.parent.ip4_address = None + self.parent.ip6_address = None self.device_name = 'host-' + self.parent.device_name create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_IFACE, @@ -155,8 +197,6 @@ class VPPInterface(Resource): self.parent.remote.set('offload', False) elif self.parent.get_type() == 'dpdkdevice': - self.ip4_address = self.parent.ip4_address - self.ip6_address = self.parent.ip6_address self.device_name = self.parent.device_name else : # Currently assume naively that everything else will be a physical diff --git a/vicn/resource/vpp/memif_link.py b/vicn/resource/vpp/memif_link.py index 62de03c6..25cfeea3 100644 --- a/vicn/resource/vpp/memif_link.py +++ b/vicn/resource/vpp/memif_link.py @@ -90,7 +90,7 @@ class MemifLink(Channel): foldername = SHARED_FOLDER_PATH.format(self.src_node.name + '-' + self.dst_node.name), permission = 777) - self.key = random.randint(0, 2**64) + self.key = random.randint(0, 2**31) self._src = MemifDevice(node = self.src_node, channel = self, diff --git a/vicn/resource/vpp/scripts.py b/vicn/resource/vpp/scripts.py index 06da7404..b467df6c 100644 --- a/vicn/resource/vpp/scripts.py +++ b/vicn/resource/vpp/scripts.py @@ -282,7 +282,7 @@ api-segment { ''' APPARMOR_VPP_PROFILE = ''' -lxc.aa_profile = lxc-dpdk +lxc.apparmor.profile = lxc-dpdk lxc.mount.entry = hugetlbfs dev/hugepages hugetlbfs rw,relatime,create=dir 0 0 lxc.mount.auto = sys:rw''' diff --git a/vicn/resource/vpp/vpp.py b/vicn/resource/vpp/vpp.py index 9d4f7068..a185c039 100644 --- a/vicn/resource/vpp/vpp.py +++ b/vicn/resource/vpp/vpp.py @@ -147,7 +147,10 @@ class VPP(LinuxApplication): if numa in socket_mem: socket_mem_str = socket_mem_str + str(socket_mem[numa]) else: - socket_mem_str = socket_mem_str + '0' + if None in socket_mem: #No numa nodes on machine but DpdkDevice has socket mem + socket_mem_str = socket_mem_str+str(socket_mem[None]) + else: + socket_mem_str = socket_mem_str + '0' if numa < numa_mgr.get_number_of_numa()-1: socket_mem_str = socket_mem_str + ',' diff --git a/vicn/resource/vpp/vpp_commands.py b/vicn/resource/vpp/vpp_commands.py index acc89640..e0b71517 100644 --- a/vicn/resource/vpp/vpp_commands.py +++ b/vicn/resource/vpp/vpp_commands.py @@ -6,6 +6,7 @@ CMD_VPP_DISABLE = 'systemctl disable vpp.service' # 'sleep 1' ensures that VPP has enough time to start CMD_VPP_START = ''' flock /tmp/vppctl.lock -c "systemctl start vpp" +sleep 2 ''' CMD_VPP_STOP = ''' flock /tmp/vppctl.lock -c "systemctl stop vpp" @@ -25,7 +26,7 @@ vppctl_wrapper set interface state {vpp_interface.device_name} up # generated by VPP, preventing any reboot of VPP and recreation of commands CMD_VPP_CREATE_MEMIFACE = ''' # Create vpp interface from shared_memory -vppctl_wrapper create memif key {key} socket {vpp_interface.parent.path_unix_socket}{vpp_interface.parent.socket_name} hw-addr {vpp_interface.parent.mac_address} {master_slave} +vppctl_wrapper create memif {key_label} {key} socket {vpp_interface.parent.path_unix_socket}{vpp_interface.parent.socket_name} hw-addr {vpp_interface.parent.mac_address} {master_slave} ''' CMD_VPP_SET_IP = 'vppctl_wrapper set int ip address {device_name} {ip_address}/{prefix_len}' CMD_VPP_SET_UP = 'vppctl_wrapper set int state {netdevice.device_name} {state}' |