示例#1
0
    def tryCallback(self, notification):

        """
        And this is the callback itself.  Everything that touches an ODL-specific
        data structure needs to go in here...above this layer it's all generic
        OpenFlow.

        :param notification org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived
        """
        # Find out where the packet came from (ingress port).  First find the node and connector
        # in the ODL/Java world (ingressNode and ingressNodeConnector)
        nodeConnectorRef = notification.getIngress() # XXX need to turn this into a NodeConnector object

        # String nodeId = ingress.getValue().firstIdentifierOf(Node.class).firstKeyOf(Node.class, NodeKey.class).getId().getValue();
        ingressNodeId = nodeConnectorRef.getValue().firstIdentifierOf(Node).firstKeyOf(Node, NodeKey).getId().getValue()
        switch = self.getSwitch(ingressNodeId) # ENOS switch
        ingressNode = self.findODLSwitch(switch) # ODL switch corresponding to it
        # String ncId = ncRef.getValue().firstIdentifierOf(NodeConnector.class).firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue();
        ingressNodeConnectorId = nodeConnectorRef.getValue().firstIdentifierOf(NodeConnector).firstKeyOf(NodeConnector, NodeConnectorKey).getId().getValue()
        # Make sure this is an OpenFlow switch.  If not, ignore the packet.
        if ingressNode.getAugmentation(FlowCapableNode) is not None:

            # This part is harder.  Need to figure out the ENOS port from the
            # NodeConnector object.  We also have the ENOS switch.
            # ingressNodeConnectorId is of the form u'openflow:72620962556436737:3',
            # but we need to get to an ENOS port from that (which has the form "eth13"
            # (for OVS) or "1" (for Corsa).  The ENOS port name for
            # NodeConnectorId can be gotten from the FlowCapableNodeConnector
            # augmentation for the NodeConnector.
            # We iterate over the Node's connectors to try to find the correct
            # NodeConnector...it's sort of the opposite of OdlMdsalImpl.getNodeConnector
            # (and this implies that we should probably make this into a Java function
            # someday.
            # XXX Would replacing this with something that just reads the NodeConnector
            # from the data store be more efficient?  It would avoid the loop, but by time
            # we get here we've already queried the data store for the Node anyway.
            ncs = self.odlMdsalImpl.getNodeConnectors(ingressNode)
            IngressNodeConnector = None
            portName = None
            for nc in ncs:
                if nc.getId().getValue() == ingressNodeConnectorId:
                    IngressNodeConnector = nc
                    fcnc = nc.getAugmentation(FlowCapableNodeConnector)
                    portName = fcnc.getName()
                    break

            # Complain if we can't figure out the ENOS port name
            if portName == None:
                ODLClient.logger.error("Can't determine port name for NodeConnector %r on node %r" % (ingressNodeConnectorId, ingressNodeId))
                return
            if not portName in switch.props['ports']:
                ODLClient.logger.error("Can't find port %s on node %s" % (portName, switch))
                return
            port = switch.props['ports'][portName]
            # Complain if we can't find the port, even though we have its name
            if port == None:
                ODLClient.logger.error("Can't find port %r on node %r" % (portName, ingressNodeId))
                return

            if self.debug and not self.dropLLDP:
                print "PACKET_IN from port %r in node %r" % (port, ingressNodeId)

            # Try to decode the packet.  First get the payload bytes and parse them.
            l2pkt = notification.getPayload()
            ethernetFrame = EthernetFrame.packetToFrame(l2pkt)

            if ethernetFrame != None:

                srcMac = MACAddress(ethernetFrame.getSrcMac())
                destMac = MACAddress(ethernetFrame.getDstMac())
                etherType = ethernetFrame.getEtherType() & 0xffff # convert to unsigned type
                vlanTag = ethernetFrame.getVid()
                payload = ethernetFrame.getPayload()

                # Possibly drop LLDP frames
                if self.dropLLDP:
                    if etherType == EthernetFrame.ETHERTYPE_LLDP:
                        return

                packetIn = PacketInEvent(inPort = port, srcMac=srcMac, dstMac=destMac, vlan=vlanTag, payload=payload)
                packetIn.props['ethertype'] = etherType

                if self.debug:
                    print "  Ethernet frame " + srcMac.str() + " -> " + destMac.str() + " Ethertype " + "%04x" % etherType + " VLAN " + "%04x" % vlanTag
                self.dispatchPacketIn(packetIn)

            else:
                if self.debug:
                    print "  Unknown frame type"

        else:
            if self.debug:
                print "PACKET_IN from Non-OpenFlow Switch"
示例#2
0
    def send(self, packet):

        """
        Send a packet via a PACKET_OUT OpenFlow message.  We use the PacketOut members
        and use net.es.netshell.odlmdsal.impl.EthernetFrame to help us put a VLAN
        header on the front

        :param packet: common.openflow.PacketOut
        :return:  True if successful, False if not
        """
#        print "ODLClient.send with packet from " + str(packet.dl_src) + " to " + str(packet.dl_dst) + " on " + packet.scope.switch.props['dpid']
        if self.isPacketOutValid(packet):
            # Get the switch (Node in the ODL world) and port (NodeConnector in the ODL world)
            sw = self.findODLSwitch(packet.scope.switch)
            dpid = packet.scope.switch.props['dpid'][-8:]
            if sw == None:
                print packet, "cannot be sent because the switch is not in inventory"
                return False
            portName = packet.port.name
            nodeconn = self.odlController.getNodeConnector(sw, portName)
            if nodeconn == None:
                ODLClient.logger.warning('can not send %r because the port %s on %r is invalid' % (packet, portName, sw.getId()))
                return False

            # Create the outgoing packet in ODL land.  The outgoing node connector must be set.
            frame = EthernetFrame()
            frame.setDstMac(self.javaByteArray(packet.dl_dst.data))
            frame.setSrcMac(self.javaByteArray(packet.dl_src.data))
            frame.setEtherType(packet.etherType)
            frame.setVid(packet.vlan)
            frame.setPayload(packet.payload)

            self.odlController.transmitDataPacket(self.javaByteArray(dpid), portName, frame.toPacket())

            return True
        ODLClient.logger.warning("Packet %r is not valid" % packet)
        return False