Ejemplo n.º 1
0
    def break_packet(pkt):
        ethernet = Ethernet()
        ethernet.unpack(pkt)
        ether_type = ethernet.ether_type
        offset = 0

        if ethernet.ether_type == constants.VLAN:
            vlan = VLAN()
            vlan.unpack(ethernet.data.value)
            ether_type = vlan.ether_type
            offset += constants.VLAN_LEN
        else:
            vlan = None

        ip = None
        if ether_type == constants.IPv4:
            ip = IPv4()
            ip.unpack(ethernet.data.value, offset)
            offset += ip.length
        elif ether_type == 'IPv6':  #TODO
            pass

        tp = None
        if ether_type == constants.IPv4:  #TODO: add IPv6 with an or
            if ip.protocol == constants.TCP:
                tp = TCP()
                tp.parse(ethernet.data.alue, offset)
                offset += tp.length
            elif ip.protocol == constants.UDP:
                tp = UDP()
                tp.parse(ethernet.data.alue, offset)
                offset += tp.length

        return ethernet, vlan, ip, tp
Ejemplo n.º 2
0
def packet_in(event, packet_in_msg):
    """ Process OpenFlow 1.0 PacketIn messages

    Args:
        event: PacketIN event
        packet_in_msg: PacketIn msg
    Return:
        ethernet: PacketIn data
        in_port: in_port
        switch: OpenFlow datapath
        0, 0, 0 if it is not a trace probe
    """

    ethernet = Ethernet()
    ethernet.unpack(packet_in_msg.data.value)

    if settings.COLOR_VALUE in ethernet.source.value:
        log.debug("OpenFlow 1.0 PacketIn Trace Msg Received")

        in_port = packet_in_msg.in_port.value
        switch = event.source.switch
        return ethernet, in_port, switch

    log.debug("PacketIn is not a Data Trace Probe")
    return 0, 0, 0
Ejemplo n.º 3
0
    def update_links(self, event):
        """Dispatch 'reacheable.mac' event.

        Listen:
            `kytos/of_core.v0x0[14].messages.in.ofpt_packet_in`

        Dispatch:
            `reachable.mac`:
                { switch : <switch.id>,
                  port: <port.port_no>
                  reachable_mac: <mac_address>
                }

        """
        ethernet = Ethernet()
        ethernet.unpack(event.message.data.value)

        name = 'kytos/of_topology.reachable.mac'
        content = {
            'switch': event.source.switch.id,
            'port': event.message.in_port,
            'reachable_mac': ethernet.source
        }
        event = KytosEvent(name, content)
        self.controller.buffers.app.put(event)

        msg = 'The MAC %s is reachable from switch/port %s/%s.'
        log.debug(msg, ethernet.source, event.source.switch.id,
                  event.message.in_port)
Ejemplo n.º 4
0
    def handle_packet_in(self, event):
        """Handle PacketIn Event.

        Install flows allowing communication between switch ports.

        Args:
            event (KytosPacketIn): Received Event
        """
        log.debug("PacketIn Received")

        packet_in = event.content['message']

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        # Ignore LLDP packets or packets not generated by table-miss flows
        if (ethernet.destination in settings.lldp_macs
                or packet_in.reason != PacketInReason.OFPR_NO_MATCH):
            return

        # Learn the port where the sender is connected
        in_port = packet_in.in_port.value
        switch = event.source.switch
        switch.update_mac_table(ethernet.source, in_port)

        ports = switch.where_is_mac(ethernet.destination)

        # Add a flow to the switch if the destination is known
        if ports:
            flow_mod = FlowMod()
            flow_mod.command = FlowModCommand.OFPFC_ADD
            flow_mod.match = Match()
            flow_mod.match.dl_src = ethernet.source.value
            flow_mod.match.dl_dst = ethernet.destination.value
            flow_mod.match.dl_type = ethernet.ether_type
            flow_mod.actions.append(ActionOutput(port=ports[0]))
            event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                         'ofpt_flow_mod'),
                                   content={
                                       'destination': event.source,
                                       'message': flow_mod
                                   })
            self.controller.buffers.msg_out.put(event_out)

        # Send the packet to correct destination or flood it
        packet_out = PacketOut()
        packet_out.buffer_id = packet_in.buffer_id
        packet_out.in_port = packet_in.in_port
        packet_out.data = packet_in.data

        port = ports[0] if ports else Port.OFPP_FLOOD
        packet_out.actions.append(ActionOutput(port=port))
        event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                     'ofpt_packet_out'),
                               content={
                                   'destination': event.source,
                                   'message': packet_out
                               })

        self.controller.buffers.msg_out.put(event_out)
