예제 #1
0
def map_flows2stateful(overlay, start_instance, arc, out_flows):
    # remove any existing mappings of flows to edges along the arc
    for e in start_instance.edges_out.values():
        if e.arc == arc:
            e.flows = []

    # add currently outgoing flows to edges back to stateful instances (create edges if necessary)
    for f in out_flows:
        dest_inst = f.passed_stateful[arc.dest]
        if dest_inst in start_instance.edges_out.keys():
            new_edge = False
            edge = start_instance.edges_out[dest_inst]
        else:
            new_edge = True
            edge = Edge(arc, start_instance, dest_inst)
            edge.paths.append(shortest_paths[(start_instance.location,
                                              dest_inst.location)][0])
            overlay.edges.append(edge)
        f.dr[edge] = out_flows[f]
        edge.flows.append(f)
        # print("\tMapped flow {} (dr {}) to edge {} (new: {}) back to same stateful instance".format(f, out_flows[f],
        #       edge, new_edge))
        logger.info(
            "\tMapped flow {} (dr {}) to edge {} (new: {}) back to same stateful instance"
            .format(f, out_flows[f], edge, new_edge))
예제 #2
0
def read_prev_embedding(file, templates, nodes, links):
    # create shortest paths
    shortest_paths = sp.all_pairs_shortest_paths(nodes, links)
    # create empty overlays for all templates
    prev_embedding = {}  # dict: template -> overlay
    for t in templates:
        prev_embedding[t] = Overlay(t, [], [])

    with open(file, "r") as f:
        yaml_file = yaml.load(f, yaml.SafeLoader)

        # read and create VNF instances of previous embedding
        for vnf in yaml_file["placement"]["vnfs"]:
            # find component that matches the VNF name (in any of the templates)
            for t in templates:
                # use first matching component (assuming it's only in one template)
                if vnf["name"] in [c.name for c in t.components]:
                    component = list(filter(lambda x: x.name == vnf["name"], t.components))[0]
                    # add new instance to overlay of corresponding template (source components need src_flows being set)
                    if component.source:
                        prev_embedding[t].instances.append(Instance(component, vnf["node"], src_flows=[]))
                    else:
                        prev_embedding[t].instances.append(Instance(component, vnf["node"]))
                    break

        # TODO: read and create flows. otherwise, adding edges really doesn't make a difference in the heuristic
        # read and create edges of previous embedding
        for edge in yaml_file["placement"]["vlinks"]:
            instances = [i for ol in prev_embedding.values() for i in ol.instances]

            # try to get source and dest instance from list of instances
            try:
                source = list(filter(lambda x: x.component.name == edge["src_vnf"] and x.location == edge["src_node"],
                                     instances))[0]
                dest = list(filter(lambda x: x.component.name == edge["dest_vnf"] and x.location == edge["dest_node"],
                                   instances))[0]
            # if the vnfs don't exist in prev_embedding (eg, through incorrect input), ignore the edge
            except IndexError:
                # print("No matching VNFs in prev_embedding for edge from {} to {}.
                #                                         Ignoring the edge.".format(source, dest))
                continue  # skip and continue with next edge

            # get arc from templates by matching against source and dest components
            for t in templates:
                if source.component in t.components and dest.component in t.components:
                    # assume t has an arc source->dest if both components are in t
                    arc = list(filter(lambda x: x.source == source.component and x.dest == dest.component, t.arcs))[0]
                    # add new edge to overlay of corresponding template
                    edge = Edge(arc, source, dest)
                    prev_embedding[t].edges.append(edge)
                    edge.paths.append(shortest_paths[(source.location, dest.location)][0])

    return prev_embedding
예제 #3
0
def map_flow2edge(overlay, start_instance, arc, flow, flow_dr, tabu):
    # determine if the instances of the destination component are fixed => if so, cannot place new instances
    fixed = False
    for i in overlay.instances:
        if i.component == arc.dest and i.fixed:
            fixed = True
            break
    best_node = find_best_node(overlay, start_instance.location, arc, flow_dr,
                               fixed, tabu)
    if best_node is None:
        logger.error(f"No suitable node found. Cannot compute placement.")
        return False

    # if the instance at best node already exists (e.g., from forward dir), just connect to it, else create anew
    # look for existing instance
    instance_exists = False
    for i in overlay.instances:
        if i.component == arc.dest and i.location == best_node:
            instance_exists = True
            dest_instance = i
            break
    # create new instance if none exists in the overlay
    if not instance_exists:
        dest_instance = Instance(arc.dest, best_node)
        overlay.instances.append(dest_instance)
        # print("\tAdded new instance {} at best node {} (may exist in other overlays)".format(dest_instance,
        #        best_node))
        logger.info(
            "\tAdded new instance {} at best node {} (may exist in other overlays)"
            .format(dest_instance, best_node))

    # check if edge to dest_instance already exists
    edge_exists = False
    if instance_exists:
        if dest_instance in start_instance.edges_out.keys():
            edge_exists = True
            edge = start_instance.edges_out[dest_instance]

    # if it doesn't exist, create a new edge and assign a path (shortest path)
    if not edge_exists:
        edge = Edge(arc, start_instance, dest_instance)
        overlay.edges.append(edge)
        edge.paths.append(shortest_paths[(start_instance.location,
                                          dest_instance.location)][0])

    # map flow to edge
    flow.dr[edge] = flow_dr
    edge.flows.append(flow)
    # print("\tMapped flow {} (dr {}) to edge {} (new: {})".format(flow, flow_dr, edge, not edge_exists))
    logger.info("\tMapped flow {} (dr {}) to edge {} (new: {})".format(
        flow, flow_dr, edge, not edge_exists))
    return True
예제 #4
0
    def __deepcopy__(self, memodict={}):
        new_overlay = Overlay(self.template, [], [])  # empty overlay
        instance_dict = {
        }  # dict of old to new instances; for easy access when adding the edges
        flow_dict = {}  # same for old to new flows

        # add new instances with same attributes (component, etc) but without edges_in/out
        for i in self.instances:
            # copy src_flows
            new_src_flows = None
            if i.src_flows:
                new_src_flows = []
                for f in i.src_flows:
                    new_flow = Flow(f.id, f.src_dr)
                    flow_dict[f] = new_flow
                    new_src_flows.append(new_flow)
            # copy instances
            new_instance = Instance(i.component, i.location, new_src_flows,
                                    i.fixed)
            new_overlay.instances.append(new_instance)
            instance_dict[i] = new_instance

        # add new edges in topological order => sets edges_in/out etc automatically
        for e in self.topological_order(True):
            # source/dest from new_overlay's instances using the instance_dict
            new_source = instance_dict[e.source]
            new_dest = instance_dict[e.dest]
            # create new edge with references to the new instances and manually set the remaining attributes
            new_edge = Edge(e.arc, new_source, new_dest)
            new_edge.direction = e.direction
            new_edge.paths = copy.deepcopy(
                e.paths, memodict)  # deepcopy for copying list of lists

            # copy and update flows
            for f in e.flows:
                new_flow = flow_dict[f]
                new_edge.flows.append(new_flow)
                new_flow.dr[new_edge] = f.dr[e]
                if new_edge.source.component.stateful:
                    new_flow.passed_stateful[
                        new_edge.source.component] = new_edge.source
                elif new_edge.dest.component.stateful:
                    new_flow.passed_stateful[
                        new_edge.dest.component] = new_edge.dest

            new_overlay.edges.append(new_edge)

        return new_overlay