예제 #1
0
    def network_info(self, **kwargs):

        # Access resource catalogue
        catalog = ndb()

        # Get network topology
        (topo_success, topo_msg) = self.ovs_ctl.get_topology()
        if not topo_success:
            # Send error message
            msg = '[ERROR]: Could not retrieve the network topology from ovs controller'
            print('failed', (time() - st) * 1000, 'ms')
            # Inform the user about the creation
            return False, msg

        topology = topo_msg.get('topology')
        catalog.set_topology(topology)

        # Return information
        return True, {
            "tn": {
                "topology": catalog.get_topology(),
                "capacity": catalog.get_capacity(),
                "routes": catalog.get_routes(),
                #  "networks": catalog.get_networks(),
                "usage": catalog.get_usage(),
                "flows": catalog.get_flows(),
                "virtual_ifaces": catalog.get_virtual_ifaces()
            }
        }
예제 #2
0
    def get_throughput_comply_path(self, paths, throughput):
        catalog = ndb()
        flows = catalog.get_flows()
        usage = catalog.get_usage()
        capacity = catalog.get_capacity()
        
        count = {}
        comply_paths = []
        for path in paths:
            is_comply = True
            path_string = ''.join(map(str, path))
            for p in range(0, len(path) - 1):
                if path_string not in count:
                    count[path_string] = 0
                count[path_string] = count[path_string] + flows[path[p]][path[p + 1]]
                if usage[path[p]][path[p + 1]] + throughput >= capacity[path[p]][path[p + 1]]:
                    is_comply = False
                    break
            if is_comply:
                comply_paths.append(path)

        path_to_apply = None
        min_count = 999999999
        if len(comply_paths) > 0:
            for path in comply_paths:
                path_string = ''.join(map(str, path))
                if count[path_string] < min_count:
                    min_count = count[path_string]
                    path_to_apply = path
                elif count[path_string] == min_count and len(path) < len(path_to_apply):
                    min_count = count[path_string]
                    path_to_apply = path
        return path_to_apply
예제 #3
0
 def configure_flow_rules(self, src_agent, dst_agent):
     engine = PathEngine()
     catalog = ndb()
     topology = self.get_topology()
     paths = engine.get_paths(topology, src_agent.get('switch'),
                              dst_agent.get('switch'))
     src = []
     for path in paths:
         self.src_seq = self.src_seq + 1
         src_host = str(self.src_seq)
         src.append(src_host)
         switches = engine.generate_match_switches(topology, path,
                                                   src_agent.get('port'),
                                                   dst_agent.get('port'))
         route = {
             'ipv4_src': src_host,
             'ipv4_src_netmask': '255.255.255.255',
             'ipv4_dst': dst_agent.get('host'),
             'ipv4_dst_netmask': '255.255.255.255',
             'min_rate': None,
             'max_rate': None,
             'priority': 10,
             'switches': switches
         }
         s_id = str(uuid4())
         success, msg = self.orch.ovs_ctl.create_slice(**{
             's_id': s_id,
             'route': route
         })
         if not success:
             return None
         addresses = src_host + '-' + dst_agent.get('host')
         path_string = '-'.join(map(str, path))
         catalog.add_virtual_iface(addresses, path_string)
     return src
예제 #4
0
 def get_path(self, topology, src, dst, requirements):
     catalog = ndb()
     catalog.init_arrays()
     paths = self.get_paths(topology, src, dst)
     print('paths', paths)
     path = self.get_capable_path(paths, requirements)
     return path
예제 #5
0
    def delete_slice(self, **kwargs):
        # Extract parameters from keyword arguments
        s_id = kwargs.get('s_id', None)
        route = kwargs.get('route', None)
        complete_remove = False

        catalog = ndb()
        if route is None:
            # Retrieve the route previously applied
            complete_remove = True
            route = catalog.get_route(s_id)

            if route is None:
                return False, 'Route not found for s_id ' + s_id

        # Send message to remove slice
        success, msg = self.ovs_ctl.delete_slice(**{
            's_id': s_id,
            'route': route
        })
        if success:
            path = route['path']
            for p in range(0, len(path) - 1):
                catalog.add_flow_count(path[p], path[p + 1], -1)
                if route['throughput'] is not None:
                    catalog.add_link_usage(path[p], path[p + 1],
                                           -route['throughput'])
            if complete_remove:
                catalog.remove_route(s_id)
        # Inform the user about the removal
        return success, msg
