ONOS源码笔记--实现

app生命周期

@Activate
public void activate(ComponentContext context ) {
    cfgService.registerProperties(getClass());
    appId = coreService .registerApplication("org.onosproject.fwd");

    packetService.addProcessor(processor , PacketProcessor.director(2));
    topologyService.addListener(topologyListener );
    readComponentConfiguration( context);
    requestIntercepts();

    log.info("Started" , appId .id());
}

@Deactivate
public void deactivate() {
    cfgService.unregisterProperties(getClass(), false);
    withdrawIntercepts();
    flowRuleService.removeFlowRulesById(appId );
    packetService.removeProcessor(processor );
    topologyService.removeListener(topologyListener );
    processor = null ;
    log.info("Stopped" );
}

@Modified
public void modified(ComponentContext context ) {
    readComponentConfiguration( context);
    requestIntercepts();
}

常见功能函数

// Indicates whether this is a control packet, e.g. LLDP, BDDP
// 判断是否为控制数据包
private boolean isControlPacket(Ethernet eth ) {
    short type = eth.getEtherType();
    return type == Ethernet.TYPE_LLDP || type == Ethernet.TYPE_BSN;
}

// Indicated whether this is an IPv6 multicast packet.
// 判断是否为ipv6多播包
private boolean isIpv6Multicast(Ethernet eth ) {
    return eth .getEtherType() == Ethernet.TYPE_IPV6 && eth.isMulticast();
}

// Selects a path from the given set that does not lead back to the
// specified port if possible.
// 在一个给定的path集合中选择一条不通过指定端口的路径
private Path pickForwardPathIfPossible(Set<Path> paths, PortNumber notToPort) {
    Path lastPath = null ;
    for (Path path : paths) {
        lastPath = path ;
        if (!path .src().port().equals(notToPort)) {
            return path ;
        }
    }
    return lastPath ;
}

// Floods the specified packet if permissible.
// 看看数据包从哪儿来,要是广播,泛洪出去
private void flood(PacketContext context ) {
    if (topologyService.isBroadcastPoint(topologyService .currentTopology(),
                                         context.inPacket().receivedFrom())) {
        packetOut( context, PortNumber.FLOOD);
    } else {
        context.block();
    }
}

// Sends a packet out the specified port.
// 把数据包从指定端口发出,一般映射为交换机的某个网卡,其实这是两个过程,可以分开
private void packetOut(PacketContext context , PortNumber portNumber) {
    context.treatmentBuilder().setOutput(portNumber );
    context.send();
}

