org.opendaylight.netvirt.vpnmanager.ArpScheduler.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.netvirt.vpnmanager.ArpScheduler.java

Source

/*
 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.netvirt.vpnmanager;

import com.google.common.base.Optional;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.Thread.UncaughtExceptionHandler;
import java.math.BigInteger;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;

import java.util.List;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

public class ArpScheduler extends AsyncDataTreeChangeListenerBase<VpnPortipToPort, ArpScheduler> {
    private static final Logger LOG = LoggerFactory.getLogger(ArpScheduler.class);
    private final DataBroker dataBroker;
    private final OdlInterfaceRpcService intfRpc;
    private final IMdsalApiManager mdsalManager;
    private ScheduledExecutorService executorService;
    private volatile static ArpScheduler arpScheduler = null;
    private static DelayQueue<MacEntry> macEntryQueue = new DelayQueue<MacEntry>();

    public ArpScheduler(final DataBroker dataBroker, final OdlInterfaceRpcService interfaceRpc,
            final IMdsalApiManager mdsalManager) {
        super(VpnPortipToPort.class, ArpScheduler.class);
        this.dataBroker = dataBroker;
        this.intfRpc = interfaceRpc;
        this.mdsalManager = mdsalManager;
    }

    public void start() {
        LOG.info("{} start", getClass().getSimpleName());
        registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
        executorService = Executors.newScheduledThreadPool(ArpConstants.THREAD_POOL_SIZE,
                getThreadFactory("Arp Cache Timer Tasks"));
        scheduleExpiredEntryDrainerTask();
    }

    @Override
    protected InstanceIdentifier<VpnPortipToPort> getWildCardPath() {
        return InstanceIdentifier.create(NeutronVpnPortipPortData.class).child(VpnPortipToPort.class);
    }

    private void scheduleExpiredEntryDrainerTask() {
        LOG.info("Scheduling expired entry drainer task");
        ExpiredEntryDrainerTask expiredEntryDrainerTask = new ExpiredEntryDrainerTask();
        executorService.scheduleAtFixedRate(expiredEntryDrainerTask, ArpConstants.NO_DELAY, ArpConstants.PERIOD,
                TimeUnit.MILLISECONDS);
    }

    private ThreadFactory getThreadFactory(String threadNameFormat) {
        ThreadFactoryBuilder builder = new ThreadFactoryBuilder();
        builder.setNameFormat(threadNameFormat);
        builder.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                LOG.error("Received Uncaught Exception event in Thread: {}", t.getName(), e);
            }
        });
        return builder.build();
    }

    private class ExpiredEntryDrainerTask implements Runnable {
        @Override
        public void run() {
            Collection<MacEntry> expiredMacEntries = new ArrayList<>();
            macEntryQueue.drainTo(expiredMacEntries);
            for (MacEntry macEntry : expiredMacEntries) {
                LOG.info("Removing the ARP cache for" + macEntry);
                InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortInstanceOpDataIdentifier(
                        macEntry.getIpAddress().getHostAddress(), macEntry.getVpnName());
                Optional<VpnPortipToPort> vpnPortipToPort = VpnUtil.read(dataBroker,
                        LogicalDatastoreType.OPERATIONAL, id);
                if (vpnPortipToPort.isPresent()) {
                    VpnPortipToPort vpnPortipToPortold = vpnPortipToPort.get();
                    String fixedip = vpnPortipToPortold.getPortFixedip();
                    String vpnName = vpnPortipToPortold.getVpnName();
                    String interfaceName = vpnPortipToPortold.getPortName();
                    DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
                    coordinator.enqueueJob(buildJobKey(fixedip, vpnName),
                            new ArpUpdateCacheTask(dataBroker, fixedip, vpnName, interfaceName));
                }

            }
        }
    }

    private String getRouteDistinguisher(String vpnName) {
        InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
                .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
        Optional<VpnInstance> vpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
        String rd = "";
        if (vpnInstance.isPresent()) {
            VpnInstance instance = vpnInstance.get();
            VpnAfConfig config = instance.getIpv4Family();
            rd = config.getRouteDistinguisher();
        }
        return rd;
    }

    public static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortInstanceOpDataIdentifier(String ip,
            String vpnName) {
        return InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
                .child(VpnPortipToPort.class, new VpnPortipToPortKey(ip, vpnName)).build();
    }

    @Override
    protected ArpScheduler getDataTreeChangeListener() {
        return this;
    }

    @Override
    protected void update(InstanceIdentifier<VpnPortipToPort> id, VpnPortipToPort value,
            VpnPortipToPort dataObjectModificationAfter) {
        try {
            InetAddress srcInetAddr = InetAddress.getByName(value.getPortFixedip());
            String oldMacAddress = value.getMacAddress();
            MacAddress srcMacAddress = MacAddress.getDefaultInstance(oldMacAddress);
            String newMacAddress = dataObjectModificationAfter.getMacAddress();
            String vpnName = value.getVpnName();
            String interfaceName = value.getPortName();
            Boolean islearnt = value.isLearnt();
            if (islearnt) {
                DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
                coordinator.enqueueJob(buildJobKey(srcInetAddr.toString(), vpnName),
                        new ArpAddCacheTask(srcInetAddr, srcMacAddress, vpnName, interfaceName, macEntryQueue));
            } else if (dataObjectModificationAfter.isSubnetIp() && !oldMacAddress.equalsIgnoreCase(newMacAddress)) {
                WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
                VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, oldMacAddress,
                        BigInteger.ZERO /* On all DPNs */, writeTx, NwConstants.DEL_FLOW);
                VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, newMacAddress,
                        BigInteger.ZERO /* on all DPNs */, writeTx, NwConstants.ADD_FLOW);
                writeTx.submit();
            }
        } catch (Exception e) {
            LOG.error("Error in deserializing packet {} with exception {}", value, e);
            e.printStackTrace();
        }
    }

    @Override
    protected void add(InstanceIdentifier<VpnPortipToPort> identifier, VpnPortipToPort value) {
        try {
            InetAddress srcInetAddr = InetAddress.getByName(value.getPortFixedip());
            String macAddress = value.getMacAddress();
            MacAddress srcMacAddress = MacAddress.getDefaultInstance(macAddress);
            String vpnName = value.getVpnName();
            String interfaceName = value.getPortName();
            Boolean islearnt = value.isLearnt();
            if (islearnt) {
                DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
                coordinator.enqueueJob(buildJobKey(srcInetAddr.toString(), vpnName),
                        new ArpAddCacheTask(srcInetAddr, srcMacAddress, vpnName, interfaceName, macEntryQueue));
            }
            if (value.isSubnetIp()) {
                WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
                VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, macAddress,
                        BigInteger.ZERO /* On all DPNs */, writeTx, NwConstants.ADD_FLOW);
                writeTx.submit();
            }
        } catch (Exception e) {
            LOG.error("Error in deserializing packet {} with exception {}", value, e);
        }
    }

    @Override
    protected void remove(InstanceIdentifier<VpnPortipToPort> key, VpnPortipToPort value) {
        try {
            InetAddress srcInetAddr = InetAddress.getByName(value.getPortFixedip());
            String macAddress = value.getMacAddress();
            MacAddress srcMacAddress = MacAddress.getDefaultInstance(macAddress);
            String vpnName = value.getVpnName();
            String interfaceName = value.getPortName();
            Boolean islearnt = value.isLearnt();
            if (islearnt) {
                DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
                coordinator.enqueueJob(buildJobKey(srcInetAddr.toString(), vpnName),
                        new ArpRemoveCacheTask(srcInetAddr, srcMacAddress, vpnName, interfaceName, macEntryQueue));
            }
            if (value.isSubnetIp()) {
                WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
                VpnUtil.setupSubnetMacIntoVpnInstance(dataBroker, mdsalManager, vpnName, macAddress,
                        BigInteger.ZERO /* On all DPNs */, writeTx, NwConstants.DEL_FLOW);
                writeTx.submit();
            }
        } catch (Exception e) {
            LOG.error("Error in deserializing packet {} with exception {}", value, e);
        }
    }

    private String buildJobKey(String ip, String vpnName) {
        return new StringBuilder(ArpConstants.ARPJOB).append(ip).append(vpnName).toString();
    }

    public void refreshArpEntry(VpnPortipToPort value) {
        try {
            InetAddress srcInetAddr = InetAddress.getByName(value.getPortFixedip());
            MacAddress srcMacAddress = MacAddress.getDefaultInstance(value.getMacAddress());
            String vpnName = value.getVpnName();
            String interfaceName = value.getPortName();
            Boolean islearnt = value.isLearnt();
            if (islearnt) {
                DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
                coordinator.enqueueJob(buildJobKey(srcInetAddr.toString(), vpnName),
                        new ArpAddCacheTask(srcInetAddr, srcMacAddress, vpnName, interfaceName, macEntryQueue));
            }
        } catch (Exception e) {
            LOG.error("Error in deserializing packet {} with exception {}", value, e);
        }
    }
}