Example #1
0
 def _delete_all_flows(self):
     """ Delete all flows on the device """
     try:
         self.flows_proxy.update('/', Flows(items=[]))
         self.groups_proxy.update('/', FlowGroups(items=[]))
     except Exception, e:
         self.exception('flow-delete-exception', e=e)
Example #2
0
    def group_delete(self, group_mod):
        assert isinstance(group_mod, ofp.ofp_group_mod)

        groups = OrderedDict((g.desc.group_id, g)
                             for g in self.groups_proxy.get('/').items)
        groups_changed = False
        flows_changed = False

        group_id = group_mod.group_id
        if group_id == ofp.OFPG_ALL:
            # TODO we must delete all flows that point to this group and
            # signal controller as requested by flow's flag
            groups = OrderedDict()
            groups_changed = True
            self.log.debug('all-groups-deleted')

        else:
            if group_id not in groups:
                # per openflow spec, this is not an error
                pass

            else:
                flows = list(self.flows_proxy.get('/').items)
                flows_changed, flows = self.flows_delete_by_group_id(
                    flows, group_id)
                del groups[group_id]
                groups_changed = True
                self.log.debug('group-deleted', group_id=group_id)

        if groups_changed:
            self.groups_proxy.update('/', FlowGroups(items=groups.values()))
        if flows_changed:
            self.flows_proxy.update('/', Flows(items=flows))
    def update_children_flows(self, device_rules_map):

        for device_id, (flows, groups) in device_rules_map.iteritems():
            if device_id != self.device_id:
                self.root_proxy.update('/devices/{}/flows'.format(device_id),
                                       Flows(items=flows.values()))
                self.root_proxy.update('/devices/{}/flow_groups'.format(
                    device_id), FlowGroups(items=groups.values()))
Example #4
0
    def ListDeviceFlowGroups(self, request, context):
        log.info('grpc-request', request=request)

        if '/' in request.id:
            context.set_details('Malformed device id \'{}\''.format(
                request.id))
            context.set_code(StatusCode.INVALID_ARGUMENT)
            return FlowGroups()

        try:
            groups = self.root.get('/devices/{}/flow_groups'.format(
                request.id))
            return groups
        except KeyError:
            context.set_details('Device \'{}\' not found'.format(request.id))
            context.set_code(StatusCode.NOT_FOUND)
            return FlowGroups()
Example #5
0
    def _flow_table_updated(self, flows):
        self.log.debug('flow-table-updated',
                       logical_device_id=self.logical_device_id,
                       flows=flows)

        if self._no_flow_changes_required:
            # Stats changes, no need to process further
            self.log.debug('flow-stats-update')
        else:

            groups = self.groups_proxy.get('/').items
            device_rules_map = self.decompose_rules(flows.items, groups)

            # TODO we have to evolve this into a policy-based, event based pattern
            # This is a raw implementation of the specific use-case with certain
            # built-in assumptions, and not yet device vendor specific. The policy-
            # based refinement will be introduced that later.

            # Temporary bypass for openolt

            if self.accepts_direct_logical_flows:
                #give the logical flows directly to the adapter
                self.log.debug('it is an direct logical flow bypass')
                if self.device_adapter_agent is None:
                    self.log.error('No device adapter agent',
                                   device_id=self.device_id,
                                   logical_device_id=self.logical_device_id)
                    return

                flows_to_add = []
                for f in flows.items:
                    if f.id in self._flows_ids_to_add:
                        flows_to_add.append(f)

                self.log.debug('flows to remove',
                               flows_to_remove=self._flows_to_remove,
                               flows_ids=self._flows_ids_to_remove)

                try:
                    self.device_adapter_agent.update_logical_flows(
                        self.device_id, flows_to_add, self._flows_to_remove,
                        groups, device_rules_map)
                except Exception as e:
                    self.log.error('logical flows bypass error',
                                   error=e,
                                   flows=flows)
            else:

                for device_id, (flows, groups) in device_rules_map.iteritems():

                    self.root_proxy.update(
                        '/devices/{}/flows'.format(device_id),
                        Flows(items=flows.values()))
                    self.root_proxy.update(
                        '/devices/{}/flow_groups'.format(device_id),
                        FlowGroups(items=groups.values()))