Ejemplo n.º 5
0
def packet_in(event, packet_in_msg):
    """ Process OpenFlow 1.0 PacketIn messages

    Args:
        event: PacketIN event
        packet_in_msg: PacketIn msg
    Return:
        ethernet: PacketIn data
        in_port: in_port
        switch: OpenFlow datapath
        0, 0, 0 if it is not a trace probe
    """

    ethernet = Ethernet()
    ethernet.unpack(packet_in_msg.data.value)

    if settings.COLOR_VALUE in ethernet.source.value:
        log.debug("OpenFlow 1.0 PacketIn Trace Msg Received")

        in_port = packet_in_msg.in_port.value
        switch = event.source.switch
        return ethernet, in_port, switch

    log.debug("PacketIn is not a Data Trace Probe")
    return 0, 0, 0
Ejemplo n.º 6
0
def get_vlan_from_pkt(data):

    ethernet = Ethernet()
    ethernet.unpack(data)

    vlan = VLAN()
    vlan.unpack(ethernet.data.value)

    return vlan.vid
Ejemplo n.º 7
0
    def handle_packet_in(self, event):
        """Handle PacketIn Event.

        Install flows allowing communication between switch ports.

        Args:
            event (KytosPacketIn): Received Event
        """
        log.debug("PacketIn Received")

        packet_in = event.content['message']

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        # Ignore LLDP packets or packets not generated by table-miss flows
        if (ethernet.destination in settings.LLDP_MACS
                or packet_in.reason != PacketInReason.OFPR_NO_MATCH):
            return

        switch = event.source.switch
        version = switch.ofp_version

        # Learn the port where the sender is connected
        if version == '0x01':
            in_port = packet_in.in_port.value
        else:
            in_port = packet_in.in_port

        switch.update_mac_table(ethernet.source, in_port)

        ports = switch.where_is_mac(ethernet.destination)

        # Add a flow to the switch if the destination is known
        if ports:
            flow_mod = self._create_flow_mod(version, ethernet, ports[0])

            event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                         'ofpt_flow_mod'),
                                   content={
                                       'destination': event.source,
                                       'message': flow_mod
                                   })
            self.controller.buffers.msg_out.put(event_out)

        # Send the packet to correct destination or flood it
        packet_out = self._create_packet_out(version, packet_in, ports)

        event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                     'ofpt_packet_out'),
                               content={
                                   'destination': event.source,
                                   'message': packet_out
                               })

        self.controller.buffers.msg_out.put(event_out)
 def test_Ethernet_unpack(self):
     """Test pack method of Ethernet class without VLAN tag."""
     raw = b'\x00\x15\xaf\xd58\x98\x00\x1f:>\x9a\xcf\x08\x00testdata'
     expected = Ethernet(destination='00:15:af:d5:38:98',
                         source='00:1f:3a:3e:9a:cf', ether_type=0x800,
                         data=b'testdata')
     expected.pack()
     unpacked = Ethernet()
     unpacked.unpack(raw)
     self.assertEqual(unpacked, expected)
Ejemplo n.º 9
0
 def test_Ethernet_unpack(self):
     """Test pack method of Ethernet class without VLAN tag."""
     raw = b'\x00\x15\xaf\xd58\x98\x00\x1f:>\x9a\xcf\x08\x00testdata'
     expected = Ethernet(destination='00:15:af:d5:38:98',
                         source='00:1f:3a:3e:9a:cf', ether_type=0x800,
                         data=b'testdata')
     expected.pack()
     unpacked = Ethernet()
     unpacked.unpack(raw)
     self.assertEqual(unpacked, expected)
