org.onosproject.ipfix.FlowRemovedListener.java Source code

Java tutorial

Introduction

Here is the source code for org.onosproject.ipfix.FlowRemovedListener.java

Source

/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.ipfix;

import java.util.ArrayList;
import java.util.List;

import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.ipfix.packet.DataRecord;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPDscpCriterion;
import org.onosproject.net.flow.criteria.IPEcnCriterion;
import org.onosproject.net.flow.criteria.IPProtocolCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.Criterion.Type;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.openflow.controller.Dpid;

import com.google.common.primitives.Longs;

/**
 * Flow Rule Listener for detecting flow removal or flow statistics update by ONOS.
 */
public class FlowRemovedListener implements FlowRuleListener {

    private IpfixManager ipfixManager;

    /**
     * Flow Event listerner for Flow removed events of Reactive Forwarding application.
     *
     * @param ipfixManager ipfix manager instance
     */
    public FlowRemovedListener(IpfixManager ipfixManager) {
        this.ipfixManager = ipfixManager;
    }

    @Override
    public void event(FlowRuleEvent event) {
        switch (event.type()) {
        case RULE_REMOVED:
            FlowRule rule = event.subject();
            FlowEntry entry = (FlowEntry) rule;
            if (entry.appId() == ipfixManager.coreService.getAppId("org.onosproject.fwd").id()) {
                flowRemovedRfwd(entry);
            }
            break;
        default:
            break;
        }
    }

