Example #1
0
def checkVNFLoad(vnfSwitches, offLoad):
    swDict = {}
    for sw in vnfSwitches:  # loop through all switches
        if type(sw) == type({}):
            sw = sw['dstHost']

        #print "checkvnfLoad SW %s" % (sw)
        switchObj = switchFinder.findSwitch(sw)
        switchLoad = int(pktMon.getSwitchLoad(s_name=switchObj.name))
        newLoad = int(
            float(switchLoad) +
            (float(abs(offLoad)) * float(1 + float(migrateMargin))))
        #print "checkvnfLoad SW %s has load %i and will get load %i with new NF" % (sw, int(switchLoad), newLoad)
        if float(float(1 - migrateMargin) * switchObj.queueRate) > float(
                newLoad):  # if switch will not be overloading:
            swDict[sw] = {
                'curload': int(switchLoad),
                'newLoad': int(newLoad),
                'maxLoad': int(switchObj.queueRate),
                'newloadNum':
                float(float(newLoad) / float(switchObj.queueRate))
            }

        # order the dict:
    res = OrderedDict(
        sorted(swDict.items(), key=lambda x: getitem(x[1], 'newloadNum')))
    return res
Example #2
0
def startPacketCounter(dstSwName='s3'):
    # this service needs to:
    # - enable code on the switch
    # - write some behaviour to switch that indicates which things to do
    tStart = time.time()

    sw = switchFinder.findSwitch(dstSwName)
    # add vnf to object
    sw.vnfList.append('packetCounter')
    dbConnect.addVNF(vnfName='packetCounter', prio=-10)
    appServices.addService('packetCounter', None) # this function only does this if it doesn't exist
    res = appServices.addServiceSwitch('packetCounter', sw.name)
    if res != True:
        raise Exception("something went wrong for adding a VNF")
    tPacketSetupService = time.time() - tStart
    print "Service proxy started. The whole process took %f seconds" % (tPacketSetupService)
Example #3
0
def startProxyService(dstSwName='s1'):
    # this service needs to:
    # - enable code on a switch
    # - write some rules to the switch to have some behaviour
    # this is the network address translation service that tracks the connections that have to go through the proxy service.
    tStart = time.time()
    sw = switchFinder.findSwitch(dstSwName)
    ruleList = []
    # add any original service rules to the dict. not used now because this is the initializing function, but this may be used in the future
    ruleList.append({
                'origDstIP' : '10.0.1.2',
                'origSrcIP' : '10.0.1.10',
                'newDstIP'  : '10.0.1.20',
                'newMAC'    : '02:00:00:00:02:22'
            }
        )
    ruleList.append({
                'origDstIP' : '10.0.1.2',
                'origSrcIP' : '10.0.1.20',
                'newDstIP'  : '10.0.1.10',
                'newMAC'    : '02:00:00:00:01:11'
            }
        )
    
          
    for rule in ruleList:
        oldDstIP = rule['origDstIP']
        oldSrcIP = rule['origSrcIP']
        newDstIP  = rule['newDstIP']
        newMAC    = rule['newMAC']   
        dbConnect.addProxyStateless(srcIP=oldSrcIP, dstIP=oldDstIP, newDstIP=newDstIP, newDstMAC=newMAC)
        dbConnect.addVNF(vnfName='proxyStateless', srcIP=oldSrcIP, dstIP=oldDstIP)

    # initialize one instance on switch s3:
    appServices.addService('proxyStateless', None)
    appServices.addServiceSwitch('proxyStateless', sw.name)

    # add vnf to object
    sw.vnfList.append('proxyStateless')
    
    tProxySetupService = time.time() - tStart
    print "Service proxy started. The whole process took %f seconds" % (tProxySetupService)

    return