Ejemplo n.º 10
0
 def test_Tagged_Ethernet_unpack(self):
     """Test pack method of Ethernet class including VLAN tag."""
     raw = b'\x00\x15\xaf\xd58\x98\x00\x1f:>'
     raw += b'\x9a\xcf\x81\x00!^\x08\x00testdata'
     expected = Ethernet(destination='00:15:af:d5:38:98',
                         source='00:1f:3a:3e:9a:cf', vlans=[VLAN(pcp=1,
                                                               vid=350)],
                         ether_type=0x800, data=b'testdata')
     expected.pack()
     unpacked = Ethernet()
     unpacked.unpack(raw)
     self.assertEqual(unpacked, expected)
Ejemplo n.º 11
0
 def test(self, event):
     from pyof.v0x04.asynchronous.packet_in import PacketIn
     msg = event.content['message']
     assert isinstance(msg, PacketIn)
     eth = Ethernet()
     eth.unpack(msg.data.value)
     log.debug('ethernet type=%s'%str(eth.ether_type))
     if eth.ether_type == EtherType.IPV4:
         ipv4 = IPv4()
         ipv4.unpack(eth.data.value)
         log.debug(ipv4.source)
         log.debug(ipv4.destination)
Ejemplo n.º 12
0
 def test_Tagged_Ethernet_unpack(self):
     """Test pack method of Ethernet class including VLAN tag."""
     raw = b'\x00\x15\xaf\xd58\x98\x00\x1f:>'
     raw += b'\x9a\xcf\x81\x00!^\x08\x00testdata'
     expected = Ethernet(destination='00:15:af:d5:38:98',
                         source='00:1f:3a:3e:9a:cf', vlans=[VLAN(pcp=1,
                                                               vid=350)],
                         ether_type=0x800, data=b'testdata')
     expected.pack()
     unpacked = Ethernet()
     unpacked.unpack(raw)
     self.assertEqual(unpacked, expected)
Ejemplo n.º 13
0
def _get_vlan_from_pkt(data):
    """ Get VLAN ID from frame. Used for VLAN Translation

    Args:
        data: Ethernet Frame
    Returns:
        VLAN VID
    """
    ethernet = Ethernet()
    ethernet.unpack(data)
    vlan = ethernet.vlans[0]
    return vlan.vid
Ejemplo n.º 14
0
def _get_vlan_from_pkt(data):
    """ Get VLAN ID from frame. Used for VLAN Translation

    Args:
        data: Ethernet Frame
    Returns:
        VLAN VID
    """
    ethernet = Ethernet()
    ethernet.unpack(data)
    vlan = ethernet.vlans[0]
    return vlan.vid
Ejemplo n.º 15
0
    def handle_packet_in(self, event):
        """Handle PacketIn Event.

        Install flows allowing communication between switch ports.

        Args:
            event (KytosPacketIn): Received Event
        """
        log.debug("PacketIn Received")

        packet_in = event.content['message']

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        # Ignore LLDP packets or packets not generated by table-miss flows
        if (ethernet.destination in settings.LLDP_MACS
                or packet_in.reason != PacketInReason.OFPR_NO_MATCH):
            return

        switch = event.source.switch
        version = switch.ofp_version

        # Learn the port where the sender is connected
        in_port = getattr(packet_in.in_port, 'value', packet_in.in_port)

        switch.update_mac_table(ethernet.source, in_port)

        ports = switch.where_is_mac(ethernet.destination)

        # Add a flow to the switch if the destination is known
        if ports:
            flow = self._create_flow(ethernet, ports[0])
            destination = switch.id
            endpoint = f'{settings.FLOW_MANAGER_URL}/flows/{destination}'
            data = {'flows': [flow]}
            requests.post(endpoint, json=data)

        # Send the packet to correct destination or flood it
        packet_out = self._create_packet_out(version, packet_in, ports, switch)

        if packet_out is None:
            return

        event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                     'ofpt_packet_out'),
                               content={
                                   'destination': event.source,
                                   'message': packet_out
                               })

        self.controller.buffers.msg_out.put(event_out)
