コード例 #1
0
def save_end2end_delay(edges, links):
    flow_delays = {}
    for edge in edges:
        for flow in edge.flows:
            if flow.id not in flow_delays:
                flow_delays[flow.id] = 0
            # adding vnf_delays of destinations
            flow_delays[flow.id] += edge.dest.component.vnf_delay
            # adding path delay ,path delays are always the shortest paths and hence the same, so just adding the one at 0th index.
            flow_delays[flow.id] += sp.path_delay(links, edge.paths[0])
    return flow_delays
コード例 #2
0
def save_heuristic_variables(result, changed_instances, instances, edges,
                             nodes, links):
    # save placement
    result["placement"] = {"vnfs": [], "vlinks": []}
    for i in instances:
        vnf = {
            "name": i.component.name,
            "node": i.location,
            "image": i.component.config
        }
        result["placement"]["vnfs"].append(vnf)
    result["metrics"]["num_instances"] = len(result["placement"]["vnfs"])

    for e in edges:
        vlink = {
            "src_vnf": e.source.component.name,
            "src_node": e.source.location,
            "dest_vnf": e.dest.component.name,
            "dest_node": e.dest.location
        }
        result["placement"]["vlinks"].append(vlink)

    # node capacity violations
    result["placement"]["cpu_oversub"] = []
    result["placement"]["mem_oversub"] = []
    max_cpu, max_mem = 0, 0
    for v in nodes.ids:
        over_cpu = sum(i.consumed_cpu()
                       for i in instances if i.location == v) - nodes.cpu[v]
        if over_cpu > 0:
            result["placement"]["cpu_oversub"].append({"node": v})
            if over_cpu > max_cpu:
                max_cpu = over_cpu
        over_mem = sum(i.consumed_mem()
                       for i in instances if i.location == v) - nodes.mem[v]
        if over_mem > 0:
            result["placement"]["mem_oversub"].append({"node": v})
            if over_mem > max_mem:
                max_mem = over_mem
    result["metrics"]["max_cpu_oversub"] = max_cpu
    result["metrics"]["max_mem_oversub"] = max_mem

    # consumed node resources
    result["placement"]["alloc_node_res"] = []
    for i in instances:
        resources = {
            "name": i.component.name,
            "node": i.location,
            "cpu": i.consumed_cpu(),
            "mem": i.consumed_mem()
        }
        result["placement"]["alloc_node_res"].append(resources)

    # changed instances (compared to previous embedding)
    result["metrics"]["changed"] = []
    for i in changed_instances:
        result["metrics"]["changed"].append({
            "name": i.component.name,
            "node": i.location
        })
    result["metrics"]["num_changed"] = len(result["metrics"]["changed"])

    # edge and link data rate, used links
    result["placement"]["flows"] = []
    result["metrics"]["path_delays"] = []
    result["metrics"]["vnf_delays"] = []
    result["metrics"]["total_path_delay"] = 0
    result["metrics"]["total_vnf_delay"] = 0
    result['metrics']["total_delay"] = 0
    result["placement"]["links"] = []
    consumed_dr = defaultdict(int)  # default = 0
    for e in edges:
        for f in e.flows:
            flow = {
                "arc": str(e.arc),
                "src_node": e.source.location,
                "dst_node": e.dest.location,
                "flow_id": f.id
            }
            result["placement"]["flows"].append(flow)
        for path in e.paths:
            # record edge delay: all flows take the same (shortest) path => take path delay
            path_delay = {
                "src": e.arc.source.name,
                "dest": e.arc.dest.name,
                "src_node": e.source.location,
                "dest_node": e.dest.location,
                "path_delay": sp.path_delay(links, path)
            }
            result["metrics"]["path_delays"].append(path_delay)
            result["metrics"]["total_path_delay"] += sp.path_delay(links, path)
            result["metrics"]["total_delay"] += sp.path_delay(links, path)

            # go through nodes of each path and increase the dr of the traversed links
            for i in range(len(path) - 1):
                # skip connections on the same node (no link used)
                if path[i] != path[i + 1]:
                    consumed_dr[(path[i],
                                 path[i + 1])] += e.flow_dr() / len(e.paths)
                    link = {
                        "arc": str(e.arc),
                        "edge_src": e.source.location,
                        "edge_dst": e.dest.location,
                        "link_src": path[i],
                        "link_dst": path[i + 1]
                    }
                    result["placement"]["links"].append(link)

    # record VNF delay
    for i in instances:
        vnf_delay = {
            "vnf": i.component.name,
            "vnf_delay": i.component.vnf_delay
        }
        result["metrics"]["vnf_delays"].append(vnf_delay)
        result["metrics"]["total_vnf_delay"] += i.component.vnf_delay

    # record total delay = link + vnf delay
    result["metrics"]["total_delay"] = result["metrics"][
        "total_path_delay"] + result["metrics"]["total_vnf_delay"]

    # link capacity violations
    result["placement"]["dr_oversub"] = []
    max_dr = 0
    for l in links.ids:
        if links.dr[l] < consumed_dr[l]:
            result["placement"]["dr_oversub"].append({"link": l})
            if consumed_dr[l] - links.dr[l] > max_dr:
                max_dr = consumed_dr[l] - links.dr[l]
    result["metrics"]["max_dr_oversub"] = max_dr

    return result
