예제 #1
0
def _onlySAPsRequest():
    nffg = NFFG(id="BME-req-001")
    sap1 = nffg.add_sap(name="SAP1", id="sap1")
    sap2 = nffg.add_sap(name="SAP2", id="sap2")

    nffg.add_sglink(sap1.add_port(0), sap2.add_port(0))
    # nffg.add_sglink(sap1.add_port(1), sap2.add_port(1))

    nffg.add_req(sap1.ports[0], sap2.ports[0], bandwidth=1000, delay=24)
    nffg.add_req(sap1.ports[0], sap2.ports[0], bandwidth=1000, delay=24)

    return nffg
예제 #2
0
def _example_request_for_fallback():
    nffg = NFFG(id="FALLBACK-REQ", name="fallback-req")
    sap1 = nffg.add_sap(name="SAP1", id="sap1")
    sap2 = nffg.add_sap(name="SAP2", id="sap2")

    # add NF requirements.
    nf0 = nffg.add_nf(id="NF0",
                      name="NetFunc0",
                      func_type='B',
                      cpu=2,
                      mem=2,
                      storage=2,
                      bandwidth=100)
    nf1 = nffg.add_nf(id="NF1",
                      name="NetFunc1",
                      func_type='A',
                      cpu=1.5,
                      mem=1.5,
                      storage=1.5,
                      delay=50)
    nf2 = nffg.add_nf(id="NF2",
                      name="NetFunc2",
                      func_type='C',
                      cpu=3,
                      mem=3,
                      storage=3,
                      bandwidth=500)
    nf3 = nffg.add_nf(id="NF3",
                      name="NetFunc3",
                      func_type='A',
                      cpu=2,
                      mem=2,
                      storage=2,
                      bandwidth=100,
                      delay=50)

    # add SG hops
    nffg.add_sglink(sap1.add_port(0), nf0.add_port(0), id="s1n0")
    nffg.add_sglink(nf0.add_port(1), nf1.add_port(0), id="n0n1")
    nffg.add_sglink(nf1.add_port(1), nf2.add_port(0), id="n1n2")
    nffg.add_sglink(nf1.add_port(2), nf3.add_port(0), id="n1n3")
    nffg.add_sglink(nf2.add_port(1), sap2.add_port(0), id="n2s2")
    nffg.add_sglink(nf3.add_port(1), sap2.add_port(1), id="n3s2")

    # add EdgeReqs
    # port number on SAP2 doesn`t count
    nffg.add_req(sap1.ports[0], sap2.ports[1], bandwidth=1000, delay=24)
    nffg.add_req(nf0.ports[1], nf1.ports[0], bandwidth=200)
    nffg.add_req(nf0.ports[1], nf1.ports[0], delay=3)

    # set placement criteria. Should be used to enforce the placement decision of
    # the upper orchestration layer. Placement criteria can contain multiple
    # InfraNode id-s, if the BiS-BiS is decomposed to multiple InfraNodes in this
    # layer.
    # setattr(nf1, 'placement_criteria', ['nc2'])

    return nffg
예제 #3
0
def _testRequestForBacktrack():
    nffg = NFFG(id="backtracktest-req", name="btreq")
    sap1 = nffg.add_sap(name="SAP1", id="sap1req")
    sap2 = nffg.add_sap(name="SAP2", id="sap2req")

    a = nffg.add_nf(id="a",
                    name="NetFunc0",
                    func_type='A',
                    cpu=3,
                    mem=3,
                    storage=3)
    b = nffg.add_nf(id="b",
                    name="NetFunc1",
                    func_type='A',
                    cpu=3,
                    mem=3,
                    storage=3)
    c = nffg.add_nf(id="c",
                    name="NetFunc2",
                    func_type='A',
                    cpu=3,
                    mem=3,
                    storage=3)

    nffg.add_sglink(sap1.add_port(0), a.add_port(0), id="sa")
    nffg.add_sglink(a.add_port(1), b.add_port(0), id="ab")
    nffg.add_sglink(b.add_port(1), c.add_port(0), id="bc")
    nffg.add_sglink(c.add_port(1), sap2.add_port(0), id="cs")

    nffg.add_req(a.ports[0], b.ports[1], delay=1.0, sg_path=["ab"])
    nffg.add_req(b.ports[0], c.ports[1], delay=1.0, sg_path=["bc"])
    nffg.add_req(c.ports[0], sap2.ports[0], delay=1.0, sg_path=["cs"])
    nffg.add_req(sap1.ports[0],
                 sap2.ports[0],
                 delay=50,
                 bandwidth=10,
                 sg_path=["sa", "ab", "bc", "cs"])

    return nffg