Ejemplo n.º 16
0
    def handle_packet_in(self, event):
        """ Receives PacketIn msgs and search from trace packets.

        Args:
            event (KycoPacketIn): Received Event
        """
        log.debug("PacketIn Received")
        packet_in = event.content['message']

        in_port = packet_in.in_port.value
        switch = event.source.switch

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        if settings.COLOR_VALUE in ethernet.source.value:
            self.tracing.process_probe_packet(event, ethernet,
                                              in_port, switch)
Ejemplo n.º 17
0
    def update_links(event):
        """Receive a kytos event and update links interface.

        Get the event kytos/of_core.messages.in.ofpt_packet_in and update
        the interface endpoints, ignoring the LLDP packages.

        Parameters:
            event (KytosEvent): event with Ethernet packet.
        """
        ethernet = Ethernet()
        ethernet.unpack(event.message.data.value)
        if ethernet.ether_type != constants.LLDP_ETHERTYPE:
            port_no = event.message.in_port
            hw_address = ethernet.source
            switch = event.source.switch
            interface = switch.get_interface_by_port_no(port_no.value)

            if interface is not None and \
               not interface.is_link_between_switches():
                interface.update_endpoint(hw_address)
Ejemplo n.º 18
0
    def update_links(self, message, source):
        """Dispatch 'reacheable.mac' event.

        Args:
            message: python openflow (pyof) PacketIn object.
            source: kytos.core.switch.Connection instance.

        Dispatch:
            `reachable.mac`:
                {
                  switch : <switch.id>,
                  port: <port.port_no>
                  reachable_mac: <mac_address>
                }

        """
        ethernet = Ethernet()
        ethernet.unpack(message.data.value)
        if ethernet.ether_type in (EtherType.LLDP, EtherType.IPV6):
            return

        try:
            port = source.switch.get_interface_by_port_no(
                message.in_port.value)
        except AttributeError:
            port = source.switch.get_interface_by_port_no(message.in_port)

        name = 'kytos/of_core.reachable.mac'
        content = {
            'switch': source.switch,
            'port': port,
            'reachable_mac': ethernet.source.value
        }
        event = KytosEvent(name, content)
        self.controller.buffers.app.put(event)

        msg = 'The MAC %s is reachable from switch/port %s/%s.'
        log.debug(msg, ethernet.source, source.switch.id, message.in_port)
Ejemplo n.º 19
0
    def handle_packet_in(self, event):
        """Handle PacketIn Event.

        Install flows allowing communication between switch ports.

        Args:
            event (KytosPacketIn): Received Event
        """
        log.debug("PacketIn Received")

        packet_in = event.content['message']

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        # Ignore LLDP packets or packets not generated by table-miss flows
        if (ethernet.destination in settings.lldp_macs
                or packet_in.reason != PacketInReason.OFPR_NO_MATCH):
            return

        # Learn the port where the sender is connected
        in_port = packet_in.in_port

        switch = event.source.switch
        switch.update_mac_table(ethernet.source, in_port)

        ports = switch.where_is_mac(ethernet.destination)

        # Add a flow to the switch if the destination is known
        if ports:
            flow_mod = FlowMod()
            flow_mod.command = FlowModCommand.OFPFC_ADD
            flow_mod.priority = settings.flow_priority

            match_dl_type = OxmTLV()
            match_dl_type.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_TYPE
            match_dl_type.oxm_value = ethernet.ether_type.value.to_bytes(
                2, 'big')
            flow_mod.match.oxm_match_fields.append(match_dl_type)

            match_dl_src = OxmTLV()
            match_dl_src.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_SRC
            match_dl_src.oxm_value = ethernet.source.pack()
            flow_mod.match.oxm_match_fields.append(match_dl_src)

            match_dl_dst = OxmTLV()
            match_dl_dst.oxm_field = OxmOfbMatchField.OFPXMT_OFB_ETH_DST
            match_dl_dst.oxm_value = ethernet.destination.pack()
            flow_mod.match.oxm_match_fields.append(match_dl_dst)

            action = ActionOutput(port=ports[0])

            instruction = InstructionApplyAction()
            instruction.actions.append(action)

            flow_mod.instructions.append(instruction)

            event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                         'ofpt_flow_mod'),
                                   content={
                                       'destination': event.source,
                                       'message': flow_mod
                                   })
            self.controller.buffers.msg_out.put(event_out)

        # Send the packet to correct destination or flood it
        packet_out = PacketOut()
        packet_out.buffer_id = packet_in.buffer_id
        packet_out.in_port = in_port
        packet_out.data = packet_in.data

        port = ports[0] if ports else PortNo.OFPP_FLOOD

        out_action = ActionOutput(port=port)

        packet_out.actions.append(out_action)
        event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                     'ofpt_packet_out'),
                               content={
                                   'destination': event.source,
                                   'message': packet_out
                               })

        self.controller.buffers.msg_out.put(event_out)
