Exemplo n.º 1
0
    def routeViroPacket(self, pkt, inport=None):
        """ Route the viro packet closer to destination """

        dst_pkt = VidAddr(pkt.dst.sw, 0x00)

        if (dst_pkt == self.sw.vid):
            # consume the packet since its sent to me
            self.processViroPacket(pkt, inport)
            return

        if pkt.effective_ethertype == viroctrl.VIRO_CTRL_TYPE:
            op = pkt.payload.op
            nexthop, port = self.routing.getNextHop(dst_pkt, op)
        else:
            nexthop, port = self.routing.getNextHop(dst_pkt)

        if nexthop != None:
            msg = msgFactory.packetOut(pkt, port)
            self.sw.connection.send(msg)
        else:
            log.debug("routeViroPacket nexthop not found")

        # use for handling data packets
        if inport:
            return port
Exemplo n.º 2
0
    def processCtrlPacket(self, viropkt, inport):
        """ Comsume a viro control packet """
        ctrlpkt = viropkt.payload

        if ctrlpkt.op == viroctrl.DISC_ECHO_REQ:
            self.numOfVIRO_DISC_ECHO_REQ = self.numOfVIRO_DISC_ECHO_REQ + 1
            logging.info("VIRO_DISC_ECHO_REQ " +
                         str(self.numOfVIRO_DISC_ECHO_REQ) + " " +
                         str(time.time()) + " R")

            echo = ctrlpkt.payload
            nvid = viropkt.src

            reply = pktFactory.discoverEchoReply(self.sw.vid, nvid)
            self.numOfVIRO_DISC_ECHO_REPLY_SENT = self.numOfVIRO_DISC_ECHO_REPLY_SENT + 1
            logging.info("VIRO_DISC_ECHO_REPLY " +
                         str(self.numOfVIRO_DISC_ECHO_REPLY_SENT) + " " +
                         str(time.time()) + " S")
            msg = msgFactory.packetOut(reply, inport)

            self.sw.connection.send(msg)
            log.debug("Neighbor discovery reply sent")

            return

        elif ctrlpkt.op == viroctrl.DISC_ECHO_REPLY:
            self.numOfVIRO_DISC_ECHO_REPLY = self.numOfVIRO_DISC_ECHO_REPLY + 1
            logging.info("VIRO_DISC_ECHO_REPLY " +
                         str(self.numOfVIRO_DISC_ECHO_REPLY) + " " +
                         str(time.time()) + " R")

            nvid = viropkt.src
            self.routing.discoveryEchoReplyReceived(nvid, inport)

            return

        if not viropkt.dst == self.sw.vid:
            # forward the control packet since its not for me
            self.routeViroPacket(viropkt)
            return

        # handle viro routing packets i.e. publish, query, etc.
        if ctrlpkt.op == viroctrl.RDV_PUBLISH:
            self.numOfVIRO_RDV_PUBLISH = self.numOfVIRO_RDV_PUBLISH + 1
            logging.info("VIRO_RDV_PUBLISH " +
                         str(self.numOfVIRO_RDV_PUBLISH) + " " +
                         str(time.time()) + " R")

            nexthop = ctrlpkt.payload.vid
            svid = viropkt.src
            log.debug("RDV_PUBLISH message received from: ".format(str(svid)))

            dist = self.sw.vid.delta(nexthop)
            self.routing.rdvStore.addRdvPoint(dist, svid, nexthop)

        elif ctrlpkt.op == viroctrl.RDV_QUERY:
            self.numOfVIRO_RDV_QUERY = self.numOfVIRO_RDV_QUERY + 1
            logging.info("VIRO_RDV_QUERY " + str(self.numOfVIRO_RDV_QUERY) +
                         " " + str(time.time()) + " R")

            log.debug("RDV_QUERY message received")
            src = viropkt.src
            if src == self.sw.vid:
                log.debug("I am the rdv point - processing the packet")
                self.routing.selfRVDQuery(src, ctrlpkt.payload.bucket_dist)
            else:
                svid = viropkt.src
                k = ctrlpkt.payload.bucket_dist
                log.debug("RDV_QUERY message received from: {}".format(svid))

                # search in rdv store for the logically closest gateway to reach kth distance away neighbor
                gw = self.routing.rdvStore.findAGW(k, svid)

                # if found then form the reply packet and send to svid
                if not gw:
                    # No gateway found
                    log.debug(
                        'Node : {} has no gateway for the rdv_query packet to reach bucket: {} for node: {}'
                        .format(self.sw.vid, k, svid))
                    return

                # create a RDV_REPLY packet and send it
                rvdReplyPacket = pktFactory.rdvReply(self.sw.vid, svid, k, gw)

                # Keeps track of the Nodes that requests each Gateways at specific level
                nh = self.routing.rdvStore.findNextHop(
                    gw, k)  # nexthop associated with the selected gateway
                self.routing.rdvRequestTracker[gw][svid] = nh

                self.numOfVIRO_RDV_REPLY_SENT = self.numOfVIRO_RDV_REPLY_SENT + 1
                logging.info("VIRO_RDV_REPLY " +
                             str(self.numOfVIRO_RDV_REPLY_SENT) + " " +
                             str(time.time()) + " S")

                msg = msgFactory.packetOut(rvdReplyPacket, inport)
                self.sw.connection.send(msg)
                log.debug("RDV_REPLY message sent")

        elif ctrlpkt.op == viroctrl.RDV_REPLY:
            self.numOfVIRO_RDV_REPLY = self.numOfVIRO_RDV_REPLY + 1
            logging.info("VIRO_RDV_REPLY " + str(self.numOfVIRO_RDV_REPLY) +
                         " " + str(time.time()) + " R")

            log.debug("RDV_REPLY message received")
            # Fill my routing table using this new information
            rtbl = self.routing.routingTable
            gw = ctrlpkt.payload.gw
            k = ctrlpkt.payload.bucket_dist

            if k in self.routing.routingTable:
                log.debug(
                    'Node {} has already have an entry to reach neighbors at distance - {}'
                    .format(self.sw.vid, k))
                return

            dist = self.sw.vid.delta(gw)
            if dist not in rtbl:
                log.debug('ERROR: no nexthop found for the gateway: {}'.format(
                    str(gw)))
                return

            bucket = rtbl[dist].iterkeys().next()
            nexthop = bucket.nexthop
            port = bucket.port

            bucket = Bucket(k, nexthop, gw, port)
            rtbl.addBucket(bucket)

        elif ctrlpkt.op == viroctrl.RDV_WITHDRAW:
            self.numOfVIRO_RDV_WITHDRAW = self.numOfVIRO_RDV_WITHDRAW + 1
            logging.info("VIRO_RDV_WITHDRAW " +
                         str(self.numOfVIRO_RDV_WITHDRAW) + " " +
                         str(time.time()) + " R")

            #log.debug('RDV_WITHDRAW message received from: {}'.format())
            svid = viropkt.src
            gw = ctrlpkt.payload.gw
            k = ctrlpkt.payload.bucket_dist

            log.debug('RDV_WITHDRAW message received from: {} for gateway: {}'.
                      format(svid, gw))
            self.routing.rdvWithDraw(svid, gw)

            # Sends Remove Gateway messages to the appropriated nodes
            if gw in self.routing.rdvRequestTracker:
                for dst in self.routing.rdvRequestTracker[gw]:
                    # Sends the GW_WITHDRAW message to nodes
                    pkt = pktFactory.gatewayWithdraw(self.sw.vid, dst, gw)
                    nexthop, port = self.routing.getNextHop(dst)

                    if nexthop:
                        self.numOfVIRO_GW_WITHDRAW_SENT = self.numOfVIRO_GW_WITHDRAW_SENT + 1
                        logging.info("VIRO_GW_WITHDRAW " +
                                     str(self.numOfVIRO_GW_WITHDRAW_SENT) +
                                     " " + str(time.time()) + " S")

                        log.debug(
                            'Sending GW_WITHDRAW message received from: {} to destination: {}'
                            .format(self.sw.vid, dst))
                        self.routeViroPacket(pkt)
                    else:
                        log.debug("No next hop found!")

                # delete the failed gateway from the rdvRequestTracker - House Keeping
                del self.routing.rdvRequestTracker[gw]
                log.debug(
                    'Removed the failed gateway: {} from rvd request-tracker'.
                    format(gw))

            # Remove all the Gateways using the "failed node" as nexthop (Fixme! simply this code)
            gw_entries = self.routing.rdvStore.findGWByNextHop(
                gw)  # list of gateways using "failed node" as its nexthop

            delete_entries = []

            for gw_other in gw_entries:
                for dst in self.routing.rdvRequestTracker[gw_other]:

                    if self.routing.rdvRequestTracker[gw_other][dst] == gw:
                        # Sends the GW_WITHDRAW message to nodes
                        pkt = pktFactory.gatewayWithdraw(
                            self.sw.vid, dst, gw_other)
                        nexthop, port = self.routing.getNextHop(dst)

                        if nexthop:
                            self.numOfVIRO_GW_WITHDRAW_SENT = self.numOfVIRO_GW_WITHDRAW_SENT + 1
                            logging.info("VIRO_GW_WITHDRAW " +
                                         str(self.numOfVIRO_GW_WITHDRAW_SENT) +
                                         " " + str(time.time()) + " S")

                            log.debug(
                                'Sending GW_WITHDRAW message received from: {} to destination: {}'
                                .format(self.sw.vid, dst))
                            self.routeViroPacket(pkt)
                        else:
                            log.debug("No next hop found!")

                        delete_entries.append((gw_other, dst))

                        # deleting entry from the RDVStore
                        self.routing.rdvStore.deleteGatewayPerNextHop(
                            gw_other, gw)
                        log.debug(
                            'Removed the failed gateway entry: {} from RDVStore per level'
                            .format(gw_other))

            # delete any remaining gateway using the failed nexthop - House Keeping
            self.routing.rdvStore.deleteGatewayForNextHop(gw)

            # delete the failed gateway entry from the rdvRequestTracker - House Keeping
            for gw_other, dst in delete_entries:
                del self.routing.rdvRequestTracker[gw_other][dst]

                log.debug(
                    'Removed the failed gateway entry: {} from rvd request-tracker'
                    .format(gw_other))

        elif ctrlpkt.op == viroctrl.GW_WITHDRAW:
            self.numOfVIRO_GW_WITHDRAW = self.numOfVIRO_GW_WITHDRAW + 1
            logging.info("VIRO_GW_WITHDRAW " +
                         str(self.numOfVIRO_GW_WITHDRAW) + " " +
                         str(time.time()) + " R")

            failed_gw = ctrlpkt.payload.failed_gw
            log.debug(
                'Received Gateway Withdraw for node: {}'.format(failed_gw))
            self.routing.removeFailedNode(failed_gw)