def generateRequestForCarrierTopo(all_saps_ending,
                                  all_saps_beginning,
                                  avg_shp_len,
                                  nf_types,
                                  max_e2e_lat_multiplier=20,
                                  min_e2e_lat_multiplier=1.1,
                                  loops=False,
                                  use_saps_once=True,
                                  vnf_sharing_probabilty=0.0,
                                  multiSC=False,
                                  max_sc_count=2,
                                  chain_maxlen=8,
                                  max_cpu=4,
                                  max_mem=1600,
                                  max_storage=3,
                                  max_bw=7):
    """
  By default generates VNF-disjoint SC-s starting/ending only once in each SAP.
  With the 'loops' option, only loop SC-s are generated.
  'vnf_sharing_probabilty' determines the ratio of 
     #(VNF-s used by at least two SC-s)/#(not shared VNF-s).
  """
    sc_count = 1
    gen = NameGenerator()
    # maximal possible bandwidth for chains
    if multiSC:
        sc_count = rnd.randint(2, max_sc_count)
    while len(all_saps_ending) > sc_count and len(
            all_saps_beginning) > sc_count:
        nffg = NFFG(id="E2e_req_test_nffg")
        nffg.mode = NFFG.MODE_ADD
        # newly added NF-s of one request
        current_nfs = []
        for scid in xrange(0, sc_count):
            # find two SAP-s for chain ends.
            nfs_this_sc = []
            sapid = all_saps_beginning.pop() if use_saps_once else \
              rnd.choice(all_saps_beginning)
            if sapid not in nffg:
                sap1 = nffg.add_sap(id=sapid)
            else:
                sap1 = nffg.network.node[sapid]
            sap2 = None
            if loops:
                sap2 = sap1
            else:
                tmpid = all_saps_ending.pop() if use_saps_once else \
                  rnd.choice(all_saps_ending)
                while True:
                    if tmpid != sap1.id:
                        if tmpid not in nffg:
                            sap2 = nffg.add_sap(id=tmpid)
                        else:
                            sap2 = nffg.network.node[tmpid]
                        break
                    else:
                        tmpid = all_saps_ending.pop() if use_saps_once else \
                          rnd.choice(all_saps_ending)
            sg_path = []
            if len(sap1.ports) > 0:
                for sap1port in sap1.ports:
                    break
            else:
                sap1port = sap1.add_port(id=gen.get_name("port"))
            last_req_port = sap1port
            # generate some VNF-s connecting the two SAP-s
            vnf_cnt = next(gen_seq()) % chain_maxlen + 1
            for vnf in xrange(0, vnf_cnt):
                # in the first case p is used to determine which previous chain should
                # be used to share the VNF, in the latter case it is used to determine
                # whether we should share now.
                p = rnd.random()
                if multiSC and \
                      p < vnf_sharing_probabilty and len(current_nfs) > 0:
                    # this influences the the given VNF sharing probability...
                    if reduce(lambda a, b: a and b,
                              [v in nfs_this_sc for v in current_nfs]):
                        log.warn(
                            "All shareable VNF-s are already added to this chain! "
                            "Skipping VNF sharing...")
                        continue
                    else:
                        nf = rnd.choice(current_nfs)
                        while nf in nfs_this_sc:
                            nf = rnd.choice(current_nfs)
                            # the VNF is already in the subchain, we just need to add the
                            # links
                            # vnf_added = True
                else:
                    nf = nffg.add_nf(id="-".join(
                        ("SC", str(scid), "VNF", str(vnf))),
                                     func_type=rnd.choice(nf_types),
                                     cpu=rnd.random() * max_cpu,
                                     mem=rnd.random() * max_mem,
                                     storage=rnd.random() * max_storage)

                nfs_this_sc.append(nf)
                newport = nf.add_port(id=gen.get_name("port"))
                sglink = nffg.add_sglink(last_req_port,
                                         newport,
                                         id=gen.get_name("link"))
                sg_path.append(sglink.id)
                last_req_port = nf.add_port(id=gen.get_name("port"))

            if len(sap2.ports) > 0:
                for sap2port in sap2.ports:
                    break
            else:
                sap2port = sap2.add_port(id=gen.get_name("port"))
            sglink = nffg.add_sglink(last_req_port,
                                     sap2port,
                                     id=gen.get_name("link"))
            sg_path.append(sglink.id)

            # WARNING: this is completly a wild guess! Failing due to this doesn't
            # necessarily mean algorithm failure
            # Bandwidth maximal random value should be min(SAP1acces_bw,
            # SAP2access_bw)
            # MAYBE: each SAP can only be once in the reqgraph? - this is the case
            # now.
            minlat = avg_shp_len * min_e2e_lat_multiplier
            maxlat = avg_shp_len * max_e2e_lat_multiplier
            nffg.add_req(sap1port,
                         sap2port,
                         delay=rnd.uniform(minlat, maxlat),
                         bandwidth=rnd.random() * max_bw,
                         sg_path=sg_path,
                         id=gen.get_name("req"))
            # log.debug(
            #   "Service Chain on NF-s added: %s" % [nf.id for nf in nfs_this_sc])
            # this prevents loops in the chains and makes new and old NF-s equally
            # preferable in total for NF sharing
            new_nfs = [vnf for vnf in nfs_this_sc if vnf not in current_nfs]
            for tmp in xrange(0, scid + 1):
                current_nfs.extend(new_nfs)
            if not multiSC:
                return nffg
        if multiSC:
            return nffg
    return None
