亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Floodlight 源碼解讀:FloodlightProvider

dadong / 633人閱讀

摘要:每個消息將通過一個的線程進行處理,并執(zhí)行與所有模塊的消息相關(guān)聯(lián)的所有邏輯其他模塊也可以注冊類似交換機連接或斷開和端口狀態(tài)通知特定時間。默認(rèn)情況下,使用地址和來識別設(shè)備。設(shè)備管理器將了解其他屬性,如地址。在消息轉(zhuǎn)發(fā)實現(xiàn)前,模塊將啟動。

FloodlightProvider

處理交換機之間的連接并將 OpenFlow 的消息轉(zhuǎn)化成其他模塊可以監(jiān)聽的時間

決定某些特定的 OpenFLow 消息(即 PacketIn,F(xiàn)lowRemove,PortStatus 等)被分派到該偵聽消息的模塊的順序,模塊可以決定允許該消息進入下一個監(jiān)聽對象或者停止處理消息

FloodlightProvider 如何工作?

FloodlightProvider 使用 Netty 庫來處理到交換機的線程和連接。
每個 OpenFlow 消息將通過一個 Netty 的線程進行處理,并執(zhí)行與所有模塊的消息相關(guān)聯(lián)的所有邏輯
其他模塊也可以注冊類似交換機連接或斷開和端口狀態(tài)通知特定時間。
為了使模塊注冊為基于 OpenFlow 消息的,必須實現(xiàn) IOFMessageListener 接口

要監(jiān)聽 OpenFlow 消息,要先向 FloodlightProvider 注冊
調(diào)用 IFloodlightProviderService(具體由 Controller 類實現(xiàn))的 addOFMessageListener 方法進行注冊訂閱
核心工作是在 ListenerDispatcher 類來完成。
每次增加觀察者都會判斷是否是終結(jié)點(也就是不被其他的 Listener 所依賴),因為最終確定這些觀察者順序的時候就是由這些終結(jié)點開始往前進行 DFS 遍歷得到

Controller中實現(xiàn) IFloodlightProviderService 的方法
    @Override
    public synchronized void addOFMessageListener(OFType type, IOFMessageListener listener) {
        //先判斷與type對應(yīng)的 ListenerDispatcher對象是否存在
        ListenerDispatcher ldd =
            messageListeners.get(type);
        if (ldd == null) {
            ldd = new ListenerDispatcher();
            messageListeners.put(type, ldd);
        }
      //注冊監(jiān)聽type這個消息;
        ldd.addListener(type, listener);
    }
ListenerDispatcher 維護這些觀察者,有依賴關(guān)系
    volatile List listeners = new ArrayList();

//每個OF msg都有唯一的ListenerDispatcher對象,觀察者存在listeners鏈表中

    private boolean ispre(U type, T l1, T l2) {
        return (l2.isCallbackOrderingPrereq(type, l1.getName()) ||
                l1.isCallbackOrderingPostreq(type, l2.getName()));
    }

返回兩個傳入的監(jiān)聽器的順序

     public void addListener(U type, T listener) {
        List newlisteners = new ArrayList();
        if (listeners != null)
            newlisteners.addAll(listeners);
        newlisteners.add(listener);
        // Find nodes without outgoing edges
        // 查找沒有出邊的節(jié)點
        List terminals = new ArrayList();
        for (T i : newlisteners) {
            boolean isterm = true;
            for (T j : newlisteners) {
                if (ispre(type, i, j)) {
                    //兩個都不關(guān)心前后順序的時候
                    isterm = false;
                    break;
                }
            }
            if (isterm) {
                //關(guān)乎有前后順序的監(jiān)聽模塊存入
                terminals.add(i);
            }
        }
        if (terminals.size() == 0) {
            logger.error("No listener dependency solution: " +
                         "No listeners without incoming dependencies");
            listeners = newlisteners;
            return;
        }
        // visit depth-first traversing in the opposite order from
        // the dependencies.  Note we will not generally detect cycles
        /**
         * 以相反順序訪問深度優(yōu)先遍歷依賴。 注意我們通常不會檢測周期
         */
        HashSet visited = new HashSet();
        List ordering = new ArrayList();
        for (T term : terminals) {
            //進行排序
            visit(newlisteners, type, visited, ordering, term);
        }
        listeners = ordering;
    }
    private void visit(List newlisteners, U type, HashSet visited,
                       List ordering, T listener) {
        if (!visited.contains(listener)) {
            visited.add(listener);
            for (T i : newlisteners) {
                if (ispre(type, i, listener)) {
                    visit(newlisteners, type, visited, ordering, i);
                }
            }
            ordering.add(listener);
            //
        }
    }