예제 #6
0
파일: she.py 프로젝트: orca-project/hoen
 def analyze_paths(self, metric):
     catalog = ndb()
     routes = catalog.get_routes()
     path_string = catalog.get_virtual_iface(metric.get('src') + '-' + metric.get('dst'))
     current_latency = float(metric.get('params').get('max'))
     affected_slices = [
         i for i in routes if routes[i].get('path_string') == path_string 
         and routes[i].get('latency') is not None 
         and (routes[i].get('latency') <= current_latency 
             or current_latency < 0)
     ]
     for s_id in affected_slices:
         print('\t', 'SHE - starting reconfiguration of slice ', s_id)
         if s_id not in self.lock:
             try:
                 self.lock.append(s_id)
                 success, msg = self.orch.reconfigure_slice(**{'s_id': s_id})
                 if success:
                     print('\t', 'SHE - reconfiguration finished for ', s_id)
                 else:
                     print('\t', 'SHE - ERROR ', s_id)
                 self.lock.remove(s_id)
             except Exception as e:
                 self.lock.remove(s_id)
                 print('\t', 'SHE - ERROR reconfiguring ', s_id, e)
                 #traceback.print_stack()
예제 #7
0
 def find_border_switch(self, address):
     catalog = ndb()
     resp = None
     networks = catalog.get_networks()
     for network in networks:
         if IPAddress(address) in IPNetwork(network):
             resp = networks[network]
             break
     return resp
예제 #8
0
 def get_latency_comply_paths(self, paths, latency):
     catalog = ndb()
     comply_paths = []
     for path in paths:
         path_string = '-'.join(map(str, path))
         metric = catalog.get_path_latency(path_string)
         if metric is not None and metric.get('max') != -1 and float(metric.get('max')) < float(latency):
             comply_paths.append(path)
     return comply_paths
예제 #9
0
    def get_topology(self):
        (topo_success, topo_msg) = self.orch.ovs_ctl.get_topology()
        if not topo_success:
            return None

        topology = topo_msg.get('topology')
        catalog = ndb()
        catalog.set_topology(topology)
        return topology
예제 #10
0
    def reconfigure_slice(self, **kwargs):
        s_id = kwargs.get('s_id', None)
        catalog = ndb()
        old_route = catalog.get_route(s_id)

        source = old_route.get('src')
        destination = old_route.get('dst')
        latency = old_route.get('latency')
        throughput = old_route.get('throughput')

        slice_args = {
            's_id': s_id,
            'source': source,
            'destination': destination,
            'requirements': {
                'throughput': throughput,
                'latency': latency
            }
        }
        print('slice args ', slice_args)
        (success, msg) = self.create_slice(**slice_args)
        print('create success ', success)
        if success:
            switches = []
            new_route = catalog.get_route(s_id)
            print('new_route', new_route)
            if old_route.get('path_string') != new_route.get('path_string'):
                for old in old_route.get('switches'):
                    current = self.get_in_switches(old,
                                                   new_route.get('switches'))
                    if len(current) > 0:
                        #if old.get('in_port') != current[0].get('in_port'):
                        #    switches.append(old)
                        if old.get('in_port') != current[0].get('in_port'):
                            if old.get('out_port') != current[0].get(
                                    'out_port'):
                                old['direction'] = 'full'
                                switches.append(old)
                            else:
                                old['direction'] = 'half-fw'
                                switches.append(old)
                        elif old.get('out_port') != current[0].get('out_port'):
                            old['direction'] = 'half-rv'
                            switches.append(old)
                    else:
                        old['direction'] = 'full'
                        switches.append(old)
                route_to_delete = self.generate_route_to_delete(
                    old_route, switches)
                success, msg = self.delete_slice(**{
                    's_id': s_id,
                    'route': route_to_delete
                })
        return success, msg
예제 #11
0
 def request_slice(self, **kwargs):
     s_id = kwargs.get('s_id', None)
     catalog = ndb()
     if s_id is not None:
         route = catalog.get_route(s_id)
         if route is not None:
             msg = {}
             msg[s_id] = route
     else:
         msg = catalog.get_routes()
     return (False, "Service not found.") \
         if (s_id and not msg) else (True, msg)
예제 #12
0
 def __init__(self, orch, host, port):
     Thread.__init__(self)
     self.orch = orch
     self.src_seq = ipaddress.ip_address("10.10.0.0")
     self.shutdown_flag = Event()
     self._server_bind(host, port)
     catalog = ndb()
     #agent = catalog.add_local_agent('sonar-req02', '10.0.0.30', 'ith0', 's01', 5)
     #agent = catalog.add_local_agent('sonar-p01', '10.1.0.1', 'ith0', 's05', 3)
     agent = catalog.add_local_agent('sonar-local-agent01', '100.1.3.3',
                                     'sth01', 's01', 1)
     agent = catalog.add_local_agent('sonar-local-agent02', '100.1.3.4',
                                     'sth01', 's05', 4)