Ejemplo n.º 20
0
    def packet_in(self, event):
        self.lock.acquire()

        from pyof.v0x04.asynchronous.packet_in import PacketIn
        msg = event.content['message']
        assert isinstance(msg, PacketIn)
        eth = Ethernet()
        eth.unpack(msg.data.value)
        #log.info('ethernet type=%s'%str(eth.ether_type))
        switch = event.source.switch
        in_port = msg.in_port
        # if eth.ether_type != 35020:
        #     log.info('ethernet type=%s'%str(eth.ether_type))
        if eth.ether_type == EtherType.IPV4:
            ipv4 = IPv4()
            ipv4.unpack(eth.data.value)

            if ipv4.destination == '10.0.0.254':
                pass
                #only for host locate
                # role = HOST_ROLE[ipv4.source]
                # self.nodes[ipv4.source] = {'role': role}
                #
                # h_id = ipv4.source
                # s_id = str(switch.dpid) + ":" + str(in_port)
                #
                # h2s_id = h_id + "+" + s_id
                # s2h_id = s_id + "+" + h_id
                # self.edges[h2s_id] = {'src': h_id, 'dst': s_id}
                # self.edges[s2h_id] = {'src': s_id, 'dst': h_id}
                # #TODO: need to handle host mobility
                # print(self.nodes)
                # print(self.edges)
                # if not self.debug:
                #     pass # self.trident.set_topology(self.nodes, self.edges)
            else:
                sip = ipv4.source
                dip = ipv4.destination
                ipproto = ipv4.protocol
                sport = None
                dport = None
                # allow_ip = ["10.0.0.1","10.0.0.2","10.0.0.3"]
                # if sip not in allow_ip:
                #     return
                # if dip not in allow_ip:
                #     return
                allow_pair = [("10.0.0.2", "10.0.0.3"),
                              ("10.0.0.2", "10.0.0.1")]
                if (sip, dip) not in allow_pair:
                    self.lock.release()
                    return
                if ipproto == 6:
                    ipproto = "tcp"
                elif ipproto == 17:
                    ipproto = "udp"
                else:
                    ipproto = "unknown"

                if ipproto == "tcp":
                    tcph = unpack('!HHLLBBHHH', eth.data.value[20:40])
                    sport = tcph[0]
                    dport = tcph[1]
                elif ipproto == "udp":
                    udph = unpack('!HHHH', eth.data.value[20:28])
                    sport = udph[0]
                    dport = udph[1]
                else:
                    self.lock.release()
                    return

                log.info("sip:" + str(sip) + "dip:" + str(dip) + str(ipproto) +
                         "sport" + str(sport) + "dport" + str(dport))
                pkt = TridentPacket(sip, dip, sport, dport, ipproto)
                if not self.debug:
                    log.info('start to call trident new_pkt')
                    self.trident.new_pkt(pkt)
        self.lock.release()
Ejemplo n.º 21
0
def get_vlan_from_pkt(data):

    ethernet = Ethernet()
    ethernet.unpack(data)

    return ethernet.vlan.vid