監(jiān)聽器具有的方法
public interface IListener

    public enum Command {
        CONTINUE, STOP
    }
狀態(tài)值,用來判斷是否繼續(xù)執(zhí)行

    public String getName(); 
    //用來判斷 name 的這個模塊是否要在當(dāng)前對象之前執(zhí)行
    public boolean isCallbackOrderingPrereq(T type, String name);
    //用來判斷 name 的這個模塊是否要在當(dāng)前對象之后執(zhí)行
    public boolean isCallbackOrderingPostreq(T type, String name);

IOFMessageListener接口繼承了 IListener 接口,同時定義了 receive 方法

    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx);
返回 CONTINUE 或者 STOP,繼續(xù)看每個繼承這個接口的模塊的重寫
查看繼承了 IOFMessageListener 的Type Hierarchy

TopologyManager 模塊的IOFMessageListener 重寫的方法:

    @Override
    public String getName() {
        return MODULE_NAME; //此處為 topology,每個模塊都有自己的 MODULE_NAME
    }

    @Override
    public boolean isCallbackOrderingPrereq(OFType type, String name) {
        //從此處可以看出,在執(zhí)行這個模塊之前,需要先執(zhí)行 MODULE_NAME 為 linkiscovery 的模塊
        return "linkdiscovery".equals(name);
    }

    @Override
    public boolean isCallbackOrderingPostreq(OFType type, String name) {
        return false;
    }

    @Override
    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
        switch (msg.getType()) {
        case PACKET_IN:
            ctrIncoming.increment();//計數(shù)器,加一
            //調(diào)用這里的執(zhí)行方法
            return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
        default:
            break;
        }

        return Command.CONTINUE;
    }

通過 Type Hierarchy 可以找到Packet-In消息處理順序的幾個模塊

FloodlightContextStore 數(shù)據(jù)結(jié)構(gòu)

FloodlightContextStore 代表的是一種緩存模型(利用的是ConcurrentHashMap,線程安全的 HashMap)

里面存儲的是上下文相關(guān)的對象,能夠根據(jù)相應(yīng)的key得到具體的 Object

存在的意義是Floodlight中注冊監(jiān)聽某個事件的listener可以在被調(diào)用的時候直接從中取出上下文信息(context information)

基本數(shù)據(jù)結(jié)構(gòu),這是一個上下文對象,F(xiàn)loodlight代碼監(jiān)聽器可以注冊它,稍后可以檢索與事件相關(guān)聯(lián)的上下文信息

    public class FloodlightContext {
        protected ConcurrentHashMap storage =
                new ConcurrentHashMap();

        public ConcurrentHashMap getStorage() {
            return storage;
        }
    }

創(chuàng)建了一個 HashMap storage,

    public class FloodlightContextStore {
        
        @SuppressWarnings("unchecked")
        public V get(FloodlightContext bc, String key) {
            return (V)bc.storage.get(key);
        }
        
        public void put(FloodlightContext bc, String key, V value) {
            bc.storage.put(key, value);
        }
        
        public void remove(FloodlightContext bc, String key) {
            bc.storage.remove(key);
        }
    }

