Beispiel #1
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
 def test_Ethernet_pack(self):
     """Test pack method of Ethernet class without VLAN tag."""
     ethernet = Ethernet(destination='00:1f:3a:3e:9a:cf',
                         source='00:15:af:d5:38:98', ether_type=0x800,
                         data=b'testdata')
     packed = ethernet.pack()
     expected = b'\x00\x1f:>\x9a\xcf\x00\x15\xaf\xd58\x98\x08\x00testdata'
     self.assertEqual(packed, expected)
 def test_Tagged_Ethernet_pack(self):
     """Test pack method of Ethernet class including VLAN tag."""
     ethernet = Ethernet(destination='00:1f:3a:3e:9a:cf',
                         source='00:15:af:d5:38:98', vlans=[VLAN(vid=200)],
                         ether_type=0x800, data=b'testdata')
     packed = ethernet.pack()
     expected = b'\x00\x1f:>\x9a\xcf\x00\x15\xaf\xd58'
     expected += b'\x98\x81\x00\x00\xc8\x08\x00testdata'
     self.assertEqual(packed, expected)
Beispiel #4
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
Beispiel #5
0
def _create_ethernet_frame(trace_entries, color):
    """ Create an Ethernet frame using TraceEntries
    and color (dl_src)

    Args:
        trace_entries: TraceEntries provided by user or collected from PacketIn
        color: field and value that indicate the color
    Returns:
        ethernet frame
    """
    ethernet = Ethernet()
    ethernet.ether_type = trace_entries.dl_type

    ethernet.source = color['color_value']
    ethernet.destination = trace_entries.dl_dst

    vlan = VLAN(vid=trace_entries.dl_vlan,
                pcp=trace_entries.dl_vlan_pcp)
    ethernet.vlans.append(vlan)
    return ethernet
Beispiel #6
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)
 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)
Beispiel #8
0
    def execute(self):
        """Send LLDP Packets every 'POLLING_TIME' seconds to all switches."""
        switches = list(self.controller.switches.values())
        for switch in switches:
            try:
                of_version = switch.connection.protocol.version
            except AttributeError:
                of_version = None

            if not (switch.is_connected() and of_version in [0x01, 0x04]):
                continue

            for interface in switch.interfaces.values():

                # Avoid ports with speed == 0
                if interface.port_number == 65534:
                    continue

                lldp = LLDP()
                lldp.chassis_id.sub_value = DPID(switch.dpid)
                port_type = UBInt16 if of_version == 0x01 else UBInt32
                lldp.port_id.sub_value = port_type(interface.port_number)

                ethernet = Ethernet()
                ethernet.ether_type = EtherType.LLDP
                ethernet.source = interface.address
                ethernet.destination = constants.LLDP_MULTICAST_MAC
                ethernet.data = lldp.pack()

                packet_out = self.build_lldp_packet_out(
                    of_version, interface.port_number, ethernet.pack())

                if packet_out is not None:
                    name = 'kytos/of_lldp.messages.out.ofpt_packet_out'
                    content = {
                        'destination': switch.connection,
                        'message': packet_out
                    }
                    event_out = KytosEvent(name=name, content=content)
                    self.controller.buffers.msg_out.put(event_out)

                    log.debug("Sending a LLDP PacketOut to the switch %s",
                              switch.dpid)
Beispiel #9
0
    def execute(self):
        """Implement a loop to check switches liveness."""
        switches = list(self.controller.switches.values())
        for switch in switches:
            if not (switch.is_connected() and
                    switch.connection.protocol.version == 0x01):
                continue
            # Gerar lldp para cada uma das portas do switch
            # Gerar o hash de cada um dos pacotes e armazenar

            for port in switch.features.ports:
                output_action = ActionOutput()
                output_action.port = port.port_no

                # Avoid ports with speed == 0
                if port.port_no.value == 65534:
                    continue

                ethernet = Ethernet()
                ethernet.ether_type = constants.LLDP_ETHERTYPE
                ethernet.source = port.hw_addr
                ethernet.destination = constants.LLDP_MULTICAST_MAC

                lldp = LLDP()
                lldp.chassis_id.sub_value = DPID(switch.dpid)
                lldp.port_id.sub_value = port.port_no

                ethernet.data = lldp.pack()

                packet_out = PacketOut()
                packet_out.actions.append(output_action)
                packet_out.data = ethernet.pack()

                event_out = KytosEvent()
                event_out.name = 'kytos/of_lldp.messages.out.ofpt_packet_out'
                event_out.content = {'destination': switch.connection,
                                     'message': packet_out}
                self.controller.buffers.msg_out.put(event_out)

                log.debug("Sending a LLDP PacketOut to the switch %s",
                          switch.dpid)