Example #6
0
    def test_add_group(self):
        group_mod = mk_multicast_group_mod(
            group_id=2,
            buckets=[
                ofp.ofp_bucket(actions=[pop_vlan(), output(1)]),
                ofp.ofp_bucket(actions=[pop_vlan(), output(2)]),
            ])
        self.lda.update_group_table(group_mod)

        expected_groups = FlowGroups(
            items=[group_entry_from_group_mod(group_mod)])
        self.assertEqual(self.groups, expected_groups)
Example #7
0
    def _group_table_updated(self, flow_groups):
        self.log.debug('group-table-updated',
                  logical_device_id=self.logical_device_id,
                  flow_groups=flow_groups)

        flows = self.flows_proxy.get('/').items
        device_flows_map = self.decompose_rules(flows, flow_groups.items)
        for device_id, (flows, groups) in device_flows_map.iteritems():
            self.root_proxy.update('/devices/{}/flows'.format(device_id),
                                   Flows(items=flows.values()))
            self.root_proxy.update('/devices/{}/flow_groups'.format(device_id),
                                   FlowGroups(items=groups.values()))
Example #8
0
    def _flow_table_updated(self, flows):
        self.log.debug('flow-table-updated',
                  logical_device_id=self.logical_device_id, flows=flows)

        # TODO we have to evolve this into a policy-based, event based pattern
        # This is a raw implementation of the specific use-case with certain
        # built-in assumptions, and not yet device vendor specific. The policy-
        # based refinement will be introduced that later.

        groups = self.groups_proxy.get('/').items
        device_rules_map = self.decompose_rules(flows.items, groups)
        for device_id, (flows, groups) in device_rules_map.iteritems():
            self.root_proxy.update('/devices/{}/flows'.format(device_id),
                                   Flows(items=flows.values()))
            self.root_proxy.update('/devices/{}/flow_groups'.format(device_id),
                                   FlowGroups(items=groups.values()))
Example #9
0
    def group_add(self, group_mod):
        assert isinstance(group_mod, ofp.ofp_group_mod)

        groups = OrderedDict((g.desc.group_id, g)
                             for g in self.groups_proxy.get('/').items)
        changed = False

        if group_mod.group_id in groups:
            self.signal_group_mod_error(ofp.OFPGMFC_GROUP_EXISTS, group_mod)
        else:
            group_entry = group_entry_from_group_mod(group_mod)
            groups[group_mod.group_id] = group_entry
            changed = True

        if changed:
            self.groups_proxy.update('/', FlowGroups(items=groups.values()))
Example #10
0
    def group_modify(self, group_mod):
        assert isinstance(group_mod, ofp.ofp_group_mod)

        groups = OrderedDict(
            (g.desc.group_id, g) for g in self.groups_proxy.get('/').items)
        changed = False

        if group_mod.group_id not in groups:
            self.signal_group_mod_error(ofp.OFPGMFC_INVALID_GROUP, group_mod)
        else:
            # replace existing group entry with new group definition
            group_entry = group_entry_from_group_mod(group_mod)
            groups[group_mod.group_id] = group_entry
            changed = True

        if changed:
            self.groups_proxy.update('/', FlowGroups(items=groups.values()))