一個FloodlightContextStore對象,可用于PACKET-IN有效內(nèi)容,消息對象是Ethernet類型

    public static final FloodlightContextStore bcStore =
            new FloodlightContextStore();
LinkDiscoveryManager 模塊

鏈接發(fā)現(xiàn)服務(wù)負(fù)責(zé)發(fā)現(xiàn)和維護 OpenFlow 網(wǎng)絡(luò)中的網(wǎng)絡(luò)連接的狀態(tài)

IOFMessageListener 的 receive 方法

    @Override
    public Command receive(IOFSwitch sw, OFMessage msg,
            FloodlightContext cntx) {
        switch (msg.getType()) {
        case PACKET_IN:
            ctrIncoming.increment();
            return this.handlePacketIn(sw.getId(), (OFPacketIn) msg,
                    cntx);
        default:
            break;
        }
        return Command.CONTINUE;
    }

主要使用了 handlePacketIn()方法

    protected Command handlePacketIn(DatapathId sw, OFPacketIn pi,
            FloodlightContext cntx) {
        //提取 Packet-In 的有效分組內(nèi)容
        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
                IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
        OFPort inPort = (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT));
        if (eth.getPayload() instanceof BSN) {
            BSN bsn = (BSN) eth.getPayload();
            if (bsn == null) return Command.STOP;
            if (bsn.getPayload() == null) return Command.STOP;
            // It could be a packet other than BSN LLDP, therefore
            // continue with the regular processing.
            // 它可以是除BSN LLDP之外的分組,因此繼續(xù)進行常規(guī)處理。
            if (bsn.getPayload() instanceof LLDP == false)
                return Command.CONTINUE;
            return handleLldp((LLDP) bsn.getPayload(), sw, inPort, false, cntx);
        } else if (eth.getPayload() instanceof LLDP) {
            return handleLldp((LLDP) eth.getPayload(), sw, inPort, true, cntx);
        } else if (eth.getEtherType().getValue() < 1536 && eth.getEtherType().getValue() >= 17) {
            long destMac = eth.getDestinationMACAddress().getLong();
            if ((destMac & LINK_LOCAL_MASK) == LINK_LOCAL_VALUE) {
                ctrLinkLocalDrops.increment();
                if (log.isTraceEnabled()) {
                    log.trace("Ignoring packet addressed to 802.1D/Q "
                            + "reserved address.");
                }
                return Command.STOP;
            }
        } else if (eth.getEtherType().getValue() < 17) {
            log.error("Received invalid ethertype of {}.", eth.getEtherType());
            return Command.STOP;
        }

        if (ignorePacketInFromSource(eth.getSourceMACAddress())) {
            ctrIgnoreSrcMacDrops.increment();
            return Command.STOP;
        }

        // If packet-in is from a quarantine port, stop processing.
        NodePortTuple npt = new NodePortTuple(sw, inPort);
        if (quarantineQueue.contains(npt)) {
            ctrQuarantineDrops.increment();
            return Command.STOP;
        }

        return Command.CONTINUE;
    }
TopolopyManager

為控制器維護拓?fù)湫畔?,以及在網(wǎng)絡(luò)中尋找路由

IOFMessageListener 的 receive 方法

    @Override
    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
        switch (msg.getType()) {
        case PACKET_IN:
            ctrIncoming.increment();
            return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
        default:
            break;
        }

        return Command.CONTINUE;
    }
主要使用了processPacketInMessage()方法

    protected Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
        // get the packet-in switch.
        Ethernet eth =
                IFloodlightProviderService.bcStore.
                get(cntx,IFloodlightProviderService.CONTEXT_PI_PAYLOAD);

        if (eth.getPayload() instanceof BSN) {
            BSN bsn = (BSN) eth.getPayload();
            if (bsn == null) return Command.STOP;
            if (bsn.getPayload() == null) return Command.STOP;

            // 可能不是 BSN LLDP,繼續(xù)常規(guī)處理
            if (bsn.getPayload() instanceof LLDP == false)
                return Command.CONTINUE;

            doFloodBDDP(sw.getId(), pi, cntx);
            return Command.STOP;
        } else {
            return dropFilter(sw.getId(), pi, cntx);
        }
    }
