ONOS源码笔记--机制

app注册

private ApplicationId appId;

    appId = coreService .registerApplication("org.onosproject.fwd");
    //注册应用,一般在activate函数中完成

拓扑监听器

//自定义拓扑监听器,覆盖event函数,具体功能可自己实现,这里是避免路由黑洞
private class InternalTopologyListener implements TopologyListener {
    @Override
    public void event(TopologyEvent event) {
        List< Event> reasons = event.reasons();
        if (reasons != null) {
            reasons.forEach(re -> {
                if (re instanceof LinkEvent) {
                    LinkEvent le = (LinkEvent) re;
                    if (le .type() == LinkEvent.Type.LINK_REMOVED) {
                        fixBlackhole( le.subject().src());
                    }
                }
            });
        }
    }
}

private final TopologyListener topologyListener = new InternalTopologyListener();
//定义一个拓扑监听器

    topologyService.addListener( topologyListener);
    //添加监听器,般在activate函数中完成

设备监听器

/**
 * Listener to Device Event and OVSDB connection.
 * 这段代码来自github,供参考。网址:https://github.com/MaoJianwei/ONOS_OVS_Manager_Bootcamp2016
 */
private class InnerDeviceListener implements DeviceListener {
    @Override
    public void event(DeviceEvent event) {

        if (!event.type().equals(DeviceEvent.Type.DEVICE_ADDED)) {
            return;
        }

        Device device = event.subject();

        if (device.type() == Device.Type.CONTROLLER) {
            dealController(device.id());
        } else {
            dealSwitch(device.id());
        }
    }

    /**
     * Catch the new OVSDB connection.
     * @param deviceId : The OVSDB connection ID.
     */
    private void dealController(DeviceId deviceId) {
        controllerId = deviceId;
        log.info( "controllerId is ready !!!" );
    }

    /**
     * Separate two type of switches.
     * @param deviceId : The DeviceId of target device.
     */
    private void dealSwitch(DeviceId deviceId) {
        String datapathId = deviceId.toString().split( ":")[1];
        if (Integer.valueOf(datapathId) > CORE_DEVICEID_CARDINALITY) {
            dealCoreSwitch(deviceId);
        } else {
            dealAccessSwitch(deviceId);
        }
    }

    /**
     * Add specific ForwardingObject to CORE switch.
     * @param deviceId : The DeviceId of target device.
     */
    private void dealCoreSwitch(DeviceId deviceId) {
        TrafficSelector.Builder trafficSelectorBuilder0 = DefaultTrafficSelector.builder();
        trafficSelectorBuilder0.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
                .matchIPDst(IpPrefix.valueOf( "192.168.1.1/28"))
                .matchIPSrc(IpPrefix.valueOf( "1.2.3.4/32"));

        TrafficTreatment.Builder trafficTreatmentBuilder0 = DefaultTrafficTreatment.builder();
        trafficTreatmentBuilder0.setEthDst(MacAddress.BROADCAST).transition(1);

        addForward(deviceId, BOTH_TABLE_PRIORITY,
                   trafficSelectorBuilder0.build(), trafficTreatmentBuilder0.build());
    }

    /**
     * Add specific ForwardingObject to ACCESS switch.
     * @param deviceId : The DeviceId of target device.
     */
    private void dealAccessSwitch(DeviceId deviceId) {
        TrafficSelector.Builder trafficSelectorBuilder0 = DefaultTrafficSelector.builder();
        trafficSelectorBuilder0.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
                .matchIPSrc(IpPrefix.valueOf( "10.0.0.0/24"));

        TrafficTreatment.Builder trafficTreatmentBuilder0 = DefaultTrafficTreatment.builder();
        trafficTreatmentBuilder0.setEthDst(MacAddress.BROADCAST).transition(1);

        addForward(deviceId, BOTH_TABLE_PRIORITY,
                   trafficSelectorBuilder0.build(), trafficTreatmentBuilder0.build());


        TrafficSelector.Builder trafficSelectorBuilder1 = DefaultTrafficSelector.builder();
        trafficSelectorBuilder1.matchEthDst(MacAddress.BROADCAST);

        TrafficTreatment.Builder trafficTreatmentBuilder1 = DefaultTrafficTreatment.builder();
        trafficTreatmentBuilder1.drop();

        addForward(deviceId, BOTH_TABLE_PRIORITY,
                   trafficSelectorBuilder1.build(), trafficTreatmentBuilder1.build());
    }