Example #4
0
def checkSwitches(srcSw, migrate=False):
    # the flow volume that has to be offloaded to stop overloading the switch
    swLoad = float(pktMon.getSwitchLoad(s_name=srcSw.name))
    offLoad = abs(
        int(swLoad -
            int(float(srcSw.queueRate) *
                float(1 - float(migrateMargin)))))  # absolute...
    print("We will need to offload %s from the current load of %s" %
          (int(offLoad), int(swLoad)))
    # check all VNFS that run on the switch: If one solution has been found, redistributing load is feasible and that particular VNF
    for vnf in srcSw.vnfList:
        if migrate == False:
            vnfSwitches = getRebalanceOptions(str(vnf))
        else:
            vnfSwitches = getMigrationOptions(str(vnf))
        #print ("vnfswitches: %s" % (str(vnfSwitches)))
        if str(srcSw.name) in vnfSwitches:
            vnfSwitches.remove(srcSw.name)
        if len(vnfSwitches) < 1:
            # only one VNF running... definately no migration
            continue
        #orders the switches that could handle the load, from low load to high load.
        swDict = checkVNFLoad(vnfSwitches=vnfSwitches, offLoad=offLoad)
        #print swDict
        for swName, swDict in swDict.items():
            if swName == srcSw.name:
                # not much use for this...
                continue
            #print "Checking to offload NF %s from %s to switch %s" %(vnf, srcSw.name, swName)
            dstSw = switchFinder.findSwitch(swName)
            flowIDList = checkRedistributeSwitchLoad(srcSw=srcSw,
                                                     dstSw=dstSw,
                                                     offLoad=offLoad,
                                                     vnf=vnf)
            print "flowIDlist = %s" % str(flowIDList)
            if len(flowIDList) > 0:
                return (flowIDList, dstSw, flowIDList, vnf)
    return False, False, False, False
Example #5
0
def installLabelPath(path, pkt, firstSwitch, lastSwitch, sequence):
    if path == None:
        # find out if source and destination are hosts:
        # TODO this only works for host<=> host communications.
        raise Exception("Path None can't have a shortes route")

    if pkt.flowID == None:
        raise Exception(
            "Flowid with id None can't be processed by installLabelPathFunction"
        )

    # find services for flowID
    i = path.index(lastSwitch)
    while i >= 0:
        if netGraph.getHostAttr(path[i], "type") == "switch":
            s = switchFinder.findSwitch(path[i])
            installRules = []

            if s is not None:
                # do routing only if the path doesn't end with a switch. Do this until the last switch.
                # This packet will send a new packetin when it has finished processing the packet.
                # doe als:

                if s.name != lastSwitch or path[-1] != str(lastSwitch):
                    #if s.name is not lastSwitch:
                    #print "installing route_flowID rule on switch %s" % s.name
                    installRule = {}
                    installRule["default_action"] = False
                    installRule["table_name"] = "route_flowID_tbl"
                    installRule["match_fields"] = {
                        "flowID.flowID": int(pkt.flowID),
                    }
                    installRule["action_name"] = "route_flowID"
                    installRule["action_params"] = {
                        "outPort":
                        int(
                            netGraph.getLinkProperties(path[i],
                                                       path[i + 1])["port"])
                    }
                    installRules.append(installRule)

                # only install this last rule when switching to a real destination host. Otherwise packetins don't work
                if (s.name == str(firstSwitch)) and (
                        sequence == 0
                ):  # lastswitch bit added for single length paths. Is shouldn't set the flowID again.
                    #print "installing set_flowID rule on switch %s" % s.name
                    installRule = {}
                    installRule["default_action"] = False
                    installRule["table_name"] = "set_flowID_tbl"
                    installRule["match_fields"] = {
                        "ipv4.srcAddr": pkt.srcIP,
                        "ipv4.dstAddr": pkt.dstIP,
                        "ipv4.protocol": pkt.ip.p,
                        "port_metadata.srcPort": pkt.srcPort,
                        "port_metadata.dstPort": pkt.dstPort
                    }
                    installRule["action_name"] = "set_flowID"
                    installRule["action_params"] = {"flowid": pkt.flowID}

                    installRules.append(installRule)
                # if the last step in the path is the last switch, do not install the last forwarding rule.
                if (s.name
                        == str(lastSwitch)) and (path[-1] != str(lastSwitch)):
                    #print "installing remove_flowID rule on switch %s" % s.name
                    installRule = {}
                    installRule["default_action"] = False
                    installRule["table_name"] = "remove_flowID_tbl"
                    installRule["match_fields"] = {
                        "flowID.flowID": int(pkt.flowID)
                    }
                    installRule["action_name"] = "remove_flowID"
                    installRule["action_params"] = {}
                    installRules.append(installRule)
            # at the end of this, install all rules to the switch
            s.installRulesOnSwitch(installRules)
        i -= 1

    return True