DeviceManagerImpl

DeviceManager基于在網(wǎng)絡(luò)中看到的MAC地址創(chuàng)建設(shè)備

它跟蹤映射到設(shè)備的任何網(wǎng)絡(luò)地址及其在網(wǎng)絡(luò)中的位置

設(shè)備管理器通過 PACKET-IN 消息請求了解設(shè)備,通過 PACKET-IN 消息獲取信息,根據(jù)實體如何建立進行分類。默認(rèn)情況下,entity classifies 使用 MAC 地址和 VLAN 來識別設(shè)備。這兩個屬性定義一個獨一無二的設(shè)備。設(shè)備管理器將了解其他屬性,如 IP 地址。
信息中的一個重要的部分是設(shè)備的連接點,如果一個交換機接受到一個 PACKET-IN 消息,則交換機將會創(chuàng)建一個連接點,設(shè)備也會根據(jù)時間清空連接點,IP 地址,以及設(shè)備本身,最近看到的時間戳是用來保持清空過程的控制

IOFMessageListener 的 receive 方法

    @Override
    public Command receive(IOFSwitch sw, OFMessage msg,
            FloodlightContext cntx) {
        switch (msg.getType()) {
        case PACKET_IN:
            cntIncoming.increment();
            return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
        default:
            break;
        }
        return Command.CONTINUE;
    }

主要使用了processPacketInMessage()方法

    protected Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
        OFPort inPort = (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT));
        // Extract source entity information
        Entity srcEntity = getSourceEntityFromPacket(eth, sw.getId(), inPort);
        if (srcEntity == null) {
            cntInvalidSource.increment();
            return Command.STOP;
        }

        // Learn from ARP packet for special VRRP settings.
        // In VRRP settings, the source MAC address and sender MAC
        // addresses can be different.  In such cases, we need to learn
        // the IP to MAC mapping of the VRRP IP address.  The source
        // entity will not have that information.  Hence, a separate call
        // to learn devices in such cases.
        learnDeviceFromArpResponseData(eth, sw.getId(), inPort);

        // Learn/lookup device information
        Device srcDevice = learnDeviceByEntity(srcEntity);
        if (srcDevice == null) {
            cntNoSource.increment();
            return Command.STOP;
        }

        // Store the source device in the context
        fcStore.put(cntx, CONTEXT_SRC_DEVICE, srcDevice);

        // Find the device matching the destination from the entity
        // classes of the source.
        if (eth.getDestinationMACAddress().getLong() == 0) {
            cntInvalidDest.increment();
            return Command.STOP;
        }
        Entity dstEntity = getDestEntityFromPacket(eth);
        Device dstDevice = null;
        if (dstEntity != null) {
            dstDevice = findDestByEntity(srcDevice.getEntityClass(), dstEntity);
            if (dstDevice != null)
                fcStore.put(cntx, CONTEXT_DST_DEVICE, dstDevice);
            else
                cntNoDest.increment();
        } else {
            cntNoDest.increment();
        }

        if (logger.isTraceEnabled()) {
            logger.trace("Received PI: {} on switch {}, port {} *** eth={}" +
                    " *** srcDev={} *** dstDev={} *** ",
                    new Object[] { pi, sw.getId().toString(), inPort, eth,
                    srcDevice, dstDevice });
        }

        snoopDHCPClientName(eth, srcDevice);

        return Command.CONTINUE;
    }
vitualNetworkFilter

虛擬網(wǎng)絡(luò)過濾器模塊是基于虛擬化網(wǎng)絡(luò)的數(shù)據(jù)鏈路層,它允許你在獨立的數(shù)據(jù)鏈路層上創(chuàng)建多個邏輯鏈路