コード例 #3
0
ファイル: control.py プロジェクト: PSNAppz/B-JointSP
def objective_value(overlays, print_info=False):
    # check delay of each edge; if too high, return math.inf for infeasible/infinity
    edges = [e for ol in overlays.values() for e in ol.edges]
    for e in edges:
        for path in e.paths:
            if sp.path_delay(links, path) > e.arc.max_delay:
                # print("Embedding INFEASIBLE because delay of path of {} is too high".format(e))
                logger.warning(
                    "Embedding INFEASIBLE because delay of path of {} is too high"
                    .format(e))
                return math.inf

    # calculate changed instances (compared to previous instances)
    curr_instances = {i for ol in overlays.values() for i in ol.instances}
    changed = prev_instances ^ curr_instances  # instances that are were added or removed
    # record max over-subscription of node capacities
    consumed_cpu, consumed_mem = consumed_node_resources(overlays)
    max_cpu_over, max_mem_over = 0, 0
    for v in nodes.ids:
        if consumed_cpu[v] - nodes.cpu[v] > max_cpu_over:
            max_cpu_over = consumed_cpu[v] - nodes.cpu[v]
        if consumed_mem[v] - nodes.mem[v] > max_mem_over:
            max_mem_over = consumed_mem[v] - nodes.mem[v]

    # calculate data rate of each link and mark used links for each edge
    consumed_dr = defaultdict(int)  # default = 0
    link_used = {}
    edges = [e for ol in overlays.values() for e in ol.edges]
    for e in edges:
        for path in e.paths:
            # go along nodes of the path and increment data rate of each traversed link
            for i in range(len(path) - 1):
                # skip connections on same node without a link (both inst at same node)
                if path[i] != path[i + 1]:
                    # assume the edge dr is split equally among all paths (currently only 1 path per edge)
                    consumed_dr[(path[i],
                                 path[i + 1])] += e.flow_dr() / len(e.paths)
                    link_used[(e.arc, e.source.location, e.dest.location,
                               path[i], path[i + 1])] = 1

    # record max over-subscription of link capacitiy
    max_dr_over = 0
    for l in links.ids:
        if consumed_dr[l] - links.dr[l] > max_dr_over:
            max_dr_over = consumed_dr[l] - links.dr[l]

    # calculate total delay over all used links (by different edges)
    total_delay = 0
    for key in link_used:
        total_delay += links.delay[(key[3], key[4])]

    # calculate total vnf delay of each node and add it to total_delay
    vnf_delays = 0
    for i in curr_instances:
        vnf_delays += i.component.vnf_delay

    # adding vnf_delay to total_delay
    total_delay += vnf_delays

    # calculate total consumed resources
    total_consumed_cpu = sum(consumed_cpu[v] for v in nodes.ids)
    total_consumed_mem = sum(consumed_mem[v] for v in nodes.ids)
    total_consumed_dr = sum(consumed_dr[l] for l in links.ids)

    # print objective value info
    if print_info:
        # print("Max over-subscription: {} (cpu), {} (mem), {} (dr)".format(max_cpu_over, max_mem_over, max_dr_over))
        # print("Total delay: {}, Num changed instances: {}".format(total_delay, len(changed)))
        # print("Total consumed resources: {} (cpu), {} (mem), {} (dr)".format(total_consumed_cpu, total_consumed_mem,
        #        total_consumed_dr))
        logger.info(
            "Max over-subscription: {} (cpu), {} (mem), {} (dr)".format(
                max_cpu_over, max_mem_over, max_dr_over))
        logger.info("Total delay: {}, Num changed instances: {}".format(
            total_delay, len(changed)))
        logger.info(
            "Total consumed resources: {} (cpu), {} (mem), {} (dr)".format(
                total_consumed_cpu, total_consumed_mem, total_consumed_dr))

    # calculate objective value; objectives & weights have to be identical to the MIP
    # lexicographical combination of all objectives
    if obj == objective.COMBINED:
        w1 = 100 * 1000 * 1000  # assuming changed instances < 100
        w2 = 1000 * 1000  # assuming total resource consumption < 1000
        w3 = 1000  # assuming total delay < 1000
        value = w1 * (max_cpu_over + max_mem_over + max_dr_over)
        value += w2 * len(changed)
        value += w3 * (total_consumed_cpu + total_consumed_mem +
                       total_consumed_dr)
        value += total_delay

    # minimize max over-subscription
    elif obj == objective.OVER_SUB:
        value = max_cpu_over + max_mem_over + max_dr_over

    # minimize changed instances (compared to previous embedding)
    elif obj == objective.CHANGED:
        value = len(changed)

    # minimize total resource consumption
    elif obj == objective.RESOURCES:
        value = total_consumed_cpu + total_consumed_mem + total_consumed_dr

    # minimize total delay
    elif obj == objective.DELAY:
        value = total_delay

    else:
        logger.error("Objective {} unknown".format(obj))
        raise ValueError("Objective {} unknown".format(obj))

    return value
