Ejemplo n.º 1
0
    def init(self):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Validates the given ``ovsdb_addr`` and connects to OVS instance.

        If failed to connect to OVS instance or the given ``datapath_id`` does
        not match with the Datapath ID of the connected OVS instance, raises
        :py:mod:`os_ken.lib.ovs.bridge.OVSBridgeNotFound` exception.
        """
        if not valid_ovsdb_addr(self.ovsdb_addr):
            raise ValueError('Invalid OVSDB address: %s' % self.ovsdb_addr)
        if self.br_name is None:
            self.br_name = self._get_bridge_name()
Ejemplo n.º 2
0
    def get_controller(self):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Gets the configured OpenFlow controller address.

        This method is corresponding to the following ovs-vsctl command::

            $ ovs-vsctl get-controller <bridge>
        """
        command = ovs_vsctl.VSCtlCommand('get-controller', [self.br_name])
        self.run_command([command])
        result = command.result
        return result[0] if len(result) == 1 else result
Ejemplo n.º 3
0
    def add_db_attribute(self, table, record, column, value, key=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Adds ('key'=)'value' into 'column' in 'record' in 'table'.

        This method is corresponding to the following ovs-vsctl command::

            $ ovs-vsctl add TBL REC COL [KEY=]VALUE
        """
        if key is not None:
            value = '%s=%s' % (key, value)
        command = ovs_vsctl.VSCtlCommand('add', (table, record, column, value))
        self.run_command([command])
Ejemplo n.º 4
0
    def _set_meter(self, rest, waiters):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        cmd = self.dp.ofproto.OFPMC_ADD
        try:
            self.ofctl.mod_meter_entry(self.dp, rest, cmd)
        except:
            raise ValueError('Invalid meter parameter.')

        msg = {
            'result': 'success',
            'details': 'Meter added. : Meter ID=%s' % rest[REST_METER_ID]
        }
        return msg
Ejemplo n.º 5
0
    def set_queue(self, rest, vlan_id):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        if self.ovs_bridge is None:
            msg = {'result': 'failure', 'details': 'ovs_bridge is not exists'}
            return REST_COMMAND_RESULT, msg

        port_name = rest.get(REST_PORT_NAME, None)
        vif_ports = self.ovs_bridge.get_port_name_list()

        if port_name is not None:
            if port_name not in vif_ports:
                raise ValueError('%s port is not exists' % port_name)
            vif_ports = [port_name]

        queue_list = {}
        queue_type = rest.get(REST_QUEUE_TYPE, 'linux-htb')
        parent_max_rate = rest.get(REST_QUEUE_MAX_RATE, None)
        queues = rest.get(REST_QUEUES, [])
        queue_id = 0
        queue_config = []
        for queue in queues:
            max_rate = queue.get(REST_QUEUE_MAX_RATE, None)
            min_rate = queue.get(REST_QUEUE_MIN_RATE, None)
            if max_rate is None and min_rate is None:
                raise ValueError('Required to specify max_rate or min_rate')
            config = {}
            if max_rate is not None:
                config['max-rate'] = max_rate
            if min_rate is not None:
                config['min-rate'] = min_rate
            if len(config):
                queue_config.append(config)
            queue_list[queue_id] = {'config': config}
            queue_id += 1

        for port_name in vif_ports:
            try:
                self.ovs_bridge.set_qos(port_name,
                                        type=queue_type,
                                        max_rate=parent_max_rate,
                                        queues=queue_config)
            except Exception as msg:
                raise ValueError(msg)
            self.queue_list[port_name] = queue_list

        msg = {'result': 'success', 'details': queue_list}

        return REST_COMMAND_RESULT, msg
Ejemplo n.º 6
0
 def set_qos(self, port_name, type='linux-htb', max_rate=None, queues=None):
     LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
              log_utils.get_fname(2))
     """
     Sets a Qos rule and creates Queues on the given port.
     """
     queues = queues if queues else []
     command_qos = ovs_vsctl.VSCtlCommand('set-qos',
                                          [port_name, type, max_rate])
     command_queue = ovs_vsctl.VSCtlCommand('set-queue',
                                            [port_name, queues])
     self.run_command([command_qos, command_queue])
     if command_qos.result and command_queue.result:
         return command_qos.result + command_queue.result
     return None
Ejemplo n.º 7
0
    def set_db_attribute(self, table, record, column, value, key=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Sets 'value' into 'column' in 'record' in 'table'.

        This method is corresponding to the following ovs-vsctl command::

            $ ovs-vsctl set TBL REC COL[:KEY]=VALUE
        """
        if key is not None:
            column = '%s:%s' % (column, key)
        command = ovs_vsctl.VSCtlCommand('set', (table, record, '%s=%s' %
                                                 (column, value)))
        self.run_command([command])
Ejemplo n.º 8
0
    def list_db_attributes(self, table, record=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Lists 'record' (or all records) in 'table'.

        This method is corresponding to the following ovs-vsctl command::

            $ ovs-vsctl list TBL [REC]
        """
        command = ovs_vsctl.VSCtlCommand('list', (table, record))
        self.run_command([command])
        if command.result:
            return command.result
        return []
Ejemplo n.º 9
0
    def _get_external_port(self, name):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        # exclude vif ports
        external_ids = self.db_get_map('Interface', name, 'external_ids')
        if external_ids:
            return

        # exclude tunnel ports
        options = self.db_get_map('Interface', name, 'options')
        if 'remote_ip' in options:
            return

        ofport = self.get_ofport(name)
        return VifPort(name, ofport, None, None, self)
Ejemplo n.º 10
0
    def regist_ofs(dp, CONF):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        if dp.id in QoSController._OFS_LIST:
            return

        dpid_str = dpid_lib.dpid_to_str(dp.id)
        try:
            f_ofs = QoS(dp, CONF)
            f_ofs.set_default_flow()
        except OFPUnknownVersion as message:
            QoSController._LOGGER.info('dpid=%s: %s', dpid_str, message)
            return

        QoSController._OFS_LIST.setdefault(dp.id, f_ofs)
        QoSController._LOGGER.info('dpid=%s: Join qos switch.', dpid_str)
Ejemplo n.º 11
0
    def __init__(self, *args, **kwargs):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        super(RestQoSAPI, self).__init__(*args, **kwargs)

        # logger configure
        QoSController.set_logger(self.logger)
        self.cs = kwargs['conf_switch']
        self.dpset = kwargs['dpset']
        wsgi = kwargs['wsgi']
        self.waiters = {}
        self.data = {}
        self.data['dpset'] = self.dpset
        self.data['waiters'] = self.waiters
        wsgi.registory['QoSController'] = self.data
        wsgi.register(QoSController, self.data)
Ejemplo n.º 12
0
    def __init__(self,
                 CONF,
                 datapath_id,
                 ovsdb_addr,
                 timeout=None,
                 exception=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        super(OVSBridge, self).__init__()
        self.datapath_id = datapath_id
        self.ovsdb_addr = ovsdb_addr
        self.vsctl = ovs_vsctl.VSCtl(ovsdb_addr)
        self.timeout = timeout or CONF.ovsdb_timeout
        self.exception = exception

        self.br_name = None
Ejemplo n.º 13
0
    def set_default_flow(self):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        if self.version == ofproto_v1_0.OFP_VERSION:
            return

        cookie = 0
        priority = DEFAULT_FLOW_PRIORITY
        actions = [{'type': 'GOTO_TABLE', 'table_id': QOS_TABLE_ID + 1}]
        flow = self._to_of_flow(cookie=cookie,
                                priority=priority,
                                match={},
                                actions=actions)

        cmd = self.dp.ofproto.OFPFC_ADD
        self.ofctl.mod_flow_entry(self.dp, flow, cmd)
Ejemplo n.º 14
0
    def get_db_attribute(self, table, record, column, key=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Gets values of 'column' in 'record' in 'table'.

        This method is corresponding to the following ovs-vsctl command::

            $ ovs-vsctl get TBL REC COL[:KEY]
        """
        if key is not None:
            column = '%s:%s' % (column, key)
        command = ovs_vsctl.VSCtlCommand('get', (table, record, column))
        self.run_command([command])
        if command.result:
            return command.result[0]
        return None
Ejemplo n.º 15
0
    def delete_meter(self, rest, vlan_id, waiters):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        if (self.version == ofproto_v1_0.OFP_VERSION
                or self.version == ofproto_v1_2.OFP_VERSION):
            raise ValueError('delete_meter operation is not supported')

        cmd = self.dp.ofproto.OFPMC_DELETE
        try:
            self.ofctl.mod_meter_entry(self.dp, rest, cmd)
        except:
            raise ValueError('Invalid meter parameter.')

        msg = {
            'result': 'success',
            'details': 'Meter deleted. : Meter ID=%s' % rest[REST_METER_ID]
        }
        return REST_COMMAND_RESULT, msg
Ejemplo n.º 16
0
    def _get_cookie(self, vlan_id):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        if vlan_id == REST_ALL:
            vlan_ids = self.vlan_list.keys()
        else:
            vlan_ids = [vlan_id]

        cookie_list = []
        for vlan_id in vlan_ids:
            self.vlan_list.setdefault(vlan_id, 0)
            self.vlan_list[vlan_id] += 1
            self.vlan_list[vlan_id] &= ofproto_v1_3_parser.UINT32_MAX
            cookie = (vlan_id << COOKIE_SHIFT_VLANID) + \
                self.vlan_list[vlan_id]
            cookie_list.append([cookie, vlan_id])

        return cookie_list
Ejemplo n.º 17
0
    def set_ovsdb_addr(self, dpid, ovsdb_addr):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        old_address = self.ovsdb_addr
        if old_address == ovsdb_addr:
            return
        elif ovsdb_addr is None:
            # Determine deleting OVSDB address was requested.
            if self.ovs_bridge:
                self.ovs_bridge = None
            return

        ovs_bridge = bridge.OVSBridge(self.CONF, dpid, ovsdb_addr)
        try:
            ovs_bridge.init()
        except:
            raise ValueError('ovsdb addr is not available.')
        self.ovsdb_addr = ovsdb_addr
        self.ovs_bridge = ovs_bridge
Ejemplo n.º 18
0
    def add_vxlan_port(self,
                       name,
                       remote_ip,
                       local_ip=None,
                       key=None,
                       ofport=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Creates a VxLAN tunnel port.

        See the description of ``add_tunnel_port()``.
        """
        self.add_tunnel_port(name,
                             'vxlan',
                             remote_ip,
                             local_ip=local_ip,
                             key=key,
                             ofport=ofport)
Ejemplo n.º 19
0
    def to_rest(flow):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        if REST_ACTION in flow:
            actions = []
            for act in flow[REST_ACTION]:
                field_value = re.search(r'SET_FIELD: \{ip_dscp:(\d+)', act)
                if field_value:
                    actions.append({REST_ACTION_MARK: field_value.group(1)})
                meter_value = re.search(r'METER:(\d+)', act)
                if meter_value:
                    actions.append({REST_ACTION_METER: meter_value.group(1)})
                queue_value = re.search(r'SET_QUEUE:(\d+)', act)
                if queue_value:
                    actions.append({REST_ACTION_QUEUE: queue_value.group(1)})
            action = {REST_ACTION: actions}
        else:
            action = {REST_ACTION: 'Unknown action type.'}

        return action
Ejemplo n.º 20
0
    def find_db_attributes(self, table, *conditions):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Lists records satisfying 'conditions' in 'table'.

        This method is corresponding to the following ovs-vsctl command::

            $ ovs-vsctl find TBL CONDITION...

        .. Note::

            Currently, only '=' condition is supported.
            To support other condition is TODO.
        """
        args = [table]
        args.extend(conditions)
        command = ovs_vsctl.VSCtlCommand('find', args)
        self.run_command([command])
        if command.result:
            return command.result
        return []
Ejemplo n.º 21
0
    def get_ofs(self, dp_id):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        if len(self) == 0:
            raise ValueError('qos sw is not connected.')

        dps = {}
        if dp_id == REST_ALL:
            dps = self
        else:
            try:
                dpid = dpid_lib.str_to_dpid(dp_id)
            except:
                raise ValueError('Invalid switchID.')

            if dpid in self:
                dps = {dpid: self[dpid]}
            else:
                msg = 'qos sw is not connected. : switchID=%s' % dp_id
                raise ValueError(msg)

        return dps
Ejemplo n.º 22
0
class VifPort(object):
    LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
             log_utils.get_fname(2))

    def __init__(self, port_name, ofport, vif_id, vif_mac, switch):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        super(VifPort, self).__init__()
        self.port_name = port_name
        self.ofport = ofport
        self.vif_id = vif_id
        self.vif_mac = vif_mac
        self.switch = switch

    def __str__(self):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        return ('iface-id=%s, '
                'vif_mac=%s, '
                'port_name=%s, '
                'ofport=%d, '
                'bridge_name=%s' % (self.vif_id, self.vif_mac, self.port_name,
                                    self.ofport, self.switch.br_name))
Ejemplo n.º 23
0
    def to_mod_openflow(of_match):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        mac_dontcare = mac.haddr_to_str(mac.DONTCARE)
        ip_dontcare = '0.0.0.0'
        ipv6_dontcare = '::'

        match = {}
        for key, value in of_match.items():
            if key == REST_SRC_MAC or key == REST_DST_MAC:
                if value == mac_dontcare:
                    continue
            elif key == REST_SRC_IP or key == REST_DST_IP:
                if value == ip_dontcare:
                    continue
            elif key == REST_SRC_IPV6 or key == REST_DST_IPV6:
                if value == ipv6_dontcare:
                    continue
            elif value == 0:
                continue

            match.setdefault(key, value)

        return match
Ejemplo n.º 24
0
    def stats_reply_handler(self, ev):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        msg = ev.msg
        dp = msg.datapath

        if dp.id not in self.waiters:
            return
        if msg.xid not in self.waiters[dp.id]:
            return
        lock, msgs = self.waiters[dp.id][msg.xid]
        msgs.append(msg)

        flags = 0
        if dp.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION or \
                dp.ofproto.OFP_VERSION == ofproto_v1_2.OFP_VERSION:
            flags = dp.ofproto.OFPSF_REPLY_MORE
        elif dp.ofproto.OFP_VERSION == ofproto_v1_3.OFP_VERSION:
            flags = dp.ofproto.OFPMPF_REPLY_MORE

        if msg.flags & flags:
            return
        del self.waiters[dp.id][msg.xid]
        lock.set()
Ejemplo n.º 25
0
    def add_tunnel_port(self,
                        name,
                        tunnel_type,
                        remote_ip,
                        local_ip=None,
                        key=None,
                        ofport=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Creates a tunnel port.

        :param name: Port name to be created
        :param tunnel_type: Type of tunnel (gre or vxlan)
        :param remote_ip: Remote IP address of tunnel
        :param local_ip: Local IP address of tunnel
        :param key: Key of GRE or VNI of VxLAN
        :param ofport: Requested OpenFlow port number
        """
        options = 'remote_ip=%(remote_ip)s' % locals()
        if key:
            options += ',key=%(key)s' % locals()
        if local_ip:
            options += ',local_ip=%(local_ip)s' % locals()

        args = [
            'Interface', name,
            'type=%s' % tunnel_type,
            'options:%s' % options
        ]
        if ofport:
            args.append('ofport_request=%(ofport)s' % locals())

        command_add = ovs_vsctl.VSCtlCommand('add-port', (self.br_name, name))
        command_set = ovs_vsctl.VSCtlCommand('set', args)
        self.run_command([command_add, command_set])
Ejemplo n.º 26
0
    def add_bond(self, name, ifaces, bond_mode=None, lacp=None):
        LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
                 log_utils.get_fname(2))
        """
        Creates a bonded port.

        :param name: Port name to be created
        :param ifaces: List of interfaces containing at least 2 interfaces
        :param bond_mode: Bonding mode (active-backup, balance-tcp
                          or balance-slb)
        :param lacp: LACP mode (active, passive or off)
        """
        assert len(ifaces) >= 2

        options = ''
        if bond_mode:
            options += 'bond_mode=%(bond_mode)s' % locals()
        if lacp:
            options += 'lacp=%(lacp)s' % locals()

        command_add = ovs_vsctl.VSCtlCommand('add-bond',
                                             (self.br_name, name, ifaces),
                                             options)
        self.run_command([command_add])
Ejemplo n.º 27
0
 def get_tunnel_ports(self, tunnel_type='gre'):
     LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
              log_utils.get_fname(2))
     get_tunnel_port = functools.partial(self.get_tunnel_port,
                                         tunnel_type=tunnel_type)
     return self._get_ports(get_tunnel_port)
Ejemplo n.º 28
0
 def get_external_ports(self):
     LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
              log_utils.get_fname(2))
     return self._get_ports(self._get_external_port)
Ejemplo n.º 29
0
 def get_vif_ports(self):
     LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
              log_utils.get_fname(2))
     """ Returns a VIF object for each VIF port """
     return self._get_ports(self._get_vif_port)
Ejemplo n.º 30
0
 def _get_vif_port(self, name):
     LOG.info('%s(): caller(): %s', log_utils.get_fname(1),
              log_utils.get_fname(2))
     external_ids = self.db_get_map('Interface', name, 'external_ids')
     if 'iface-id' in external_ids and 'attached-mac' in external_ids:
         return self._vifport(name, external_ids)