若是使用 floodlightdefault.properties 則沒有這個模塊

如何工作

在 Floodlight 啟動時,沒有虛擬網(wǎng)絡(luò)創(chuàng)建,這時主機之間不能相互通信。
一旦用戶創(chuàng)建虛擬網(wǎng)絡(luò),則主機就能夠被添加。
在 PACKET-IN 消息轉(zhuǎn)發(fā)實現(xiàn)前,模塊將啟動。
一旦,一條 PACKET-IN 消息被接受,模塊將查看源 MAC 地址和目的 MAC 地址,如果2個 MAC 地址是同一個虛擬網(wǎng)絡(luò),模塊將返回 Command.CONINUE消息,并且繼續(xù)處理流。如果MAC 地址不在同一個虛擬網(wǎng)絡(luò)則返回 Command.STOP 消息,并丟棄包

限制

必須在同一個物理數(shù)據(jù)鏈路層中

每個虛擬網(wǎng)絡(luò)只能擁有一個網(wǎng)關(guān)()【一個網(wǎng)關(guān)可被多個虛擬網(wǎng)絡(luò)共享】

多播和廣播沒有被隔離

允許所有的 DHCP 路徑

配置

該模塊可用于 OpenStack 的部署
包含此模塊的默認(rèn)配置文件位置:
src/main/resources/neutron.properties

IOFMessageListener 的 receive 方法

    @Override
    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
        switch (msg.getType()) {
        case PACKET_IN:
            return processPacketIn(sw, (OFPacketIn)msg, cntx);
        default:
            break;
        }
        log.warn("Received unexpected message {}", msg);
        return Command.CONTINUE;
    }

主要使用了processPacketIn()方法

    protected Command processPacketIn(IOFSwitch sw, OFPacketIn msg, FloodlightContext cntx) {
        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
                IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
        Command ret = Command.STOP;
        String srcNetwork = macToGuid.get(eth.getSourceMACAddress());
        // If the host is on an unknown network we deny it.
        // We make exceptions for ARP and DHCP.
        if (eth.isBroadcast() || eth.isMulticast() || isDefaultGateway(eth) || isDhcpPacket(eth)) {
            ret = Command.CONTINUE;
        } else if (srcNetwork == null) {
            log.trace("Blocking traffic from host {} because it is not attached to any network.",
                    eth.getSourceMACAddress().toString());
            ret = Command.STOP;
        } else if (oneSameNetwork(eth.getSourceMACAddress(), eth.getDestinationMACAddress())) {
            // if they are on the same network continue
            ret = Command.CONTINUE;
        }

        if (log.isTraceEnabled())
            log.trace("Results for flow between {} and {} is {}",
                    new Object[] {eth.getSourceMACAddress(), eth.getDestinationMACAddress(), ret});
        /*
         * TODO - figure out how to still detect gateways while using
         * drop mods
        if (ret == Command.STOP) {
            if (!(eth.getPayload() instanceof ARP))
                doDropFlow(sw, msg, cntx);
        }
         */
        return ret;
    }
LoadBalancer

IOFMessageListener 的 receive 方法

    @Override
    public net.floodlightcontroller.core.IListener.Command
            receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
        switch (msg.getType()) {
            case PACKET_IN:
                return processPacketIn(sw, (OFPacketIn)msg, cntx);
            default:
                break;
        }
        log.warn("Received unexpected message {}", msg);
        return Command.CONTINUE;
    }