예제 #13
0
 def report(self, request):
     t_id = request.get('t_id')
     catalog = ndb()
     broker = nem()
     for metric in request.get('metrics'):
         if metric.get('type') == 'latency':
             path_string = catalog.get_virtual_iface(
                 metric.get('src') + '-' + metric.get('dst'))
             catalog.set_path_latency(path_string, metric.get('params'))
             broker.insert_metric(metric)
             #self.check_paths(path_string, metric.get('params'))
     resp = {"id": t_id, "type": "report_resp", "result_code": 0}
     return resp
예제 #14
0
    def create_slice(self, **kwargs):
        catalog = ndb()
        st = time()
        # Extract parameters from keyword arguments
        s_id = kwargs.get('s_id', None)
        source, destination = self.get_address_params(kwargs)
        requirements = kwargs.get('requirements', None)

        # Append it to the list of service IDs
        self.s_ids[s_id] = requirements

        # Get network topology
        (topo_success, topo_msg) = self.ovs_ctl.get_topology()
        if not topo_success:
            # Send error message
            msg = '[ERROR]: Could not retrieve the network topology from ovs controller'
            print('failed', (time() - st) * 1000, 'ms')
            # Inform the user about the creation
            return False, msg

        topology = topo_msg.get('topology')
        catalog.set_topology(topology)

        # Define the route which can support the required QoS
        route = self.build_route(topology, source, destination, requirements)

        if route is None:
            # Send error message
            msg = '[WARN]: There is no available path for source ' + str(
                source) + ' and destination ' + str(
                    destination) + ' supporting the follow QoS: ' + str(
                        requirements)
            print('failed', (time() - st) * 1000, 'ms')
            # Inform the user about the creation
            return False, msg

        # Send message to OVS SDN controller
        self._log('Delegating it to the OVS Controller')

        # Send the message to create a slice
        success, msg = self.ovs_ctl.create_slice(**{
            's_id': s_id,
            'route': route
        })

        print('success', (time() - st) * 1000, 'ms')

        if success:
            catalog.add_route(s_id, route)
        # Inform the user about the creation
        return success, msg
예제 #15
0
    def build_route(self, topology, src, dst, requirements):
        catalog = ndb()
        engine = PathEngine()

        # Fetch switches which can arrive to the src and dst networks
        src_network = self.find_border_switch(src)
        dst_network = self.find_border_switch(dst)

        if src_network is None or dst_network is None:
            print('\t', 'Impossible to arrive from ', src, 'to ', dst)
            return None

        # Define the path to apply
        path = engine.get_path(topology, src_network.get('switch'),
                               dst_network.get('switch'), requirements)
        print('path ', path)
        if path is None:
            return None

        print('\t', 'Path to be applied: ', path)
        (ipv4_src, ipv4_src_netmask) = self.convert_cidr_to_netmask(src)
        (ipv4_dst, ipv4_dst_netmask) = self.convert_cidr_to_netmask(dst)
        (min_rate, max_rate,
         priority) = self.define_queue_parameters(requirements)

        first_port = src_network.get('port')
        last_port = dst_network.get('port')
        switches = engine.generate_match_switches(topology, path, first_port,
                                                  last_port)
        path_string = '-'.join(map(str, path))

        route = {
            'src': src,
            'dst': dst,
            'ipv4_src': ipv4_src,
            'ipv4_src_netmask': ipv4_src_netmask,
            'ipv4_dst': ipv4_dst,
            'ipv4_dst_netmask': ipv4_dst_netmask,
            'min_rate': min_rate,
            'max_rate': max_rate,
            'priority': priority,
            'switches': switches,
            'path_string': path_string,
            'path': path,
            'latency': requirements.get('latency'),
            'throughput': requirements.get('throughput')
        }
        return route
예제 #16
0
 def configure_metric_paths(self, request):
     catalog = ndb()
     src_agent = catalog.get_local_agent(request.get('name'))
     configured_agents = catalog.get_configured_agents()
     configured_agent = None
     if src_agent.get('name') not in configured_agents:
         dst = []
         agents = catalog.get_local_agents()
         for dst_agent_name in agents:
             if src_agent.get('name') != dst_agent_name:
                 src = self.configure_flow_rules(src_agent,
                                                 agents[dst_agent_name])
                 if src is None:
                     return None
                 dst.append(agents[dst_agent_name].get('host'))
         configured_agent = catalog.add_configured_agent(
             src_agent, src, dst)
     return configured_agent