    /**
     * Utility method to add ForwardingObjective.
     * @param deviceId : The DeviceId of target device.
     * @param priority : Priority of ForwardingObjective.
     * @param selector : Match fields.
     * @param treatment : Instructions.
     */
    private void addForward(DeviceId deviceId, int priority, TrafficSelector selector, TrafficTreatment treatment) {

        ForwardingObjective.Builder forwardingObjectiveBuilder = DefaultForwardingObjective.builder();
        forwardingObjectiveBuilder
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withTreatment(treatment)
                .withSelector(selector)
                .withPriority(priority)
                .fromApp(applicationId)
                .makePermanent();

        flowObjectiveService.forward(deviceId, forwardingObjectiveBuilder.add());
    }
}


private InnerDeviceListener innerDeviceListener;
innerDeviceListener = new InnerDeviceListener();

deviceService.addListener(innerDeviceListener);//一般放在activate中

包处理器

/**
 * Packet processor responsible for forwarding packets along their paths.
 * 主要为process函数,处理的是一个PacketContext,在开发自己的应用时对于包的处理
 * 可以从这段代码中得到启发。
 */
private class ReactivePacketProcessor implements PacketProcessor {

    @Override
    public void process (PacketContext context ) {
        // Stop processing if the packet has been handled, since we
        // can't do any more to it.

        if (context .isHandled()) {
            return;
        }

        InboundPacket pkt = context .inPacket();
        Ethernet ethPkt = pkt .parsed();

        if (ethPkt == null) {
            return;
        }

        // Bail if this is deemed to be a control packet.
        if (isControlPacket(ethPkt )) {
            return;
        }

        // Skip IPv6 multicast packet when IPv6 forward is disabled.
        if (!ipv6Forwarding && isIpv6Multicast(ethPkt)) {
            return;
        }

        HostId id = HostId. hostId(ethPkt.getDestinationMAC());

        // Do not process link-local addresses in any way.
        if (id .mac().isLinkLocal()) {
            return;
        }

        // Do not process IPv4 multicast packets, let mfwd handle them
        if (ignoreIpv4McastPackets && ethPkt.getEtherType() == Ethernet.TYPE_IPV4 ) {
            if (id .mac().isMulticast()) {
                return;
            }
        }

        // Do we know who this is for? If not, flood and bail.
        Host dst = hostService .getHost(id);
        if (dst == null) {
            flood( context);
            return;
        }

        // Are we on an edge switch that our destination is on? If so,
        // simply forward out to the destination and bail.
        if (pkt.receivedFrom().deviceId().equals(dst .location().deviceId())) {
            if (!context.inPacket().receivedFrom().port().equals(dst.location().port())) {
                installRule( context, dst .location().port());
            }
            return;
        }

        // Otherwise, get a set of paths that lead from here to the
        // destination edge switch.
        Set paths =
                topologyService.getPaths(topologyService .currentTopology(),
                                         pkt.receivedFrom().deviceId(),
                                         dst.location().deviceId());
        if (paths .isEmpty()) {
            // If there are no paths, flood and bail.
            flood( context);
            return;
        }

        // Otherwise, pick a path that does not lead back to where we
        // came from; if no such path, flood and bail.
        Path path = pickForwardPathIfPossible(paths , pkt.receivedFrom().port());
        if (path == null) {
            log.warn("Don't know where to go from here {} for {} -> {}",
                     pkt.receivedFrom(), ethPkt .getSourceMAC(), ethPkt.getDestinationMAC());
            flood( context);
            return;
        }

        // Otherwise forward and be done with it.
        installRule( context, path .src().port());
    }

}

private ReactivePacketProcessor processor = new ReactivePacketProcessor();
//Packet processor responsible for forwarding packets along their paths.
//负责数据包在特定路径上转发的数据包处理器

    packetService.addProcessor(processor , PacketProcessor.director(2));
    //添加包处理器,一般放在activate函数中