예제 #5
0
def generateRequestForCarrierTopo(test_lvl,
                                  all_saps_beginning,
                                  all_saps_ending,
                                  running_nfs,
                                  loops=False,
                                  use_saps_once=True,
                                  vnf_sharing_probabilty=0.0,
                                  vnf_sharing_same_sg=0.0,
                                  shareable_sg_count=9999999999999999,
                                  multiSC=False,
                                  max_sc_count=2):
    """
  By default generates VNF-disjoint SC-s starting/ending only once in each SAP.
  With the 'loops' option, only loop SC-s are generated.
  'vnf_sharing_probabilty' determines the ratio of 
     #(VNF-s used by at least two SC-s)/#(not shared VNF-s).
  NOTE: some kind of periodicity is included to make the effect of batching 
  visible. But it is (and must be) independent of the batch_length.

  WARNING!! batch_length meaining is changed if --poisson is set!

  Generate exponential arrival time for VNF-s to make Batching more reasonable.
  inter arrival time is Exp(1) so if we are batching for 4 time units, the 
  expected SG count is 4, because the sum of 4 Exp(1) is Exp(4).
  BUT we wait for 1 SG at least, but if by that time 4 units has already passed,
  map the SG alone (unbatched).
  """
    chain_maxlen = 8
    sc_count = 1
    # maximal possible bandwidth for chains
    max_bw = 7.0
    if multiSC:
        sc_count = random.randint(2, max_sc_count)
    while len(all_saps_ending) > sc_count and len(
            all_saps_beginning) > sc_count:
        nffg = NFFG(id="Benchmark-Req-" + str(test_lvl) + "-Piece")
        # newly added NF-s of one request
        current_nfs = []
        for scid in xrange(0, sc_count):
            # find two SAP-s for chain ends.
            nfs_this_sc = []
            sap1 = nffg.add_sap(id = all_saps_beginning.pop() if use_saps_once else \
                                random.choice(all_saps_beginning))
            sap2 = None
            if loops:
                sap2 = sap1
            else:
                tmpid = all_saps_ending.pop() if use_saps_once else \
                        random.choice(all_saps_ending)
                while True:
                    if tmpid != sap1.id:
                        sap2 = nffg.add_sap(id=tmpid)
                        break
                    else:
                        tmpid = all_saps_ending.pop() if use_saps_once else \
                                random.choice(all_saps_ending)
            sg_path = []
            sap1port = sap1.add_port()
            last_req_port = sap1port
            # generate some VNF-s connecting the two SAP-s
            vnf_cnt = next(gen_seq()) % chain_maxlen + 1
            for vnf in xrange(0, vnf_cnt):
                # in the first case p is used to determine which previous chain should
                # be used to share the VNF, in the latter case it is used to determine
                # whether we should share now.
                vnf_added = False
                p = random.random()
                if random.random() < vnf_sharing_probabilty and len(running_nfs) > 0 \
                   and not multiSC:
                    vnf_added, nf = _shareVNFFromEarlierSG(
                        nffg, running_nfs, nfs_this_sc, p)
                elif multiSC and \
                     p < vnf_sharing_probabilty and len(current_nfs) > 0 \
                     and len(running_nfs) > 0:
                    # this influences the the given VNF sharing probability...
                    if reduce(lambda a, b: a and b,
                              [v in nfs_this_sc for v in current_nfs]):
                        log.warn(
                            "All shareable VNF-s are already added to this chain! "
                            "Skipping VNF sharing...")
                    elif random.random() < vnf_sharing_same_sg:
                        nf = random.choice(current_nfs)
                        while nf in nfs_this_sc:
                            nf = random.choice(current_nfs)
                        # the VNF is already in the subchain, we just need to add the links
                        # vnf_added = True
                    else:
                        # this happens when VNF sharing is needed but not with the actual SG
                        vnf_added, nf = _shareVNFFromEarlierSG(
                            nffg, running_nfs, nfs_this_sc, p)
                else:
                    nf = nffg.add_nf(id="-".join(("Test",str(test_lvl),"SC",str(scid),
                                                  "VNF",str(vnf))),
                                     func_type=random.choice(['A','B','C']),
                                     cpu=random.randint(1 + (2 if test_lvl%4 == 3 else 0),
                                                        4 + (6 if test_lvl%4 == 3 else 0)),
                                     mem=random.random()*1000 + \
                                        (1000 if test_lvl%4 > 1 else 0),
                                     storage=random.random()*3 + \
                                        (6 if test_lvl%4 > 1 else 0),
                                     delay=1 + random.random()*10,
                                     bandwidth=random.random())
                    vnf_added = True
                if vnf_added:
                    # add olny the newly added VNF-s, not the shared ones.
                    nfs_this_sc.append(nf)
                    newport = nf.add_port()
                    sglink = nffg.add_sglink(last_req_port, newport)
                    sg_path.append(sglink.id)
                    last_req_port = nf.add_port()

            sap2port = sap2.add_port()
            sglink = nffg.add_sglink(last_req_port, sap2port)
            sg_path.append(sglink.id)

            # WARNING: this is completly a wild guess! Failing due to this doesn't
            # necessarily mean algorithm failure
            # Bandwidth maximal random value should be min(SAP1acces_bw, SAP2access_bw)
            # MAYBE: each SAP can only be once in the reqgraph? - this is the case now.
            if multiSC:
                minlat = 5.0 * (len(nfs_this_sc) + 2)
                maxlat = 13.0 * (len(nfs_this_sc) + 2)
            else:
                # nfcnt = len([i for i in nffg.nfs])
                minlat = 45.0 - 10.0 * (test_lvl % 4)
                maxlat = 60.0 - 12.25 * (test_lvl % 4)
            nffg.add_req(sap1port,
                         sap2port,
                         delay=random.uniform(minlat, maxlat),
                         bandwidth=random.random() * (max_bw + test_lvl % 4),
                         sg_path=sg_path)
            log.info("Service Chain on NF-s added: %s" %
                     [nf.id for nf in nfs_this_sc])
            # this prevents loops in the chains and makes new and old NF-s equally
            # preferable in total for NF sharing
            new_nfs = [vnf for vnf in nfs_this_sc if vnf not in current_nfs]
            for tmp in xrange(0, scid + 1):
                current_nfs.extend(new_nfs)
            if not multiSC:
                return nffg, all_saps_beginning, all_saps_ending
        if multiSC:
            return nffg, all_saps_beginning, all_saps_ending
    return None, all_saps_beginning, all_saps_ending