Exemplo n.º 3
0
    def _handle_ViroPacketInIP(self, event):

        IPv4_frame = event.packet
        inport = event.port
        IPv4pkt = IPv4_frame.payload  # Ip packet payload

        log.debug(
            "IPv4 packet in_port=%d, srcvid=%s, dstvid=%s, type=%#04x",
            inport,
            IPv4_frame.src,
            IPv4_frame.dst,
            IPv4_frame.type,
        )

        # Is it to us? (eg. not a DHCP packet)
        if isinstance(IPv4pkt, pkt.dhcp):
            log.debug("%s: packet is a DHCP: it is not for us",
                      str(event.connection))
            return

        # obtain the frame header info.
        srcMac = IPv4_frame.src
        dstMac = IPv4_frame.dst
        ethtype = IPv4_frame.type
        ipv4 = IPv4pkt.srcip

        log.debug("This is the ipv4 packet: {}".format(ipv4))

        n = dstMac.toRaw()
        dst_sw, dst_host = self.sw.vid.getSWHost(n)
        dst_vid = VidAddr(dst_sw, dst_host)

        # find src and dst host objects
        #dist_host = self.local_topo.findHostByVid(dst_vid)
        dist_host = self.local_topo.findHostByMac(dstMac)
        local_host = self.local_topo.findHostByMac(srcMac)

        # if local host does not exist in our topology
        # send a vid request to the remote controller
        # Drop the IPv4 pkts
        if local_host == None:
            packet = pktFactory.vidRequest(srcMac, ipv4, inport)
            msg = msgFactory.controllerEcho(LocalViro.RemoteViro_CONTROLLER_ID,
                                            packet)
            self.sw.connection.send(msg)

            log.debug("Sending a Vid Request pkt to the remote controller")
            return

        # obtain the src VidAddress
        src_vid = local_host.vid

        if dist_host != None:
            ###### Handling packets to src and dst in the same switch ######
            log.debug("src and dst attached to the same switch!")

            lport = dist_host.port
            #dst_mac = dist_host.mac
            #etherpkt = event.packet

            # set the destination macAddress and the source vid
            #etherpkt.src = src_vid.to_raw()
            #etherpkt.dst = dst_mac

            log.debug("forwarding the packet to the next host")
            msg = msgFactory.packetOut(IPv4_frame, lport)
            self.sw.connection.send(msg)

            #---------------------------------------------
            # Add a rule to the switch for future packets
            #---------------------------------------------
            log.debug("pushing the rules to the switch")
            #msg = msgFactory.rewriteMac(src_vid, dstMac, dst_mac, lport)

            # Pushing the rule in both directons
            # a) src --> dst
            msg = msgFactory.rewriteMac(srcMac, dstMac, lport)
            self.sw.connection.send(msg)

            # b) dst --> src
            msg = msgFactory.rewriteMac(dstMac, srcMac, inport)
            self.sw.connection.send(msg)

            return

        else:

            ###### Handling packets to src and dst in different switch ######
            log.debug("Converting IPv4pkts to Viropkts")

            # Generates a Viropkt frame and route it
            log.debug('VidAddress parameters - Src: {} , Dst: {}'.format(
                src_vid, dst_vid))

            viropkt = pktFactory.ViroPacket(src_vid, dst_vid, None, ethtype,
                                            IPv4pkt)
            self.routeViroPacket(viropkt, True)

            log.debug("routing Viro packets")

            #---------------------------------------------
            # Add a rule to the switch for future packets
            #---------------------------------------------
            # log.debug("Port is {}".format(outport))
            msg = msgFactory.encapsulate(srcMac, src_vid, dstMac, dst_vid)
            self.sw.connection.send(msg)

            return