主要使用了processPacketIn()方法

    private net.floodlightcontroller.core.IListener.Command processPacketIn(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
        
        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
        IPacket pkt = eth.getPayload(); 
 
        if (eth.isBroadcast() || eth.isMulticast()) {
            // handle ARP for VIP
            if (pkt instanceof ARP) {
                // retrieve arp to determine target IP address                                                       
                ARP arpRequest = (ARP) eth.getPayload();

                IPv4Address targetProtocolAddress = arpRequest.getTargetProtocolAddress();

                if (vipIpToId.containsKey(targetProtocolAddress.getInt())) {
                    String vipId = vipIpToId.get(targetProtocolAddress.getInt());
                    vipProxyArpReply(sw, pi, cntx, vipId);
                    return Command.STOP;
                }
            }
        } else {
            // currently only load balance IPv4 packets - no-op for other traffic 
            if (pkt instanceof IPv4) {
                IPv4 ip_pkt = (IPv4) pkt;
                
                // If match Vip and port, check pool and choose member
                int destIpAddress = ip_pkt.getDestinationAddress().getInt();
                
                if (vipIpToId.containsKey(destIpAddress)){
                    IPClient client = new IPClient();
                    client.ipAddress = ip_pkt.getSourceAddress();
                    client.nw_proto = ip_pkt.getProtocol();
                    if (ip_pkt.getPayload() instanceof TCP) {
                        TCP tcp_pkt = (TCP) ip_pkt.getPayload();
                        client.srcPort = tcp_pkt.getSourcePort();
                        client.targetPort = tcp_pkt.getDestinationPort();
                    }
                    if (ip_pkt.getPayload() instanceof UDP) {
                        UDP udp_pkt = (UDP) ip_pkt.getPayload();
                        client.srcPort = udp_pkt.getSourcePort();
                        client.targetPort = udp_pkt.getDestinationPort();
                    }
                    if (ip_pkt.getPayload() instanceof ICMP) {
                        client.srcPort = TransportPort.of(8); 
                        client.targetPort = TransportPort.of(0); 
                    }
                    
                    LBVip vip = vips.get(vipIpToId.get(destIpAddress));
                    if (vip == null)            // fix dereference violations           
                        return Command.CONTINUE;
                    LBPool pool = pools.get(vip.pickPool(client));
                    if (pool == null)            // fix dereference violations
                        return Command.CONTINUE;
                    LBMember member = members.get(pool.pickMember(client));
                    if(member == null)            //fix dereference violations
                        return Command.CONTINUE;
                    
                    // for chosen member, check device manager and find and push routes, in both directions                    
                    pushBidirectionalVipRoutes(sw, pi, cntx, client, member);
                   
                    // packet out based on table rule
                    pushPacket(pkt, sw, pi.getBufferId(), (pi.getVersion().compareTo(OFVersion.OF_12) < 0) ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT), OFPort.TABLE,
                                cntx, true);

                    return Command.STOP;
                }
            }
        }
        // bypass non-load-balanced traffic for normal processing (forwarding)
        return Command.CONTINUE;
    }
ForwardingBase

IOFMessageListener 的 receive 方法

     @Override
    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
        switch (msg.getType()) {
        case PACKET_IN:
            IRoutingDecision decision = null;
            if (cntx != null) {
                decision = RoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
            }

            return this.processPacketInMessage(sw, (OFPacketIn) msg, decision, cntx);
        default:
            break;
        }
        return Command.CONTINUE;
    }

主要使用了processPacketInMessage()方法

    public abstract Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, 
            IRoutingDecision decision, FloodlightContext cntx);

所有繼承了 ForwardingBase 的子類Forwarding重寫了這個方法,實現(xiàn)具體的操作

    @Override
    public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) {
        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
        // We found a routing decision (i.e. Firewall is enabled... it"s the only thing that makes RoutingDecisions)
        if (decision != null) {
            if (log.isTraceEnabled()) {
                log.trace("Forwarding decision={} was made for PacketIn={}", decision.getRoutingAction().toString(), pi);
            }

            switch(decision.getRoutingAction()) {
            case NONE:
                // don"t do anything
                return Command.CONTINUE;
            case FORWARD_OR_FLOOD:
            case FORWARD:
                doForwardFlow(sw, pi, decision, cntx, false);
                return Command.CONTINUE;
            case MULTICAST:
                // treat as broadcast
                doFlood(sw, pi, decision, cntx);
                return Command.CONTINUE;
            case DROP:
                doDropFlow(sw, pi, decision, cntx);
                return Command.CONTINUE;
            default:
                log.error("Unexpected decision made for this packet-in={}", pi, decision.getRoutingAction());
                return Command.CONTINUE;
            }
        } else { // No routing decision was found. Forward to destination or flood if bcast or mcast.
            if (log.isTraceEnabled()) {
                log.trace("No decision was made for PacketIn={}, forwarding", pi);
            }

            if (eth.isBroadcast() || eth.isMulticast()) {
                doFlood(sw, pi, decision, cntx);
            } else {
                doForwardFlow(sw, pi, decision, cntx, false);
            }
        }

        return Command.CONTINUE;
    }