예제 #6
0
    def getDecomps(self, nffg):
        """
    Get all decompositions for a given nffg.

    : param nffg: the nffg for which the decompositions should be returned
    : type nffg: nffg
    : return: all the decompositions for the given nffg
    : rtype: dict
    """
        decompositions = {}
        nodes_list = []
        index = 0

        for n in nffg.nfs:
            node = list(self.graph_db.find('NF', 'node_id', n.id))
            if len(node) != 0:
                nodes_list.append(node[0])

            else:
                log.debug("NF %s does not exist in the DB" % n.id)
                return None

        queue = deque([nodes_list])
        queue_nffg = deque([nffg])
        while len(queue) > 0:
            nodes = queue.popleft()
            nffg_init = queue_nffg.popleft()
            indicator = 0
            for node in nodes:
                rels_DECOMPOSED = list(
                    self.graph_db.match(start_node=node,
                                        rel_type='DECOMPOSED'))
                for rel in rels_DECOMPOSED:
                    indicator = 1
                    nffg_temp = NFFG()
                    graph, rels = self.getSingleDecomp(
                        rel.end_node.properties['node_id'])

                    for n in graph.nodes():
                        if graph.node[n]['properties']['label'] == 'NF':
                            nffg_temp.add_nf(
                                id=n,
                                dep_type=graph.node[n]['properties']['type'],
                                cpu=graph.node[n]['properties']['cpu'],
                                mem=graph.node[n]['properties']['mem'],
                                storage=graph.node[n]['properties']['storage'])

                        elif graph.node[n]['properties']['label'] == 'SAP':
                            nffg_temp.add_sap(id=n)
                    counter = 0
                    for edge in graph.edges():

                        for nf in nffg_temp.nfs:

                            if nf.id == edge[0]:
                                node0 = nf
                            if nf.id == edge[1]:
                                node1 = nf
                        for sap in nffg_temp.saps:
                            if sap.id == edge[0]:
                                node0 = sap
                            if sap.id == edge[1]:
                                node1 = sap
                        # FIXME - czentye --> There is a chance node0, node1 variables
                        # not defined yet until here and add_port will be raise an exception
                        nffg_temp.add_sglink(
                            node0.add_port(graph.edge[edge[0]][edge[1]]
                                           ['properties']['src_port']),
                            node1.add_port(graph.edge[edge[0]][edge[1]]
                                           ['properties']['dst_port']),
                            id='hop' + str(counter))

                    for n in nffg_init.nfs:
                        nffg_temp.add_node(n)
                    for n in nffg_init.saps:
                        nffg_temp.add_node(n)
                    for n in nffg_init.infras:
                        nffg_temp.add_node(n)
                    for l in nffg_init.links:
                        nffg_temp.add_edge(l.src.node, l.dst.node, l)
                    for l in nffg_init.sg_hops:
                        nffg_temp.add_edge(l.src.node, l.dst.node, l)
                    for l in nffg_init.reqs:
                        nffg_temp.add_edge(l.src.node, l.dst.node, l)

                    extra_nodes = []
                    for l in nffg_temp.sg_hops:
                        if node.properties['node_id'] == l.src.node.id:
                            src_port = l.src
                            dst_port = l.dst

                            for edge in graph.edges():
                                if graph.node[edge[1]]['properties'][
                                        'label'] == 'SAP':

                                    if str(src_port.id) == str(
                                            graph.edge[edge[0]][edge[1]]
                                        ['properties']['dst_port']):

                                        for e in nffg_temp.sg_hops:
                                            if e.src.node.id == edge[
                                                    0] and e.dst.node.id == edge[
                                                        1]:
                                                nffg_temp.add_sglink(
                                                    e.src, dst_port)
                                                extra_nodes.append(edge[1])

                        if node.properties['node_id'] == l.dst.node.id:
                            dst_port = l.dst
                            src_port = l.src

                            for edge in graph.edges():
                                if graph.node[edge[0]]['properties'][
                                        'label'] == 'SAP':

                                    if str(dst_port.id) == str(
                                            graph.edge[edge[0]][edge[1]]
                                        ['properties']['src_port']):
                                        for e in nffg_temp.sg_hops:
                                            if e.src.node.id == edge[
                                                    0] and e.dst.node.id == edge[
                                                        1]:
                                                nffg_temp.add_sglink(
                                                    src_port, e.dst)
                                                extra_nodes.append(edge[0])

                    nffg_temp.del_node(node.properties['node_id'])
                    for extra in extra_nodes:
                        nffg_temp.del_node(extra)
                    queue_nffg.append(nffg_temp)

                    nodes_copy = list(nodes)
                    new_nodes = map(lambda x: x.end_node, rels)
                    nodes_copy.remove(node)
                    queue.append(nodes_copy + new_nodes)
                if indicator == 1:
                    break
            if indicator == 0:
                decompositions['D' + str(index)] = nffg_init
                index += 1

        return decompositions