Example #11
0
    def setUp(self):
        self.setup_mock_registry()

        self.flows = Flows(items=[])
        self.groups = FlowGroups(items=[])
        self.ld_ports = [
            LogicalPort(id='0',
                        device_id='olt',
                        device_port_no=0,
                        root_port=True,
                        ofp_port=ofp.ofp_port(port_no=0)),
            LogicalPort(id='1',
                        device_id='onu1',
                        device_port_no=0,
                        ofp_port=ofp.ofp_port(port_no=1)),
            LogicalPort(id='2',
                        device_id='onu2',
                        device_port_no=0,
                        ofp_port=ofp.ofp_port(port_no=2))
        ]

        self.devices = {
            'olt': Device(id='olt', root=True, parent_id='id'),
            'onu1': Device(id='onu1',
                           parent_id='olt',
                           parent_port_no=1,
                           vlan=101),
            'onu2': Device(id='onu2',
                           parent_id='olt',
                           parent_port_no=1,
                           vlan=102),
        }

        self.ports = {
            'olt': [
                Port(port_no=0, type=Port.ETHERNET_NNI, device_id='olt'),
                Port(port_no=1,
                     type=Port.PON_OLT,
                     device_id='olt',
                     peers=[
                         Port.PeerPort(device_id='onu1', port_no=1),
                         Port.PeerPort(device_id='onu2', port_no=1)
                     ])
            ],
            'onu1': [
                Port(port_no=0, type=Port.ETHERNET_UNI, device_id='onu1'),
                Port(port_no=1,
                     type=Port.PON_ONU,
                     device_id='onu1',
                     peers=[
                         Port.PeerPort(device_id='olt', port_no=1),
                     ])
            ],
            'onu2': [
                Port(port_no=0, type=Port.ETHERNET_UNI, device_id='onu2'),
                Port(port_no=1,
                     type=Port.PON_ONU,
                     device_id='onu2',
                     peers=[
                         Port.PeerPort(device_id='olt', port_no=1),
                     ])
            ],
        }

        self.device_flows = {'olt': Flows(), 'onu1': Flows(), 'onu2': Flows()}

        self.device_groups = {
            'olt': FlowGroups(),
            'onu1': FlowGroups(),
            'onu2': FlowGroups()
        }

        self.ld = LogicalDevice(id='id', root_device_id='olt')

        self.root_proxy = Mock()

        def get_devices(path):
            if path == '':
                return self.devices.values()
            if path.endswith('/ports'):
                return self.ports[path[:-len('/ports')]]
            elif path.find('/') == -1:
                return self.devices[path]
            else:
                raise Exception(
                    'Nothing to yield for path /devices/{}'.format(path))

        def update_devices(path, data):
            if path.endswith('/flows'):
                self.device_flows[path[:-len('/flows')]] = data
            elif path.endswith('/flow_groups'):
                self.device_groups[path[:-len('/flow_groups')]] = data
            else:
                raise NotImplementedError(
                    'not handling path /devices/{}'.format(path))

        self.root_proxy.get = lambda p: \
            get_devices(p[len('/devices/'):]) if p.startswith('/devices') \
                else None
        self.root_proxy.update = lambda p, d: \
            update_devices(p[len('/devices/'):], d) \
                if p.startswith('/devices') \
                else None
        self.ld_proxy = Mock()
        self.ld_proxy.get = lambda p: \
            self.ld_ports if p == '/ports' else (
                self.ld if p == '/' else None
            )

        self.flows_proxy = Mock()
        self.flows_proxy.get = lambda _: self.flows  # always '/' path

        def update_flows(_, flows):  # always '/' path
            self.flows = flows

        self.flows_proxy.update = update_flows

        self.groups_proxy = Mock()
        self.groups_proxy.get = lambda _: self.groups  # always '/' path

        def update_groups(_, groups):  # always '/' path
            self.groups = groups

        self.groups_proxy.update = update_groups

        self.core = Mock()
        self.core.get_proxy = lambda path: \
            self.root_proxy if path == '/' else (
                self.ld_proxy if path.endswith('id') else (
                    self.flows_proxy if path.endswith('flows') else
                    self.groups_proxy
                )
            )

        self.lda = LogicalDeviceAgent(self.core, self.ld)