PACKET-IN

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/76540.html

相關(guān)文章

  • Floodlight 源碼解讀 :Main

    摘要:每個具體的模塊都會重寫這幾個函數(shù),下面舉個的例子。獲得的服務(wù)返回服務(wù)實現(xiàn)類和實現(xiàn)用的對象的。服務(wù)是指繼承了接口的類。模塊使用方法可以獲得對應(yīng)的服務(wù)列表,可以到源碼去看對應(yīng)的服務(wù)功能。 Floodlight 的 Main 解析圖 showImg(https://segmentfault.com/img/remote/1460000015816841?w=2048&h=2341); 需要...

    verano 評論0 收藏0
  • React 源碼深度解讀(三):首次 DOM 元素渲染 - Part 3

    摘要:在學(xué)習(xí)源碼的過程中,給我?guī)椭畲蟮木褪沁@個系列文章,于是決定基于這個系列文章談一下自己的理解。到此為止,首次渲染就完成啦總結(jié)從啟動到元素渲染到頁面,并不像看起來這么簡單,中間經(jīng)歷了復(fù)雜的層級調(diào)用。 前言 React 是一個十分龐大的庫,由于要同時考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級非常深,閱讀其源碼是一個非常艱辛的過...

    U2FsdGVkX1x 評論0 收藏0
  • React 源碼深度解讀(六):依賴注入

    摘要:依賴注入和控制反轉(zhuǎn),這兩個詞經(jīng)常一起出現(xiàn)。一句話表述他們之間的關(guān)系依賴注入是控制反轉(zhuǎn)的一種實現(xiàn)方式。而兩者有大量的代碼都是可以共享的,這就是依賴注入的使用場景了。下一步就是創(chuàng)建具體的依賴內(nèi)容,然后注入到需要的地方這里的等于這個對象。 前言 React 是一個十分龐大的庫,由于要同時考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級...

    glumes 評論0 收藏0
  • 來一打前端博客壓壓驚

    前言 本文所有內(nèi)容全部發(fā)布再個人博客主頁 https://github.com/muwoo/blogs歡迎訂閱。不過最近因為事情比較多,有一段時間沒有更新了,后面打算繼續(xù)不斷學(xué)習(xí)更新,歡迎小伙伴一起溝通交流~ 最近更新 前端單測的那些事 基于virtual dom 的canvas渲染 js Event loop 機制簡介 axios 核心源碼實現(xiàn)原理 JS 數(shù)據(jù)類型、賦值、深拷貝和淺拷貝 j...

    wangbinke 評論0 收藏0
  • 來一打前端博客壓壓驚

    前言 本文所有內(nèi)容全部發(fā)布再個人博客主頁 https://github.com/muwoo/blogs歡迎訂閱。不過最近因為事情比較多,有一段時間沒有更新了,后面打算繼續(xù)不斷學(xué)習(xí)更新,歡迎小伙伴一起溝通交流~ 最近更新 前端單測的那些事 基于virtual dom 的canvas渲染 js Event loop 機制簡介 axios 核心源碼實現(xiàn)原理 JS 數(shù)據(jù)類型、賦值、深拷貝和淺拷貝 j...

    villainhr 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<