Example #6
0
    def processMigPkt(self, msg):
        sleep(self.controlPlaneDelay)
        ts = time()
        #print "Pkt received from %s %s" % (self.name, msg.packet.payload.encode('hex'))
        try:
            idHdr = str(msg.packet.payload.encode('hex')[0:4])
            migFlowID = int(msg.packet.payload.encode('hex')[4:12], 16)
            subProtocol = str(msg.packet.payload.encode('hex')[12:14])
            sequenceID = int(msg.packet.payload.encode('hex')[14:18], 16)
            intVNFID = int(msg.packet.payload.encode('hex')[18:20], 16)
            sessionID = int(msg.packet.payload.encode('hex')[20:22], 16)
            flowID = int(msg.packet.payload.encode('hex')[22:30], 16)
        except:
            print 'error in packetpayload:'
            print msg.packet.payload.encode('hex')
        if subProtocol == 'aa' or subProtocol == '55':
            print "pkt is: %s" % msg.packet.payload.encode('hex')
            ts_u = int(msg.packet.payload.encode('hex')[-12], 16)
            pktMon.addMigPktReading(s_name=self.name,
                                    sequenceID=sequenceID,
                                    VNFID=intVNFID,
                                    sessionID=sessionID,
                                    flowID=flowID,
                                    ts_u=ts_u)
            # add logging rule to logDB
            #dbConnect.addFlowLog(flowID=flowID, ts=ts_u, recvSw=self.name, sequenceID=sequenceID, VNFID=intVNFID, subProtocol=subProtocol)

            print "Timingrommel ontvangen (%s), ts: %s!" % (subProtocol,
                                                            str(ts_u))
            # get the flowStatus. If the '3c' packet has been missed,

        elif subProtocol == '3c':  # acceptflow packet from migration destination
            print """
            Initial sync completed.
            Sync process is in update phase, where the migration destination is updated.

            Now change to 'forward' state. 
            This will cause the secondary switch to process the packets.
            State updates will not be accepted anymore for this flow.
            """

            # This is an initial sync packet
            # Now signal the migration destination switch that we can switch to the forward phase.
            # put the corresponding transmission algorithm into the next phase
            result = dbConnect.getMigSrcSw(flowID=flowID, VNFID=intVNFID)
            if result == None:
                print 'error getting dstSw, nothing returned from query %s' % str(
                    result)
                return
            if 'dstHost' not in result:
                print 'Error getting dstSw!'
                print result
                return
            srcSw = switchFinder.findSwitch(result['dstHost'])
            pktMon.addNewMigrationLine(srcSw=srcSw.name,
                                       dstSw=self.name,
                                       ts=ts,
                                       phase=15,
                                       flowID=flowID)
            # spawn a new thread that
            # 1. waits for the rule installation to be complete
            # 2. kicks the process to the flowhandler state
            # immediately go to new state.
            t = threading.Thread(target=flowHandler.flowMigratetoForwardPhase,
                                 args=(srcSw, self, flowID, intVNFID))
            t.start()
        elif subProtocol == 'ff' or subProtocol == '3f':
            # this is an ack for the forwardflow state.

            print """
            Update phase completed (ack received from srcSrcSw).
            Now install the remaining path to divert traffic from migsrc to migdst immediately,
            and therefore releaving migsrc.
            Keep hanging 1 second after the process to prevent excessive migrations
            """
            dstSwName = dbConnect.searchFlowMigrateDstHost(flowID=flowID,
                                                           srcSw=self.name)
            if dstSwName == None:
                return
            srcSw = switchFinder.findSwitch(dstSwName)
            pktMon.addNewMigrationLine(srcSw=srcSw.name,
                                       dstSw=dstSwName,
                                       ts=ts,
                                       phase=30,
                                       flowID=flowID)
            t = threading.Thread(target=flowHandler.flowMigrateFinish,
                                 args=(self, dstSwName, flowID, intVNFID))
            t.start()