流表下发与删除过程

   /*
   * 制定流表规则,比较重要的部分有两个:
   * 一个是selector,用来指定源目的 ip,源目的mac,源目的port
   * 另一个treatment,用来说明怎么处理包,丢弃还是转发,从哪儿转发
   * 再有就是确定优先级,然后发到哪个设备上 
   */
   private void installRule(TrafficSelector selector, TrafficTreatment treatment , DeviceId deviceId, int priority ){

        ForwardingObjective.Builder forwardingObjectiveBuilder = DefaultForwardingObjective.builder();
         forwardingObjectiveBuilder
                    .withFlag(ForwardingObjective.Flag. VERSATILE)
                    .withSelector( selector)
                    .withTreatment( treatment)
                    .withPriority( priority)
                    .makePermanent()
                    .fromApp( appId);
         flowObjectiveService.forward(deviceId , forwardingObjectiveBuilder .add());
  }

   //流表下发测试函数,当前拓扑中的交换机都发一遍
   private void testInstallRules(){

         src_ip_0 = 10;
         src_ip_1 = 0;
         src_ip_2 = 0;
         src_ip_3 = 1;
         des_ip_0 =10;
         des_ip_1 = 0;
         des_ip_2 = 0;
         des_ip_3 = 2;
         src_port = 8011;
         des_port = 8012;

         byte[] ip = {(byte) src_ip_0, (byte )src_ip_1 , (byte) src_ip_2, (byte)src_ip_3 };
        IpAddress src_ip = IpAddress.valueOf(IpAddress.Version. INET, ip);
        Host src_host = getHostByIp(src_ip );

         byte[] ips = {(byte) des_ip_0, (byte )des_ip_1 , (byte)des_ip_2 , (byte) des_ip_3};
        IpAddress des_ip = IpAddress.valueOf(IpAddress.Version. INET, ips);
        Host des_host = getHostByIp(des_ip );

        MacAddress src_mac = src_host .mac();
        MacAddress des_mac = des_host .mac();

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        TrafficSelector selector = selectorBuilder.matchEthSrc(src_mac )
                    .matchEthDst( des_mac)
                    .matchEthType(Ethernet. TYPE_IPV4)
                    .matchIPSrc(Ip4Prefix. valueOf(src_ip, Ip4Prefix.MAX_MASK_LENGTH ))
                    .matchIPDst(Ip4Prefix. valueOf(des_ip, Ip4Prefix.MAX_MASK_LENGTH ))
                    .matchIPProtocol(org.onlab.packet.IPv4. PROTOCOL_UDP)
                    .matchTcpSrc(TpPort. tpPort(src_port))
                    .matchTcpDst(TpPort. tpPort(des_port))
                    .build();
        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                    .setEthDst( des_mac)
                    .build();

        Iterator devices = deviceService.getDevices(Type.SWITCH).iterator();
         while(devices .hasNext()){
              Device device = devices .next();
              DeviceId deviceId = device .id();
               //log.info(deviceId.toString());
              installRule( selector, treatment , deviceId , 10);
        }
  }

   // 删除流表
private void cleanFlowRules(SrcDstPair pair , DeviceId id) {
    log.info(">>>>>Searching for flow rules to remove from: " + id);
    log.info(">>>>>Removing flows w/ SRC=" + pair.src + ", DST=" + pair.dst );
         for (FlowEntry r : flowRuleService.getFlowEntries( id)) {


        boolean matchesSrc = false, matchesDst = false ;
        for (Instruction i : r.treatment().allInstructions()) {
            if (i .type() == Instruction.Type.OUTPUT) {
                // if the flow has matching src and dst
                for (Criterion cr : r.selector().criteria()) {
                    if (cr .type() == Criterion.Type.ETH_DST) {
                        if (((EthCriterion) cr).mac().equals(pair .dst )) {
                            matchesDst = true ;
                        }
                    } else if (cr .type() == Criterion.Type.ETH_SRC) {
                        if (((EthCriterion) cr).mac().equals(pair .src )) {
                            matchesSrc = true ;
                        }
                    }
                }
            }
        }
        if (matchesDst && matchesSrc) {
            log.info(">>>>>Removed flow rule from device: " + id);
            flowRuleService.removeFlowRules((FlowRule) r );
        }
    }

}
   //流表删除测试函数
   private void testCleanRules(){

         src_ip_0 = 10;
         src_ip_1 = 0;
         src_ip_2 = 0;
         src_ip_3 = 1;
         des_ip_0 =10;
         des_ip_1 = 0;
         des_ip_2 = 0;
         des_ip_3 = 2;
         src_port = 8013;
         des_port = 8014;

         byte[] ip = {(byte) src_ip_0, (byte )src_ip_1 , (byte) src_ip_2, (byte)src_ip_3 };
        IpAddress src_ip = IpAddress.valueOf(IpAddress.Version. INET, ip);
        Host src_host = getHostByIp(src_ip );

         byte[] ips = {(byte) des_ip_0, (byte )des_ip_1 , (byte)des_ip_2 , (byte) des_ip_3};
        IpAddress des_ip = IpAddress.valueOf(IpAddress.Version. INET, ips);
        Host des_host = getHostByIp(des_ip );

        MacAddress src_mac = src_host .mac();
        MacAddress des_mac = des_host .mac();

        Iterator devices = deviceService.getDevices(Type.SWITCH).iterator();
         while(devices .hasNext()){
              Device device = devices .next();
              DeviceId deviceId = device .id();
               //log.info(deviceId.toString());
              SrcDstPair pair = new SrcDstPair(src_mac, des_mac);
              cleanFlowRules( pair, deviceId );
        }
  }

你可能感兴趣的:(ONOS)