• Floodlight中 处理packetin消息的顺序(1)



    当Controller和SW建立连接之后,就能够处理来自SW的各种OF msg。当接收到 packetin 消息之后,会将其分发给各个监听了这个OFMessage的listeners,所以假设我们要设计自己的控制器模块,仅仅须要实现对应的接口方法。约定运行顺序就可以。

    接口IListener 主要抽象了监听器模块的名字,运行顺序,接口IOFMessageListener则抽象了我们的Controller怎样处理详细的这个openflow消息。这里通过阅读代码来推断这些模块处理packetin消息的相对顺序。



    public interface IListener<T> {
        public enum Command {
            CONTINUE STOP
        }
       
        //这个监听者的名字
        public String getName();

        //名为name的module在处理这个消息的时候,要在这个module之前
        public boolean isCallbackOrderingPrereq(T type, String name);

        //在处理type消息的时候,name_module 要在这个模块之后
        public boolean isCallbackOrderingPostreq(T type, String name);
    }

    public interface IOFMessageListener extends IListener< OFType> {
          //Floodlight利用这种方法呼叫这些listeners来处理这个OF MSG;
           public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx);
    }

    通过查看type hierarchy能够知道全部实现了这个接口的模块。



    接下来看看详细细节。

    1.Divice manager 要在topology之前。

         @Override
        public String getName() {
            return "devicemanager" ;
        }

        @Override
        public boolean isCallbackOrderingPrereq(OFType type, String name) {
            return ((type == OFType.PACKET_IN || type == OFType.FLOW_MOD)
                    && name.equals( "topology" ));
        }

        @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:
                    return this .processPacketInMessage(sw,(OFPacketIn) msg, cntx);
            }

            logger.error("received an unexpected message {} from switch {}",
                         msg, sw);
            return Command.CONTINUE;
        }


    2. LinkDiscoveryManager 中没有做出对顺序的规定,由其它模块来约束的。
             @Override
             public String getName() {
                 return "linkdiscovery" ;
             }
            
             @Override
             public Command receive( IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
                 switch (msg.getType()) {
                     case PACKET_IN:
                         return this .handlePacketIn(sw, (OFPacketIn) msg, cntx);
                     case PORT_STATUS:
                         return this .handlePortStatus(sw, (OFPortStatus) msg);
                 }

                 log.error( "Received an unexpected message {} from switch {}", msg, sw);
                 return Command.CONTINUE;
             }

    3. TopologyManager要在 LinkDiscoveryManager 之后操作。
        @Override
        public String getName() {
            return "topology" ;
        }

        @Override
        public boolean isCallbackOrderingPrereq(OFType type, String name) {
            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:
                    return this .processPacketInMessage(sw,
                                                       (OFPacketIn) msg, cntx);
            }

            log.error("received an unexpected message {} from switch {}",
                      msg, sw);
            return Command.CONTINUE;
        }
    4.OFMessageFilterManager 模块在处理packetin消息时的顺序在 DeviceManager 之后,LearningSwitch 之前。这个模块的作用是同意我们加入一些过滤规则。
              @Override
             public String getName() {
                 return "messageFilterManager" ;
             }

             @Override
             public boolean isCallbackOrderingPrereq(OFType type, String name) {
                 return (type == OFType.PACKET_IN && name.equals("devicemanager" ));
             }

             @Override
             public boolean isCallbackOrderingPostreq(OFType type, String name) {
                 return (type == OFType.PACKET_IN && name.equals("learningswitch" ));
             }

             @Override
             public Command receive( IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {

                 if (filterMap == null || filterMap.isEmpty()) return Command.CONTINUE;

                 HashSet<String> matchedFilters = null;
                 if (log.isDebugEnabled()) {
                     log.debug( "Received packet {} from switch {}", msg, sw.getStringId());
                 }

                 matchedFilters = getMatchedFilters(msg, cntx);
                 if (matchedFilters == null) {
                     return Command.CONTINUE;
                 } else {
                     try {
                         sendPacket(matchedFilters, sw, msg, cntx, true );
                     } catch (TException e) {
                         log.error( "sendPacket Texception: {}", e);
                     } catch (Exception e) {
                         log.error( "sendPacket exception: {}", e);
                     }
                 }
                
                 return Command.CONTINUE;
             }

    5. VirtualNetworkFilter(二层虚拟网络模块,对于不属于这个虚拟网络的packetin会丢弃)的运行顺序在forwarding之前,在devicemanager。linkdiscoveryManager之后。

        @Override
        public String getName() {
            return "virtualizer" ;
        }

        @Override
        public boolean isCallbackOrderingPrereq(OFType type, String name) {
            // Link discovery should go before us so we don't block LLDPs
            return (type.equals(OFType.PACKET_IN) &&
                  (name.equals( "linkdiscovery" ) || (name.equals("devicemanager" ))));
        }

        @Override
        public boolean isCallbackOrderingPostreq(OFType type, String name) {
            // We need to go before forwarding
            return (type.equals(OFType.PACKET_IN) && name.equals("forwarding" ));
        }

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

    6.ForwardingBase 路由模块未对顺序做限制。
    7.其它的没有查看。

    总结。通过上面的代码阅读能够得到例如以下的结构图:
    7.通过调试得到的Listeners有序输出结果是(最后的Distributing是我们自己加入的模块):
    OF msg PACKET_IN have listeners:[
    net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager@543d8ee8, net.floodlightcontroller.topology.TopologyManager@ea5e9e7, net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl@74e551a4, net.floodlightcontroller.forwarding.Forwarding@76eb235,
     net.floodlightcontroller.dedu.Distributing@76115ae0]



  • 相关阅读:
    spring 自定义事件发布及监听(简单实例)
    解析spring中的BeanFactory(看完会有收获)
    如何提高锁的性能
    spring MVC模式拦截所有入口方法的入参出参打印
    java基于feemarker 生成word文档(超级简单)
    数据库事务特性汇总
    如何让window.open()以post请求方式调用(巧妙解法)
    a标签添加背景图片的解决办法
    深入理解Django Admin的list_display, list_filter和raw_id_fields,filter_horizontal选项
    django配置log日志
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5212954.html
Copyright © 2020-2023  润新知