    /**
     * Handle ONOS Reactive forwarding application flow removal.
     * When flow is removed, generate and send IPFIX record.
     *
     * @param entry flow entry removed from ONOS
     */
    private void flowRemovedRfwd(FlowEntry entry) {

        //Log
        ipfixManager.log.trace("Flow Removed from Reactive Forwarding, id={}, device={}, selector={}, treatment={}",
                entry.id(), entry.deviceId(), entry.selector(), entry.treatment());

        // Exporters
        IpAddress exporterIpv4 = IpAddress.valueOf(
                ipfixManager.deviceService.getDevice(entry.deviceId()).annotations().toString().split("=")[2]
                        .split(":")[0]);

        long dpid = Dpid.dpid(entry.deviceId().uri()).value();
        byte[] byteExporterIpv6 = new byte[16];
        System.arraycopy(Longs.toByteArray(0), 0, byteExporterIpv6, 0, 8);
        System.arraycopy(Longs.toByteArray(dpid), 0, byteExporterIpv6, 8, 8);
        Ip6Address exporterIpv6 = Ip6Address.valueOf(byteExporterIpv6);

        // Timestamps, octets, packets
        long start = System.currentTimeMillis() - (1000 * entry.life());
        long end = System.currentTimeMillis();
        long octets = entry.bytes();
        long packets = entry.packets();

        // Input and Output ports
        PortCriterion portCrit = (PortCriterion) entry.selector().getCriterion(Type.IN_PORT);
        int intfIn = (portCrit == null) ? 0 : (int) portCrit.port().toLong();
        List<Instruction> instructions = entry.treatment().allInstructions();
        int intfOut = 0;
        for (Instruction instruction : instructions) {
            if (instruction.type() == Instruction.Type.OUTPUT) {
                OutputInstruction outputInstruction = (OutputInstruction) instruction;
                intfOut = (outputInstruction == null) ? 0 : (int) outputInstruction.port().toLong();
            }
        }

        // Ethernet MACs, Ethertype and VLAN
        EthCriterion ethCrit;
        ethCrit = (EthCriterion) entry.selector().getCriterion(Type.ETH_SRC);
        MacAddress srcMac = (ethCrit == null) ? MacAddress.valueOf("00:00:00:00:00:00") : ethCrit.mac();
        ethCrit = (EthCriterion) entry.selector().getCriterion(Type.ETH_DST);
        MacAddress dstMac = (ethCrit == null) ? MacAddress.valueOf("00:00:00:00:00:00") : ethCrit.mac();

        EthTypeCriterion ethTypeCrit = (EthTypeCriterion) entry.selector().getCriterion(Type.ETH_TYPE);
        Short ethType = (ethTypeCrit == null) ? 0x0000 : ethTypeCrit.ethType().toShort();

        VlanIdCriterion vlanCrit = (VlanIdCriterion) entry.selector().getCriterion(Type.VLAN_VID);
        Short vlan = (vlanCrit == null) ? 0x0000 : vlanCrit.vlanId().toShort();

        // IP Criterion check
        IPCriterion srcIpCrit = (IPCriterion) entry.selector().getCriterion(Type.IPV4_SRC);
        IPCriterion dstIpCrit = (IPCriterion) entry.selector().getCriterion(Type.IPV4_DST);
        IPCriterion srcIp6Crit = (IPCriterion) entry.selector().getCriterion(Type.IPV6_SRC);
        IPCriterion dstIp6Crit = (IPCriterion) entry.selector().getCriterion(Type.IPV6_DST);

        // If IP criterions are null send MAC Data Record, else send IPv4 or IPv6 Data Record
        if (srcIpCrit == null && dstIpCrit == null && srcIp6Crit == null && dstIp6Crit == null) {
            DataRecordRfwdMac record = new DataRecordRfwdMac(exporterIpv4, exporterIpv6, start, end, octets,
                    packets, intfIn, intfOut, srcMac, dstMac, ethType, vlan);
            List<DataRecord> recordList = new ArrayList<DataRecord>();
            recordList.add(record);
            ipfixManager.ipfixSender.sendRecords(DataRecordRfwdMac.getTemplateRecord(), recordList, dpid,
                    IpfixManager.collectorIp, IpfixManager.collectorPort);
        } else {
            // Checking IPv4 and IPv6 criterions
            IPProtocolCriterion protocolCrit = (IPProtocolCriterion) entry.selector().getCriterion(Type.IP_PROTO);
            byte ipProtocol = (protocolCrit == null) ? (byte) 0xff : (byte) protocolCrit.protocol();

            IPDscpCriterion dscpCrit = (IPDscpCriterion) entry.selector().getCriterion(Type.IP_DSCP);
            byte dscp = (dscpCrit == null) ? 0x00 : dscpCrit.ipDscp();
            IPEcnCriterion ecnCrit = (IPEcnCriterion) entry.selector().getCriterion(Type.IP_ECN);
            byte ecn = (ecnCrit == null) ? 0x00 : ecnCrit.ipEcn();
            byte tos = (byte) ((byte) (dscp << 2) | ecn);

            IPv6FlowLabelCriterion flowLabelCrit = (IPv6FlowLabelCriterion) entry.selector()
                    .getCriterion(Type.IPV6_FLABEL);
            int flowLabelIpv6 = (flowLabelCrit == null) ? 0 : flowLabelCrit.flowLabel();

            int srcPort = 0;
            int dstPort = 0;
            if (ipProtocol == IPv4.PROTOCOL_TCP) {
                TcpPortCriterion tcpCrit;
                tcpCrit = (TcpPortCriterion) entry.selector().getCriterion(Type.TCP_SRC);
                srcPort = (tcpCrit == null) ? 0 : tcpCrit.tcpPort().toInt();
                tcpCrit = (TcpPortCriterion) entry.selector().getCriterion(Type.TCP_DST);
                dstPort = (tcpCrit == null) ? 0 : tcpCrit.tcpPort().toInt();
            } else if (ipProtocol == IPv4.PROTOCOL_UDP) {
                UdpPortCriterion udpCrit;
                udpCrit = (UdpPortCriterion) entry.selector().getCriterion(Type.UDP_SRC);
                srcPort = (udpCrit == null) ? 0 : udpCrit.udpPort().toInt();
                udpCrit = (UdpPortCriterion) entry.selector().getCriterion(Type.UDP_DST);
                dstPort = (udpCrit == null) ? 0 : udpCrit.udpPort().toInt();
            } else if (ipProtocol == IPv4.PROTOCOL_ICMP) {
                IcmpTypeCriterion icmpTypeCrit = (IcmpTypeCriterion) entry.selector()
                        .getCriterion(Type.ICMPV4_TYPE);
                Short icmpType = (icmpTypeCrit == null) ? 0 : icmpTypeCrit.icmpType();
                IcmpCodeCriterion icmpCodeCrit = (IcmpCodeCriterion) entry.selector()
                        .getCriterion(Type.ICMPV4_CODE);
                Short icmpCode = (icmpCodeCrit == null) ? 0 : icmpCodeCrit.icmpCode();
                dstPort = 256 * icmpType + icmpCode;
            } else if (ipProtocol == IPv6.PROTOCOL_ICMP6) {
                Icmpv6TypeCriterion icmpv6TypeCrit = (Icmpv6TypeCriterion) entry.selector()
                        .getCriterion(Type.ICMPV6_TYPE);
                Short icmpType = (icmpv6TypeCrit == null) ? 0 : icmpv6TypeCrit.icmpv6Type();
                Icmpv6CodeCriterion icmpv6CodeCrit = (Icmpv6CodeCriterion) entry.selector()
                        .getCriterion(Type.ICMPV6_CODE);
                Short icmpCode = (icmpv6CodeCrit == null) ? 0 : icmpv6CodeCrit.icmpv6Code();
                dstPort = 256 * icmpType + icmpCode;
            }
            // If IPv4 than send IPv4 Data record
            if ((srcIpCrit != null || dstIpCrit != null) && ethType == Ethernet.TYPE_IPV4) {
                IpAddress srcIp = (srcIpCrit == null) ? IpAddress.valueOf(0) : srcIpCrit.ip().address();
                IpAddress dstIp = (dstIpCrit == null) ? IpAddress.valueOf(0) : dstIpCrit.ip().address();
                DataRecordRfwdIpv4 record = new DataRecordRfwdIpv4(exporterIpv4, exporterIpv6, start, end, octets,
                        packets, intfIn, intfOut, srcMac, dstMac, ethType, vlan, srcIp, dstIp, ipProtocol, tos,
                        (short) srcPort, (short) dstPort);
                List<DataRecord> recordList = new ArrayList<DataRecord>();
                recordList.add(record);
                ipfixManager.ipfixSender.sendRecords(DataRecordRfwdIpv4.getTemplateRecord(), recordList, dpid,
                        IpfixManager.collectorIp, IpfixManager.collectorPort);
            }
            // If IPv6 than send IPv6 Data record
            if ((srcIp6Crit != null || dstIp6Crit != null) && ethType == Ethernet.TYPE_IPV6) {
                Ip6Address srcIp6 = (srcIp6Crit == null) ? Ip6Address.valueOf("0:0:0:0:0:0:0:0")
                        : srcIp6Crit.ip().address().getIp6Address();
                Ip6Address dstIp6 = (dstIp6Crit == null) ? Ip6Address.valueOf("0:0:0:0:0:0:0:0")
                        : dstIp6Crit.ip().address().getIp6Address();
                DataRecordRfwdIpv6 record = new DataRecordRfwdIpv6(exporterIpv4, exporterIpv6, start, end, octets,
                        packets, intfIn, intfOut, srcMac, dstMac, ethType, vlan, srcIp6, dstIp6, flowLabelIpv6,
                        ipProtocol, tos, (short) srcPort, (short) dstPort);
                List<DataRecord> recordList = new ArrayList<DataRecord>();
                recordList.add(record);
                ipfixManager.ipfixSender.sendRecords(DataRecordRfwdIpv6.getTemplateRecord(), recordList, dpid,
                        IpfixManager.collectorIp, IpfixManager.collectorPort);
            }
        }
    }
}