Exemplo n.º 4
0
    def processDataPacket(self, viropkt, inport):
        """ Process a VIRO data packet """
        # 1.proces the packet
        # 2. Add a rule to the switch to match future requests
        # 3. Need to check if I am the destination of the packet
        # If so remove the forwarding directive, replace the
        # Vid with the mac address with the client mac address and forward
        # the packet to the host: I need to save to which port the client is
        # connected to

        dst = viropkt.dst
        src = viropkt.src
        dst_pkt = VidAddr(dst.sw, 0x00)

        if dst_pkt == self.sw.vid:

            # I am the destination for the packet:
            # converting a Viropkt frame to ethernet frame

            log.debug("Destination VID: {}   myVid: {}".format(
                dst, self.sw.vid))
            datapkt = viropkt.payload
            local_host = self.local_topo.findHostByVid(dst)

            if local_host == None:
                log.debug(
                    "Unknown destination Vid to hosts attached to this switch!"
                )
                return

            srcMac = src.to_raw()
            dstMac = local_host.mac
            lport = local_host.port
            type = viropkt.effective_ethertype

            # Generates a internet frame and route it
            etherpkt = pktFactory.ethernetPkt(type, srcMac, dstMac, datapkt)
            msg = msgFactory.packetOut(etherpkt, lport)
            self.sw.connection.send(msg)

            log.debug("Sending data packets to local hosts")

            #---------------------------------------------
            # Add a rule to the switch for future packets
            #---------------------------------------------
            msg = msgFactory.decapsulate(dstMac, dst, lport)
            self.sw.connection.send(msg)

            return

        else:

            # Viropkt is not for us then route it!
            port = self.routeViroPacket(viropkt)

            #---------------------------------------------
            # Add a rule to the switch for future packets
            #---------------------------------------------
            level = self.sw.vid.delta(dst_pkt)
            prefix = self.sw.vid.bucketPrefix(level)
            dst_vid = int(prefix.replace("*", "0"), 2)
            dst_vid_mask = int(prefix.replace("0", "1").replace("*", "0"), 2)

            msg = msgFactory.pushRoutingTable(dst_vid, dst_vid_mask, port)
            self.sw.connection.send(msg)

            msg = msgFactory.pushRoutingTableETH(dst_vid, dst_vid_mask, port)
            self.sw.connection.send(msg)

            return
