当主机 IP 地址未知时,在 RYU-SDN 控制器中避免不必要的数据包泛滥的最佳实践?

问题描述 投票:0回答:1

我正在使用 RYU 控制器和 Mininet 模拟器构建网络。当控制器收到 packet_in 事件时,它会在存储的地址中查找 IP 地址。如果未找到,则数据包会通过网络泛洪。然而,这是低效的,因为如果目标主机不在网络中,它可能会徒劳地淹没网络。

我尝试过的一个解决方案是让主机在网络开始学习其 IP 地址时发送虚拟数据包。但我想知道是否有更专业或推荐的方法来避免不必要的数据包淹没网络。对于这种情况有什么建议或最佳做法吗?

networking mininet sdn ryu
1个回答
0
投票

在 packet_in 事件中控制器接收到数据包之前,如果发送方不知道目标的 MAC 地址,则会收到 ARP 请求。控制器应该在设置数据包本身的流之前做出响应。场景如下:

  1. 主机生成一个数据包,但不知道目的地的MAC地址,所以它发送一个ARP请求。
  2. 控制器收到 ARP 请求并在其专用 ARP 表中查找 MAC 地址。
  3. 如果控制器找到 MAC 地址,它会向主机发送 ARP 回复。
  4. 如果在 ARP 表中没有找到 MAC,它会向网络中的所有交换机发送 ARP 请求。
  5. 如果控制器收到 ARP 回复,它会更新 ARP 表,然后将 ARP 回复发送给原始请求发送者。
  6. 当主机收到 ARP 回复时,它将数据包发送到交换机,交换机又将其发送到控制器以建立流。
  7. 如果没有收到ARP回复,主机超时,没有数据包发送,网络不再繁忙。

记住不要尽可能长时间地淹没网络。

示例代码:

@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):

    pkt = packet.Packet(ev.msg.data)
    eth = pkt.get_protocol(ethernet.ethernet)

    # avoid broadcast from LLDP
    if eth.ethertype == 35020:
        return

    # drop the IPV6 Packets if not using IPV6
    if pkt.get_protocol(ipv6.ipv6):
        match = ev.msg.datapath.ofproto_parser.OFPMatch(eth_type=eth.ethertype)
        actions = []
        self.add_flow(ev.msg.datapath, 1, match, actions)
        return 

    arp_pkt = pkt.get_protocol(arp.arp)

    if arp_pkt:
        # ARP packet is received
        
        # Store the sender host information
        src_ip = arp_pkt.src_ip
        src_mac = arp_pkt.src_mac
        if src_ip not in self.arp_table:
            self.arp_table[src_ip] = src_mac

        dst_ip = arp_pkt.dst_ip

        if arp_pkt.opcode == arp.ARP_REQUEST:
            if dst_ip in hosts_by_ip:
                 # If ARP request and destination MAC is known, send ARP reply
                print("ARP destination is in hosts, sending ARP reply")
                dst_mac = self.arp_table[dst_ip]
                self.send_arp_reply(ev.msg.datapath,
                                    dst_mac, src_mac,  dst_ip, src_ip,  ev.msg.match['in_port'])
            else:
                # If ARP request and destination MAC is not known, send ARP request to all hosts
                print("ARP destination is not in hosts, sending ARP request")
                for dp in self.datapaths.values():
                    self.send_arp_request(dp, src_mac, src_ip, dst_ip)

        else:
            print("ARP reply received from ", src_ip)
            # No need to do anything as we already stored the host IP, we wait for the requester to send another ARP request
    else:
        # IPv4 packet received because no flow was found in the switch flow table
        # TODO: set the flow (in the switch) here

def send_arp_reply(self, datapath, src_mac, dst_mac, src_ip, dst_ip, in_port):
    self.send_arp(datapath, arp.ARP_REPLY, src_mac,
                    src_ip, dst_mac, dst_ip, in_port)

def send_arp_request(self, datapath, src_mac, src_ip, dst_ip):
    self.send_arp(datapath, arp.ARP_REQUEST, src_mac,
                    src_ip, None, dst_ip, None)

def send_arp(self, datapath, opcode, src_mac, src_ip, dst_mac, dst_ip, in_port):
    eth_dst_mac = dst_mac
    arp_dst_mac = dst_mac
    actions = [datapath.ofproto_parser.OFPActionOutput(in_port)]

    if opcode == arp.ARP_REQUEST:
        eth_dst_mac = 'ff:ff:ff:ff:ff:ff'
        arp_dst_mac = '00:00:00:00:00:00'
        actions = [datapath.ofproto_parser.OFPActionOutput(
            datapath.ofproto.OFPP_FLOOD)]

    # Create Ethernet header
    eth = ethernet.ethernet(
        dst=eth_dst_mac,
        src=src_mac,
        ethertype=packet.ethernet.ether.ETH_TYPE_ARP
    )

    # Create ARP header
    arp_header = arp.arp(
        opcode=opcode,
        src_mac=src_mac,
        src_ip=src_ip,
        dst_mac=arp_dst_mac,
        dst_ip=dst_ip
    )

    # Create packet and send it
    pkt = packet.Packet()
    pkt.add_protocol(eth)
    pkt.add_protocol(arp_header)

    pkt.serialize()
    datapath.send_packet_out(
        buffer_id=datapath.ofproto.OFP_NO_BUFFER,
        in_port=datapath.ofproto.OFPP_CONTROLLER,
        actions=actions,
        data=pkt.data
    )
© www.soinside.com 2019 - 2024. All rights reserved.