// Install a rule forwarding the packet to the specified port.
// 按需制定流表规则,并发出,很自动化,其实可以分开实现
private void installRule(PacketContext context , PortNumber portNumber) {
    //
    // We don't support (yet) buffer IDs in the Flow Service so
    // packet out first.
    //
    Ethernet inPkt = context .inPacket().parsed();
    TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();

    // If PacketOutOnly or ARP packet than forward directly to output port
    if (packetOutOnly || inPkt.getEtherType() == Ethernet. TYPE_ARP) {
        packetOut( context, portNumber );
        return;
    }

    //
    // If matchDstMacOnly
    //    Create flows matching dstMac only
    // Else
    //    Create flows with default matching and include configured fields
    //
    if (matchDstMacOnly ) {
        selectorBuilder.matchEthDst(inPkt .getDestinationMAC());
    } else {
        selectorBuilder.matchInPort(context .inPacket().receivedFrom().port())
                .matchEthSrc( inPkt.getSourceMAC())
                .matchEthDst( inPkt.getDestinationMAC());

        // If configured Match Vlan ID
        if (matchVlanId && inPkt.getVlanID() != Ethernet.VLAN_UNTAGGED ) {
            selectorBuilder.matchVlanId(VlanId.vlanId( inPkt.getVlanID()));
        }

        //
        // If configured and EtherType is IPv4 - Match IPv4 and
        // TCP/UDP/ICMP fields
        //
        if (matchIpv4Address && inPkt.getEtherType() == Ethernet.TYPE_IPV4 ) {
            IPv4 ipv4Packet = (IPv4) inPkt .getPayload();
            byte ipv4Protocol = ipv4Packet.getProtocol();
            Ip4Prefix matchIp4SrcPrefix =
                    Ip4Prefix. valueOf(ipv4Packet.getSourceAddress(),
                                      Ip4Prefix. MAX_MASK_LENGTH);
            Ip4Prefix matchIp4DstPrefix =
                    Ip4Prefix.valueOf(ipv4Packet.getDestinationAddress(),
                                      Ip4Prefix. MAX_MASK_LENGTH);
            selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
                    .matchIPSrc( matchIp4SrcPrefix)
                    .matchIPDst( matchIp4DstPrefix);

            if (matchIpv4Dscp ) {
                byte dscp = ipv4Packet.getDscp();
                byte ecn = ipv4Packet.getEcn();
                selectorBuilder.matchIPDscp(dscp ).matchIPEcn(ecn);
            }

            if (matchTcpUdpPorts && ipv4Protocol == IPv4.PROTOCOL_TCP ) {
                TCP tcpPacket = (TCP) ipv4Packet .getPayload();
                selectorBuilder.matchIPProtocol(ipv4Protocol )
                        .matchTcpSrc(TpPort.tpPort(tcpPacket.getSourcePort()))
                        .matchTcpDst(TpPort.tpPort(tcpPacket.getDestinationPort()));
            }
            if (matchTcpUdpPorts && ipv4Protocol == IPv4.PROTOCOL_UDP ) {
                UDP udpPacket = (UDP) ipv4Packet .getPayload();
                selectorBuilder.matchIPProtocol(ipv4Protocol )
                        .matchUdpSrc(TpPort.tpPort(udpPacket.getSourcePort()))
                        .matchUdpDst(TpPort.tpPort(udpPacket.getDestinationPort()));
            }
            if (matchIcmpFields && ipv4Protocol == IPv4.PROTOCOL_ICMP ) {
                ICMP icmpPacket = (ICMP) ipv4Packet .getPayload();
                selectorBuilder.matchIPProtocol(ipv4Protocol )
                        .matchIcmpType( icmpPacket.getIcmpType())
                        .matchIcmpCode( icmpPacket.getIcmpCode());
            }
        }

        //
        // If configured and EtherType is IPv6 - Match IPv6 and
        // TCP/UDP/ICMP fields
        //
        if (matchIpv6Address && inPkt.getEtherType() == Ethernet.TYPE_IPV6 ) {
            IPv6 ipv6Packet = (IPv6) inPkt .getPayload();
            byte ipv6NextHeader = ipv6Packet.getNextHeader();
            Ip6Prefix matchIp6SrcPrefix =
                    Ip6Prefix. valueOf(ipv6Packet.getSourceAddress(),
                                      Ip6Prefix. MAX_MASK_LENGTH);
            Ip6Prefix matchIp6DstPrefix =
                    Ip6Prefix.valueOf(ipv6Packet.getDestinationAddress(),
                                      Ip6Prefix. MAX_MASK_LENGTH);
            selectorBuilder.matchEthType(Ethernet.TYPE_IPV6)
                    .matchIPv6Src( matchIp6SrcPrefix)
                    .matchIPv6Dst( matchIp6DstPrefix);

            if (matchIpv6FlowLabel ) {
                selectorBuilder.matchIPv6FlowLabel(ipv6Packet .getFlowLabel());
            }

            if (matchTcpUdpPorts && ipv6NextHeader == IPv6.PROTOCOL_TCP ) {
                TCP tcpPacket = (TCP) ipv6Packet .getPayload();
                selectorBuilder.matchIPProtocol(ipv6NextHeader )
                        .matchTcpSrc(TpPort.tpPort(tcpPacket.getSourcePort()))
                        .matchTcpDst(TpPort.tpPort(tcpPacket.getDestinationPort()));
            }
            if (matchTcpUdpPorts && ipv6NextHeader == IPv6.PROTOCOL_UDP ) {
                UDP udpPacket = (UDP) ipv6Packet .getPayload();
                selectorBuilder.matchIPProtocol(ipv6NextHeader )
                        .matchUdpSrc(TpPort.tpPort(udpPacket.getSourcePort()))
                        .matchUdpDst(TpPort.tpPort(udpPacket.getDestinationPort()));
            }
            if (matchIcmpFields && ipv6NextHeader == IPv6.PROTOCOL_ICMP6 ) {
                ICMP6 icmp6Packet = (ICMP6) ipv6Packet .getPayload();
                selectorBuilder.matchIPProtocol(ipv6NextHeader )
                        .matchIcmpv6Type( icmp6Packet.getIcmpType())
                        .matchIcmpv6Code( icmp6Packet.getIcmpCode());
            }
        }
    }
    TrafficTreatment treatment = DefaultTrafficTreatment.builder()
            .setOutput( portNumber)
            .build();

    ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
            .withSelector( selectorBuilder.build())
            .withTreatment( treatment)
            .withPriority( flowPriority)
            .withFlag(ForwardingObjective.Flag. VERSATILE)
            .fromApp( appId)
            .makeTemporary( flowTimeout)
            .add();

    flowObjectiveService.forward(context .inPacket().receivedFrom().deviceId(),
                                 forwardingObjective);

    //
    // If packetOutOfppTable
    //  Send packet back to the OpenFlow pipeline to match installed flow
    // Else
    //  Send packet direction on the appropriate port
    //
    if (packetOutOfppTable ) {
        packetOut( context, PortNumber.TABLE);
    } else {
        packetOut( context, portNumber );
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值