예제 #7
0
def _constructExampleRequest():
    nffg = NFFG(id="BME-req-001")
    sap0 = nffg.add_sap(name="SAP0", id="sap0")
    sap1 = nffg.add_sap(name="SAP1", id="sap1")

    # add NF requirements.
    # Note: storage is used now for the first time, it comes in with the
    # NodeResource class
    # Note: internal latency is only forwarded to lower layer
    # Note: internal bw is untested yet, even before the NFFG support
    nf0 = nffg.add_nf(id="NF0",
                      name="NetFunc0",
                      func_type='A',
                      cpu=2,
                      mem=2,
                      storage=2,
                      bandwidth=100)
    nf1 = nffg.add_nf(id="NF1",
                      name="NetFunc1",
                      func_type='B',
                      cpu=1.5,
                      mem=1.5,
                      storage=1.5,
                      delay=50)
    nf2 = nffg.add_nf(id="NF2",
                      name="NetFunc2",
                      func_type='C',
                      cpu=3,
                      mem=3,
                      storage=3,
                      bandwidth=500)
    nf3 = nffg.add_nf(id="NF3",
                      name="NetFunc3",
                      func_type='A',
                      cpu=2,
                      mem=2,
                      storage=2,
                      bandwidth=100,
                      delay=50)
    nf4 = nffg.add_nf(id="NF4",
                      name="NetFunc4",
                      func_type='C',
                      cpu=0,
                      mem=0,
                      storage=0,
                      bandwidth=500)

    # directed SG links
    # flowclass default: None, meaning: match all traffic
    # some agreement on flowclass format is required.
    nffg.add_sglink(sap0.add_port(0), nf0.add_port(0))
    nffg.add_sglink(nf0.add_port(1), nf1.add_port(0), flowclass="HTTP")
    nffg.add_sglink(nf1.add_port(1), nf2.add_port(0), flowclass="HTTP")
    nffg.add_sglink(nf2.add_port(1), sap1.add_port(1))
    nffg.add_sglink(nf0.add_port(2), nf3.add_port(0), flowclass="non-HTTP")
    nffg.add_sglink(nf3.add_port(1), nf2.add_port(2), flowclass="non-HTTP")
    nffg.add_sglink(nf1.add_port(2), nf4.add_port(0), flowclass="index.com")
    nffg.add_sglink(nf4.add_port(1), nf2.add_port(3), flowclass="index.com")

    # add EdgeReqs
    nffg.add_req(sap0.ports[0], sap1.ports[1], delay=40, bandwidth=1500)
    nffg.add_req(nf1.ports[1], nf2.ports[0], delay=3.5)
    nffg.add_req(nf3.ports[1], nf2.ports[2], bandwidth=500)
    nffg.add_req(sap0.ports[0], nf0.ports[0], delay=3.0)
    # force collocation of NF0 and NF3
    # nffg.add_req(nf0.ports[2], nf3.ports[0], delay=1.0)
    # not SAP-to-SAP requests are not taken into account yet, these are ignored
    nffg.add_req(nf0.ports[1], nf2.ports[0], delay=1.0)

    # test Infra node removal from the request NFFG
    infra1 = nffg.add_infra(id="BiS-BiS1")
    infra2 = nffg.add_infra(id="BiS-BiS2")
    nffg.add_undirected_link(infra1.add_port(0), nf0.add_port(3), dynamic=True)
    nffg.add_undirected_link(infra1.add_port(1), nf0.add_port(4), dynamic=True)
    nffg.add_undirected_link(infra1.add_port(2), nf1.add_port(3), dynamic=True)
    nffg.add_undirected_link(infra2.add_port(0), nf2.add_port(4), dynamic=True)
    nffg.add_undirected_link(infra2.add_port(1), nf3.add_port(2), dynamic=True)
    nffg.add_undirected_link(infra1.add_port(3),
                             infra2.add_port(2),
                             bandwidth=31241242)

    return nffg