コード例 #4
0
def format_output(result, changed_instances, overlays, nodes, links):

    instances, edges = set(), set()

    for ol in overlays:
        instances.update(ol.instances)
        edges.update(ol.edges)

    # save placement
    result['placement'] = {'vnfs': [], 'vlinks': []}
    result['metrics'] = {}

    for i in instances:
        vnf = {'name': i.component.name, 'node': i.location}
        result['placement']['vnfs'].append(vnf)

    result['metrics']['num_instances'] = len(result['placement']['vnfs'])

    for e in edges:
        vlink = {'src_vnf': e.source.component.name, 'src_node': e.source.location,
                 'dest_vnf': e.dest.component.name, 'dest_node': e.dest.location}
        result['placement']['vlinks'].append(vlink)

    # node capacity violations
    result['placement']['cpu_oversub'] = []
    result['placement']['mem_oversub'] = []
    max_cpu, max_mem = 0, 0
    for v in nodes.ids:
        over_cpu = sum(i.consumed_cpu() for i in instances if i.location == v) - nodes.cpu[v]
        if over_cpu > 0:
            result['placement']['cpu_oversub'].append({'node': v})
            if over_cpu > max_cpu:
                max_cpu = over_cpu
        over_mem = sum(i.consumed_mem() for i in instances if i.location == v) - nodes.mem[v]
        if over_mem > 0:
            result['placement']['mem_oversub'].append({'node': v})
            if over_mem > max_mem:
                max_mem = over_mem
    result['metrics']['max_cpu_oversub'] = max_cpu
    result['metrics']['max_mem_oversub'] = max_mem

    # consumed node resources
    result['placement']['alloc_node_res'] = []
    for i in instances:
        resources = {'name': i.component.name, 'node': i.location, 'cpu': i.consumed_cpu(), 'mem': i.consumed_mem()}
        result['placement']['alloc_node_res'].append(resources)

    # changed instances (compared to previous embedding)
    result['metrics']['changed'] = []
    for i in changed_instances:
        result['metrics']['changed'].append({'name': i.component.name, 'node': i.location})
    result['metrics']['num_changed'] = len(result['metrics']['changed'])

    # edge and link data rate, used links
    result['placement']['flows'] = []
    result['metrics']['path_delays'] = []
    result['metrics']['vnf_delays'] = []
    result['metrics']['total_path_delay'] = 0
    result['metrics']['total_vnf_delay'] = 0
    result['metrics']['max_endToEnd_delay'] = 0
    result['metrics']['total_delay'] = 0
    result['placement']['links'] = []
    consumed_dr = defaultdict(int)		# default = 0
    for e in edges:
        for f in e.flows:
            flow = {'arc': str(e.arc), 'src_node': e.source.location, 'dst_node': e.dest.location,
                    'src_vnf': e.source.component.name, 'dest_vnf': e.dest.component.name, 'flow_id': f.id}
            result['placement']['flows'].append(flow)
        for path in e.paths:
            # record edge delay: all flows take the same (shortest) path => take path delay
            path_delay = {'src': e.arc.source.name, 'dest': e.arc.dest.name, 'src_node': e.source.location, 'dest_node': e.dest.location, 'path_delay': sp.path_delay(links, path)}
            result['metrics']['path_delays'].append(path_delay)
            result['metrics']['total_path_delay'] += sp.path_delay(links, path)
            result['metrics']['total_delay'] += sp.path_delay(links, path)

            # go through nodes of each path and increase the dr of the traversed links
            for i in range(len(path) - 1):
                # skip connections on the same node (no link used)
                if path[i] != path[i+1]:
                    consumed_dr[(path[i], path[i+1])] += e.flow_dr() / len(e.paths)
                    link = {'arc': str(e.arc), 'edge_src': e.source.location, 'edge_dst': e.dest.location, 'link_src': path[i], 'link_dst': path[i+1]}
                    result['placement']['links'].append(link)

    # record VNF delay
    for i in instances:
        vnf_delay = {'vnf': i.component.name, 'vnf_delay': i.component.vnf_delay}
        result['metrics']['vnf_delays'].append(vnf_delay)
        result['metrics']['total_vnf_delay'] += i.component.vnf_delay
    # record total delay = link + vnf delay
    result['metrics']['total_delay'] = result['metrics']['total_path_delay'] + result['metrics']['total_vnf_delay']

    #record max end-to-end delay
    endToEnd = save_end2end_delay(edges,links)
    if endToEnd:
        result['metrics']['max_endToEnd_delay'] = max(endToEnd.values())
    # for an empty placement, there is no end to end delay
    else:
        result['metrics']['max_endToEnd_delay'] = 0

    # link capacity violations
    result['placement']['dr_oversub'] = []
    max_dr = 0
    for l in links.ids:
        if links.dr[l] < consumed_dr[l]:
            result['placement']['dr_oversub'].append({'link': l})
            if consumed_dr[l] - links.dr[l] > max_dr:
                max_dr = consumed_dr[l] - links.dr[l]
    result['metrics']['max_dr_oversub'] = max_dr
    result['id'] = str(uuid.uuid4())
    store.store_placement_result(result)

    return result['id']