예제 #17
0
    def get_configuration(self, request):
        catalog = ndb()
        agents = catalog.get_local_agents()
        t_id = request.get('t_id')
        name = request.get('name')
        if name not in agents:
            return self.error_resp(t_id, 1)

        configured_agent = self.configure_metric_paths(request)

        if configured_agent is not None:
            resp = {
                "t_id": t_id,
                "type": "config_resp",
                "src": configured_agent.get('src'),
                "dst": configured_agent.get('dst'),
                "management_iface": agents[name].get('management_iface'),
                "result_code": 0
            }
        else:
            resp = self.error_resp(t_id, 2)
        return resp
예제 #18
0
    def post_init(self, **kwargs):
        # OVS Controller Handler
        self.ovs_ctl = ctl_base(name="OVS",
                                host_key="ovs_host",
                                port_key="ovs_port",
                                default_host="20.1.0.1",
                                default_port="3200",
                                request_key="ovs_req",
                                reply_key="ovs_rep",
                                create_msg='ovc_crs',
                                request_msg='ovc_rrs',
                                update_msg='ovc_urs',
                                delete_msg='ovc_drs',
                                topology_msg='ovc_trs')

        # setting link speeds manually
        # TODO: to create a service to fetch these values automatically from ovsdb or ofconfig
        catalog = ndb()
        catalog.set_link_capacity('s01', 's02', 1000)
        catalog.set_link_capacity('s01', 's04', 1000)
        catalog.set_link_capacity('s02', 's03', 1000)
        catalog.set_link_capacity('s02', 's01', 1000)
        catalog.set_link_capacity('s03', 's04', 1000)
        catalog.set_link_capacity('s03', 's02', 1000)
        catalog.set_link_capacity('s04', 's01', 1000)
        catalog.set_link_capacity('s04', 's03', 1000)
        '''
        Setting known hosts and networks manually.
        It could be automatic if we develop LLDP and ARP functions in the ovs controller...
        ... but it is out of scope.
        '''
        #  catalog.add_network('30.0.1.0/24', 's01', 4)
        #  catalog.add_network('10.0.4.0/24', 's01', 4)
        catalog.add_network('30.0.5.0/24', 's01', 3)
        catalog.add_network('30.0.6.0/24', 's01', 4)
        catalog.add_network('30.0.7.0/24', 's01', 5)

        catalog.add_network('10.0.0.0/24', 's03', 3)
예제 #19
0
 def get(self):
     catalog = ndb()
     topology = catalog.get_topology()
     capacity = catalog.get_capacity()
     routes = catalog.get_routes()
     networks = catalog.get_networks()
     usage = catalog.get_usage()
     flows = catalog.get_flows()
     local_agents = catalog.get_local_agents()
     configured_agents = catalog.get_configured_agents()
     path_latency = catalog.get_path_latencies()
     virtual_ifaces = catalog.get_virtual_ifaces()
     return {
         "topology": topology,
         "capacity": capacity,
         "routes": routes,
         "networks": networks,
         "usage": usage,
         "flows": flows,
         "local_agents": local_agents,
         "configured_agents": configured_agents,
         "path_latency": path_latency,
         "virtual_ifaces": virtual_ifaces
     }
예제 #20
0
 def get_capable_path(self, paths, requirements):
     print('requirements', requirements)
     catalog = ndb()
     throughput = 0
     if requirements is not None:
         # If our platform can support other QoS in the future, please add them as 'if' below:
         if requirements.get('latency') is not None:
             print('latency qos')
             paths = self.get_latency_comply_paths(paths, requirements.get('latency'))
             print('paths', paths)
         if requirements.get('throughput') is not None:
             print('throughput qos')
             throughput = requirements.get('throughput')
             path = self.get_throughput_comply_path(paths, throughput)
         else:
             if len(paths) > 0:
                 path = min(paths, key=len)
             else:
                 path = None
     if path is not None:
         for p in range(0, len(path) - 1):
             catalog.add_link_usage(path[p], path[p + 1], throughput)
             catalog.add_flow_count(path[p], path[p + 1], 1)
     return path
예제 #21
0
 def get(self):
     catalog = ndb()
     routes = catalog.get_routes()
     return {'routes': routes}