Beispiel #10
0
    def execute(self):
        """Send LLDP Packets every 'POLLING_TIME' seconds to all switches."""
        switches = list(self.controller.switches.values())
        for switch in switches:
            try:
                of_version = switch.connection.protocol.version
            except AttributeError:
                of_version = None

            if not switch.is_connected():
                continue

            if of_version == 0x01:
                port_type = UBInt16
                local_port = Port10.OFPP_LOCAL
            elif of_version == 0x04:
                port_type = UBInt32
                local_port = Port13.OFPP_LOCAL
            else:
                # skip the current switch with unsupported OF version
                continue

            interfaces = list(switch.interfaces.values())
            for interface in interfaces:

                # Avoid the interface that connects to the controller.
                if interface.port_number == local_port:
                    continue

                lldp = LLDP()
                lldp.chassis_id.sub_value = DPID(switch.dpid)
                lldp.port_id.sub_value = port_type(interface.port_number)

                ethernet = Ethernet()
                ethernet.ether_type = EtherType.LLDP
                ethernet.source = interface.address
                ethernet.destination = constants.LLDP_MULTICAST_MAC
                ethernet.data = lldp.pack()
                # self.vlan_id == None will result in a packet with no VLAN.
                ethernet.vlans.append(VLAN(vid=self.vlan_id))

                packet_out = self._build_lldp_packet_out(
                    of_version, interface.port_number, ethernet.pack())

                if packet_out is not None:
                    event_out = KytosEvent(
                        name='kytos/of_lldp.messages.out.ofpt_packet_out',
                        content={
                            'destination': switch.connection,
                            'message': packet_out
                        })
                    self.controller.buffers.msg_out.put(event_out)

                    log.debug("Sending a LLDP PacketOut to the switch %s",
                              switch.dpid)

                    msg = '\n'
                    msg += 'Switch: %s (%s)\n'
                    msg += '  Interfaces: %s\n'
                    msg += '  -- LLDP PacketOut --\n'
                    msg += '  Ethernet: eth_type (%s) | src (%s) | dst (%s)\n'
                    msg += '    LLDP: Switch (%s) | port (%s)'

                    log.debug(msg, switch.connection.address, switch.dpid,
                              switch.interfaces, ethernet.ether_type,
                              ethernet.source, ethernet.destination,
                              switch.dpid, interface.port_number)
    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()
Beispiel #12
0
def generate_trace_pkt(entries, color, r_id, my_domain):
    """ Receives the REST/PUT to generate a PacketOut
    data needs to be serialized.

    Args:
        entries:
        color: result from Coloring Napp for a specific DPID
        r_id:
        my_domain:

    Returns:
        in_port:
        pkt:
    """

    trace = {}
    switch = {}
    eth = {}
    ip = {}
    tp = {}

    # TODO Validate for dl_vlan. If empty, return error.

    # Default values
    dpid, in_port = 0, 65532
    if color['color_field'] == 'dl_src':
        dl_src = color['color_value']
    else:
        dl_src = '0e:55:05:0e:55:05'
    dl_dst = "ca:fe:ca:fe:ca:fe"
    dl_vlan, dl_type, dl_vlan_pcp = 100, 2048, 0
    nw_src, nw_dst, nw_tos = '127.0.0.1', '127.0.0.1', 0
    tp_src, tp_dst = 1, 1

    try:
        trace = entries['trace']
        switch = trace['switch']
        eth = trace['eth']
    except:
        pass

    try:
        ip = trace['ip']
    except:
        pass

    try:
        tp = trace['tp']
    except:
        pass

    if len(switch) > 0:
        dpid, in_port = prepare_switch(switch, dpid, in_port)

    if len(eth) > 0:
        dl_src, dl_dst, dl_vlan, dl_type, dl_vlan_pcp = prepare_ethernet(eth, dl_src, dl_dst,
                                                                         dl_vlan, dl_type,
                                                                         dl_vlan_pcp)
    # if len(ip) > 0:
    nw_src, nw_dst, nw_tos = prepare_ip(ip, nw_src, nw_dst, nw_tos)

    # if len(tp) > 0:
    tp_src, tp_dst = prepare_tp(tp, tp_src, tp_dst)

    kethernet = Ethernet()
    kethernet.ether_type = constants.VLAN
    kethernet.source = dl_src
    kethernet.destination = dl_dst

    kvlan = VLAN(vid=int(dl_vlan), pcp=dl_vlan_pcp, ether_type=int(dl_type))

    msg = TraceMsg(r_id, my_domain)

    if int(dl_type) == constants.IPv4:

        kip = IPv4()
        kip.destination = nw_dst
        kip.source = nw_src
        # ip.protocol = 6
        kip.data = dill.dumps(msg)
        kvlan.data = kip.pack()
    else:
        kvlan.data = dill.dumps(msg)

    kethernet.data = kvlan.pack()
    pkt = kethernet.pack()
    return in_port, pkt
Beispiel #13
0
def get_vlan_from_pkt(data):

    ethernet = Ethernet()
    ethernet.unpack(data)

    return ethernet.vlan.vid
Beispiel #14
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)