Exemplo n.º 5
0
    def processCtrlPacket(self, viropkt, inport):
        """ Comsume a viro control packet """
        ctrlpkt = viropkt.payload

        if ctrlpkt.op == viroctrl.DISC_ECHO_REQ:
            echo = ctrlpkt.payload
            nvid = viropkt.src

            reply = pktFactory.discoverEchoReply(self.sw.vid, nvid)
            msg = msgFactory.packetOut(reply, inport)

            self.sw.connection.send(msg)
            log.debug("Neighbor discovery reply sent")

            return

        elif ctrlpkt.op == viroctrl.DISC_ECHO_REPLY:
            nvid = viropkt.src
            self.routing.discoveryEchoReplyReceived(nvid, inport)

            return

        if not viropkt.dst == self.sw.vid:
            # forward the control packet since its not for me
            self.routeViroPacket(viropkt)
            return

        # handle viro routing packets i.e. publish, query, etc.
        if ctrlpkt.op == viroctrl.RDV_PUBLISH:
            nexthop = ctrlpkt.payload.vid
            svid = viropkt.src
            log.debug("RDV_PUBLISH message received from: ".format(str(svid)))

            dist = self.sw.vid.delta(nexthop)
            self.routing.rdvStore.addRdvPoint(dist, svid, nexthop)

        elif ctrlpkt.op == viroctrl.RDV_QUERY:
            log.debug("RDV_QUERY message received")
            src = viropkt.src
            if src == self.sw.vid:
                log.debug("I am the rdv point - processing the packet")
                self.routing.selfRVDQuery(src, ctrlpkt.payload.bucket_dist)
            else:
                svid = viropkt.src
                k = ctrlpkt.payload.bucket_dist
                log.debug("RDV_QUERY message received from: {}".format(svid))

                # search in rdv store for the logically closest gateway to reach kth distance away neighbor
                gw = self.routing.rdvStore.findAGW(k, svid)

                # if found then form the reply packet and send to svid
                if not gw:
                    # No gateway found
                    log.debug(
                        'Node : {} has no gateway for the rdv_query packet to reach bucket: {} for node: {}'
                        .format(self.sw.vid, k, svid))
                    return

                # create a RDV_REPLY packet and send it
                rvdReplyPacket = pktFactory.rdvReply(self.sw.vid, svid, k, gw)

                # Keeps track of the Nodes that requests each Gateways at specific level
                self.routing.rdvRequestTracker[gw][svid] = True

                msg = msgFactory.packetOut(rvdReplyPacket, inport)
                self.sw.connection.send(msg)
                log.debug("RDV_REPLY message sent")

        elif ctrlpkt.op == viroctrl.RDV_REPLY:
            # Fill my routing table using this new information
            rtbl = self.routing.routingTable
            gw = ctrlpkt.payload.gw
            k = ctrlpkt.payload.bucket_dist

            if k in self.routing.routingTable:
                log.debug(
                    'Node {} has already have an entry to reach neighbors at distance - {}'
                    .format(self.sw.vid, k))
                return

            dist = self.sw.vid.delta(gw)
            if dist not in rtbl:
                log.debug('ERROR: no nexthop found for the gateway: {}'.format(
                    str(gw)))
                return

            bucket = rtbl[dist].iterkeys().next()
            nexthop = bucket.nexthop
            port = bucket.port

            bucket = Bucket(k, nexthop, gw, port)
            rtbl.addBucket(bucket)

        elif ctrlpkt.op == viroctrl.RDV_WITHDRAW:
            #log.debug('RDV_WITHDRAW message received from: {}'.format())
            svid = viropkt.src
            gw = ctrlpkt.payload.failed_node

            log.debug('RDV_WITHDRAW message received from: {} for gateway: {}'.
                      format(svid, gw))
            self.routing.rdvWithDraw(svid, gw)

            # Sends Remove Gateway messages to the appropriated nodes
            if gw in self.routing.rdvRequestTracker:
                for dst in self.routing.rdvRequestTracker[gw]:
                    # Sends the GW_WITHDRAW message to nodes
                    pkt = pktFactory.gatewayWithdraw(self.sw.vid, dst, gw)
                    nexthop, port = self.routing.getNextHop(dst)

                    if nexthop:
                        log.debug(
                            'Sending GW_WITHDRAW message received from: {} to gateway: {}'
                            .format(self.sw.vid, dst))
                        self.routeViroPacket(pkt)
                    else:
                        log.debug("No next hop found!")

                # delete the failed gateway from the rdvRequestTracker - House Keeping
                del self.routing.rdvRequestTracker[gw]
                log.debug(
                    'Removed the failed gateway: {} from rvd request-tracker'.
                    format(gw))

        elif ctrlpkt.op == viroctrl.GW_WITHDRAW:

            failed_gw = ctrlpkt.payload.failed_gw
            log.debug(
                'Received Gateway Withdraw for node: {}'.format(failed_gw))
            self.routing.removeFailedNode(failed_gw)