diff options
Diffstat (limited to 'vicn/resource/vpp/interface.py')
-rw-r--r-- | vicn/resource/vpp/interface.py | 103 |
1 files changed, 91 insertions, 12 deletions
diff --git a/vicn/resource/vpp/interface.py b/vicn/resource/vpp/interface.py index 5f8f5018..d0538661 100644 --- a/vicn/resource/vpp/interface.py +++ b/vicn/resource/vpp/interface.py @@ -16,17 +16,63 @@ # limitations under the License. # +import pyparsing as pp + +from netmodel.model.key import Key from netmodel.model.type import Integer, String, Bool +from netmodel.model.type import Inet4Address, Inet6Address from vicn.core.resource import Resource from vicn.core.attribute import Attribute, Multiplicity from vicn.core.exception import ResourceNotFound from vicn.core.task import inline_task, BashTask, task +from vicn.core.task import inherit_parent from vicn.core.task import EmptyTask from vicn.resource.interface import Interface from vicn.resource.linux.net_device import NonTapBaseNetDevice from vicn.resource.vpp.vpp import VPP -from vicn.resource.vpp.vpp_commands import CMD_VPP_CREATE_IFACE +from vicn.resource.vpp.vpp_commands import CMD_VPP_CREATE_IFACE, CMD_VPP_CREATE_MEMIFACE from vicn.resource.vpp.vpp_commands import CMD_VPP_SET_IP, CMD_VPP_SET_UP +from vicn.resource.vpp.memif_device import MemifDevice + +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_file = pp.CaselessKeyword('file') + kw_listener = pp.CaselessKeyword('listener') + kw_connfd = pp.CaselessKeyword('conn-fd') + kw_intfd = pp.CaselessKeyword('int-fd') + kw_ringsize = pp.CaselessKeyword('ring-size') + kw_numc2srings = pp.CaselessKeyword('num-c2s-rings') + kw_nums2crings = pp.CaselessKeyword('num-s2c-rings') + kw_buffersize = pp.CaselessKeyword('buffer_size') + + 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') + + multiple = pp.OneOrMore(pp.Group(single)) + + results = multiple.parseString(rv.stdout) + + for interface in results: + if interface['path'] == vppinterface.parent.path_unix_socket + vppinterface.parent.socket_name: + vppinterface.device_name = interface['interface'] + vppinterface.parent.device_name = interface['interface'] + + return vppinterface.device_name + class VPPInterface(Resource): """ @@ -39,18 +85,21 @@ class VPPInterface(Resource): description = 'Forwarder to which this interface belong to', mandatory = True, multiplicity = Multiplicity.ManyToOne, - key = True, reverse_name = 'interfaces') parent = Attribute(Interface, description = 'parent', mandatory = True, reverse_name = 'vppinterface') - ip4_address = Attribute(String) - ip6_address = Attribute(String) - prefix_len = Attribute(Integer, default = 31) + ip4_address = Attribute(Inet4Address) + ip6_address = Attribute(Inet6Address) up = Attribute(Bool, description = 'Interface up/down status') monitored = Attribute(Bool, default = True) device_name = Attribute(String) + __key__ = Key(vpp, Resource.name) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + #-------------------------------------------------------------------------- # Resource lifecycle #-------------------------------------------------------------------------- @@ -61,10 +110,12 @@ class VPPInterface(Resource): """ return ['CentralIP'] + @inherit_parent @inline_task def __get__(self): raise ResourceNotFound + @inherit_parent def __create__(self): # We must control what is the type of the parent netDevice (currently # supported only veths, physical nics are coming) @@ -73,15 +124,27 @@ class VPPInterface(Resource): # We must let the routing algorithm know that the parent interface # belongs to vpp self.parent.has_vpp_child = True - - self.ip4_address = self.parent.ip4_address - self.ip6_address = self.parent.ip6_address self.up = True - if isinstance(self.parent,NonTapBaseNetDevice): + if isinstance(self.parent, MemifDevice): + #TODO: add output parsing to get the interface name + create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_MEMIFACE, { + 'key': hex(self.parent.key), + 'vpp_interface': self, + 'master_slave': 'master' if self.parent.master else 'slave'}, + lock = self.vpp.vppctl_lock) + fill_name = BashTask(self.vpp.node, GREP_MEMIF_INFO, + parse = (lambda x, y=self : parse_memif(x, y)), + lock = self.vpp.vppctl_lock) + + create_task = create_task > fill_name + + elif isinstance(self.parent,NonTapBaseNetDevice): # 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.device_name = 'host-' + self.parent.device_name create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_IFACE, @@ -94,6 +157,8 @@ 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 @@ -112,13 +177,27 @@ class VPPInterface(Resource): def _set_ip4_address(self): if self.ip4_address: - return BashTask(self.vpp.node, CMD_VPP_SET_IP, {'netdevice': self}, + return BashTask(self.vpp.node, CMD_VPP_SET_IP, { + 'device_name': self.device_name, + 'ip_address': str(self.ip4_address), + 'prefix_len': self.ip4_address.prefix_len}, lock = self.vpp.vppctl_lock) - def _set_up(self): - return BashTask(self.vpp.node, CMD_VPP_SET_UP, {'netdevice': self}, + def _set_ip6_address(self): + if self.ip6_address: + return BashTask(self.vpp.node, CMD_VPP_SET_IP, { + 'device_name': self.device_name, + 'ip_address': str(self.ip6_address), + 'prefix_len': self.ip6_address.prefix_len}, lock = self.vpp.vppctl_lock) + def _set_up(self): + state = 'up' if self.up else 'down' + return BashTask(self.vpp.node, CMD_VPP_SET_UP, { + 'netdevice': self, + 'state': state}, + lock = self.vpp.vppctl_lock) + @task def _get_up(self): return {'up' : False} |