Example #7
0
    def processpacketIn(self, pkt):
        # print "Packetin received from switch %s" % self.name
        # print "packet: %s" % (str(pkt.payload.encode('hex')))
        h, flowID = getHash(srcIP=pkt.srcIP,
                            dstIP=pkt.dstIP,
                            srcPort=pkt.srcPort,
                            dstPort=pkt.dstPort,
                            ipProto=pkt.ip.p,
                            srcHost=self.name)

        if h[-1] == True or str(h[-1]) == str(self.name):
            # packet does not yet exist, do everything
            doServices = False

            if pkt.flowID == None:
                pkt.flowID = int(random.getrandbits(30))
                # if applicable, add hosts to the graph
                pkt.addLinktoGraph()

            # check whether this flow should go through a VNF.
            VNF = flowHandler.getService(srcMAC=pkt.srcMAC,
                                         dstMAC=pkt.dstMAC,
                                         srcIP=pkt.srcIP,
                                         srcPort=pkt.srcPort,
                                         dstIP=pkt.dstIP,
                                         dstPort=pkt.dstPort,
                                         protocol=pkt.ip.p)
            VNFList = dbConnect.getFlowVNFS(srcIP=pkt.srcIP,
                                            dstIP=pkt.dstIP,
                                            srcPort=pkt.srcPort,
                                            dstPort=pkt.dstPort,
                                            ipProtocol=pkt.ip.p)
            processedVNFList = dbConnect.searchVNFSbyFlow(flowID=pkt.flowID)

            VNF = None
            # search the first NF that has to be processed now:
            for vnf in VNFList:
                if vnf['vnfName'] not in processedVNFList:
                    VNF = vnf['vnfName']
                    break

            # check which actions already are assigned to flow (and which are already processed):
            # change destination and install service to switch
            if VNF == 'proxyStateless':
                print 'we have a proxystateless machine!!!'
                # We have a packet that has to be processed by the proxy before it goes to its destination.
                dstSw = flowHandler.assignService(VNF)
                # install service on dstSw
                # TODO
                switchFinder.findSwitch(dstSw).installVNF(pkt=pkt, VNF=VNF)
                # calculate a new path for the packet to the assigned switch: do not remove flowID at the last switch
                pkt.realDstHost = dstSw
            elif VNF == 'packetCounter':
                # do packetcounter
                #print 'do packetcounter'
                dstSw = flowHandler.assignService(VNF)
                switchFinder.findSwitch(dstSw).installVNF(pkt=pkt, VNF=VNF)
                pkt.realDstHost = dstSw
            elif VNF == None:
                pkt.realDstHost = pkt.dstMAC

            # calculate the path from the current location of the packet (the receiving switch) to the destination
            path = findRoute(pkt.recv_sw, pkt.realDstHost)
            if path == []:
                print "iets foutgegaan in berekenen route"
                removeHash(srcIP=pkt.srcIP,
                           dstIP=pkt.dstIP,
                           srcPort=pkt.srcPort,
                           dstPort=pkt.dstPort,
                           ipProto=pkt.ip.p,
                           srcHost=self.name)
                return

            # path has been found.
            firstSwitch = pathFindFirstSwitch(path)
            lastSwitch = pathFindLastSwitch(path)
            #print 'lastswitch is: %s' % str(lastSwitch)
            if lastSwitch != None and str(lastSwitch) != 'None':
                updateHash(srcIP=pkt.srcIP,
                           dstIP=pkt.dstIP,
                           srcPort=pkt.srcPort,
                           dstPort=pkt.dstPort,
                           ipProto=pkt.ip.p,
                           srcHost=self.name,
                           dstHost=lastSwitch,
                           flowID=int(pkt.flowID))
            # get flow infromation. If no result is shown, generate a new flowID and add it to the database
            # flow is distinguished based on following fields
            # srcHost
            # srcPort
            # ipv4 protocol
            # dstHost
            # dstPort

            if pkt.flowID is not None:
                flowInfo = dbConnect.searchFlowTable(flowID=pkt.flowID,
                                                     srcIP=pkt.srcIP,
                                                     srcPort=pkt.srcPort,
                                                     ipProtocol=pkt.ip.p,
                                                     dstIP=pkt.dstIP,
                                                     dstPort=pkt.dstPort,
                                                     vnf=VNF)

            if len(flowInfo) == 0:
                # add new entry. this one is not correct:
                print "Packet with new flowID %s" % (pkt.flowID)
                # add the new flow to the table:
                sequence = dbConnect.addFlowTableEntry(flowID=str(pkt.flowID),
                                                       srcHost=str(path[0]),
                                                       dstHost=str(path[-1]),
                                                       vnf=str(VNF),
                                                       srcIP=pkt.srcIP,
                                                       srcPort=pkt.srcPort,
                                                       ipProtocol=pkt.ip.p,
                                                       dstIP=pkt.dstIP,
                                                       dstPort=pkt.dstPort)
            else:
                sequence = flowInfo[0]['sequence']
            # install path
            #print path
            installStatus = flowHandler.installLabelPath(
                path=path,
                pkt=pkt,
                firstSwitch=str(firstSwitch),
                lastSwitch=str(lastSwitch),
                sequence=sequence)

            if installStatus == False:
                print "installing path failed somewhere."
                removeHash(srcIP=pkt.srcIP,
                           dstIP=pkt.dstIP,
                           srcPort=pkt.srcPort,
                           dstPort=pkt.dstPort,
                           ipProto=pkt.ip.p,
                           srcHost=self.name)
                return
            if lastSwitch != None:
                lastSw = switchFinder.findSwitch(lastSwitch)
            flowID = int(pkt.flowID)
        elif h != False:
            # packet already exists. send the packet to the destination.
            lastSw = switchFinder.findSwitch(h[-1])
            flowID = flowID
        else:
            h = [False]  #beunbeunbeun
            while (h[-1] == False or str(h[-1]) == str(self.name)):
                # buffer this packet until h != false anymore
                print 'Packet buffered!%s' % (str(h))
                h, flowID = getHash(srcIP=pkt.srcIP,
                                    dstIP=pkt.dstIP,
                                    srcPort=pkt.srcPort,
                                    dstPort=pkt.dstPort,
                                    ipProto=pkt.ip.p,
                                    srcHost=self.name)
                if type(h) == type(None):
                    h = [False]
            lastSw = switchFinder.findSwitch(h)
            flowID = flowID

            # print("poblempaket!")
            # print('h: %s' % str(h))
            # print('flowID: %s' % str(flowID))
            # print pkt.payload.encode('hex')
            # lastSw = None
        # send packetOut
        if lastSw != None and flowID != False:
            lastSw.sendPacketOutLabel(pkt.payload[:14] + pkt.payload[16:],
                                      int(flowID))