Do not use char[]-based union access
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / TunnelInterfaceStateListener.java
index a3946919d12295fa878126df2ad646e385f2dfde..6bc22a80eba1b6da6e86b13def642e756df85adc 100644 (file)
@@ -28,7 +28,9 @@ import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
@@ -88,6 +90,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
     private final VpnInterfaceManager vpnInterfaceManager;
     private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
     private final JobCoordinator jobCoordinator;
+    private final VpnUtil vpnUtil;
 
     protected enum UpdateRouteAction {
         ADVERTISE_ROUTE, WITHDRAW_ROUTE
@@ -101,6 +104,13 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
 
     /**
      * Responsible for listening to tunnel interface state change.
+     * @param dataBroker Data Broker
+     * @param fibManager FIB APIs
+     * @param ifaceMgrRpcService Interface Manager RPC
+     * @param vpnInterfaceManager Vpn Interface APIs
+     * @param vpnSubnetRouteHandler Subnet-Route APIs
+     * @param jobCoordinator Key based job serialization mechanism
+     * @param vpnUtil Vpn Utility
      */
     @Inject
     public TunnelInterfaceStateListener(final DataBroker dataBroker,
@@ -108,7 +118,8 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                                         final OdlInterfaceRpcService ifaceMgrRpcService,
                                         final VpnInterfaceManager vpnInterfaceManager,
                                         final VpnSubnetRouteHandler vpnSubnetRouteHandler,
-                                        final JobCoordinator jobCoordinator) {
+                                        final JobCoordinator jobCoordinator,
+                                        VpnUtil vpnUtil) {
         super(StateTunnelList.class, TunnelInterfaceStateListener.class);
         this.dataBroker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
@@ -117,6 +128,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         this.vpnInterfaceManager = vpnInterfaceManager;
         this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
         this.jobCoordinator = jobCoordinator;
+        this.vpnUtil = vpnUtil;
     }
 
     @PostConstruct
@@ -164,41 +176,40 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
 
         //Remove the corresponding nexthop from the routepath under extraroute in fibentries.
         BigInteger srcDpnId = new BigInteger(update.getSrcInfo().getTepDeviceId());
-        String srcTepIp = String.valueOf(update.getSrcInfo().getTepIp().getValue());
-        List<VpnInstanceOpDataEntry> vpnInstanceOpData = VpnUtil.getAllVpnInstanceOpData(dataBroker);
+        String srcTepIp = update.getSrcInfo().getTepIp().stringValue();
+        List<VpnInstanceOpDataEntry> vpnInstanceOpData = vpnUtil.getAllVpnInstanceOpData();
         if (vpnInstanceOpData == null) {
             LOG.trace("update: No vpnInstanceOpdata present");
             return;
         }
-        if (tunOpStatus == TunnelOperStatus.Up) {
-            handleTunnelEventForDPN(update, TunnelAction.TUNNEL_EP_ADD);
-        } else {
-            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx ->
-                    vpnInstanceOpData.stream()
-                            .filter(opData -> opData.getVpnToDpnList() != null
-                                    && opData.getVpnToDpnList().stream().anyMatch(
-                                        vpnToDpn -> vpnToDpn.getDpnId().equals(srcDpnId)))
-                            .forEach(opData -> {
-                                List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
-                                        opData.getVpnId());
-                                prefixes.forEach(destPrefix -> {
-                                    VrfEntry vrfEntry = VpnUtil.getVrfEntry(dataBroker, opData.getVrfId(),
-                                            destPrefix.getDestPrefix());
-                                    if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
-                                        return;
-                                    }
-                                    List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
-                                    routePaths.forEach(routePath -> {
-                                        if (routePath.getNexthopAddress().equals(srcTepIp)) {
-                                            fibManager.updateRoutePathForFibEntry(opData.getVrfId(),
-                                                    destPrefix.getDestPrefix(), srcTepIp, routePath.getLabel(),
-                                                    false, confTx);
+        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx ->
+                vpnInstanceOpData.stream()
+                        .filter(opData -> opData.getVpnToDpnList() != null
+                                && opData.getVpnToDpnList().stream().anyMatch(
+                                    vpnToDpn -> vpnToDpn.getDpnId().equals(srcDpnId)))
+                        .forEach(opData -> {
+                            List<DestPrefixes> prefixes = VpnExtraRouteHelper.getExtraRouteDestPrefixes(dataBroker,
+                                    opData.getVpnId());
+                            prefixes.forEach(destPrefix -> {
+                                VrfEntry vrfEntry = vpnUtil.getVrfEntry(opData.getVrfId(),
+                                        destPrefix.getDestPrefix());
+                                if (vrfEntry == null || vrfEntry.getRoutePaths() == null) {
+                                    return;
+                                }
+                                List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
+                                routePaths.forEach(routePath -> {
+                                    if (routePath.getNexthopAddress().equals(srcTepIp)) {
+                                        String prefix = destPrefix.getDestPrefix();
+                                        String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(opData.getVpnInstanceName(),
+                                                prefix);
+                                        synchronized (vpnPrefixKey.intern()) {
+                                            fibManager.refreshVrfEntry(opData.getVrfId(), prefix);
                                         }
-                                    });
+                                    }
                                 });
-                            })
-            ), LOG, "Error updating route paths for FIB entries");
-        }
+                            });
+                        })
+        ), LOG, "Error updating route paths for FIB entries");
     }
 
     @Override
@@ -240,8 +251,8 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
     @SuppressWarnings("checkstyle:IllegalCatch")
     private void handleTunnelEventForDPN(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
         final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
-        final String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
-        String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
+        final String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
+        String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
         String rd;
         BigInteger remoteDpnId = null;
         boolean isTepDeletedOnDpn = false;
@@ -336,12 +347,12 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                 interfaces = interfacelistIter.next();
                 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
                     LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
-                    return;
+                    continue;
                 }
                 intfName = interfaces.getInterfaceName();
                 VpnInterface vpnInterface =
-                     VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
-                if (vpnInterface != null && !Boolean.TRUE.equals(vpnInterface.isScheduledForRemove())) {
+                     vpnUtil.getConfiguredVpnInterface(intfName);
+                if (vpnInterface != null) {
                     listVpnName.addAll(VpnHelper
                         .getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
                     handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
@@ -359,11 +370,11 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
                 interfaces = interfacelistIter.next();
                 if (!L2vlan.class.equals(interfaces.getInterfaceType())) {
                     LOG.info("handleTunnelEventForDPN: Interface {} not of type L2Vlan", interfaces.getInterfaceName());
-                    return;
+                    continue;
                 }
                 intfName = interfaces.getInterfaceName();
                 VpnInterface vpnInterface =
-                        VpnUtil.getConfiguredVpnInterface(dataBroker, intfName);
+                        vpnUtil.getConfiguredVpnInterface(intfName);
                 if (vpnInterface != null) {
                     handleTunnelEventForDPNVpn(stateTunnelList, vpnIdRdMap,
                             tunnelAction, isTepDeletedOnDpn,
@@ -414,8 +425,8 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         String rd;
         String intfName = cfgVpnInterface.getName();
         final BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
-        String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
-        String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
+        String destTepIp = stateTunnelList.getDstInfo().getTepIp().stringValue();
+        String srcTepIp = stateTunnelList.getSrcInfo().getTepIp().stringValue();
         int tunTypeVal = getTunnelType(stateTunnelList);
         BigInteger remoteDpnId = null;
         if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
@@ -425,70 +436,78 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
             LOG.warn("handleTunnelEventForDpn: no vpnName found for interface {}", intfName);
             return;
         }
-        for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
-            String vpnName = vpnInstance.getVpnName();
-            if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
-                Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil
-                           .getVpnInterfaceOpDataEntry(dataBroker, intfName, vpnName);
-                if (opVpnInterface.isPresent() && !opVpnInterface.get().isScheduledForRemove()) {
-                    VpnInterfaceOpDataEntry vpnInterface  = opVpnInterface.get();
-                    jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
-                            new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
-                                    vpnInterface,
-                                    stateTunnelList,
-                                    isTepDeletedOnDpn));
-
-                    // Populate the List of subnets
-                    InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
-                            InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
-                                    new PortOpDataEntryKey(intfName)).build();
-                    Optional<PortOpDataEntry> optionalPortOp =
-                            VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
-                    if (optionalPortOp.isPresent()) {
-                        List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
-                        if (subnetIdList != null) {
-                            for (Uuid subnetId : subnetIdList) {
-                                if (!subnetList.contains(subnetId)) {
-                                    subnetList.add(subnetId);
+        try {
+            for (VpnInstanceNames vpnInstance : cfgVpnInterface.getVpnInstanceNames()) {
+                String vpnName = vpnInstance.getVpnName();
+                if (method == TunnelEventProcessingMethod.POPULATESUBNETS) {
+                    Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil
+                            .getVpnInterfaceOpDataEntry(intfName, vpnName);
+                    if (opVpnInterface.isPresent()) {
+                        VpnInterfaceOpDataEntry vpnInterface  = opVpnInterface.get();
+                        jobCoordinator.enqueueJob("VPNINTERFACE-" + intfName,
+                                new UpdateVpnInterfaceOnTunnelEvent(tunnelAction,
+                                        vpnInterface,
+                                        stateTunnelList,
+                                        isTepDeletedOnDpn));
+
+                        // Populate the List of subnets
+                        InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
+                                InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
+                                        new PortOpDataEntryKey(intfName)).build();
+                        Optional<PortOpDataEntry> optionalPortOp =
+                                SingleTransactionDataBroker.syncReadOptional(dataBroker,
+                                        LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+                        if (optionalPortOp.isPresent()) {
+                            List<Uuid> subnetIdList = optionalPortOp.get().getSubnetIds();
+                            if (subnetIdList != null) {
+                                for (Uuid subnetId : subnetIdList) {
+                                    if (!subnetList.contains(subnetId)) {
+                                        subnetList.add(subnetId);
+                                    }
                                 }
                             }
                         }
+                        //Populate the map for VpnId-to-Rd
+                        long vpnId = vpnUtil.getVpnId(vpnName);
+                        rd = vpnUtil.getVpnRd(vpnName);
+                        vpnIdRdMap.put(vpnId, rd);
                     }
-                    //Populate the map for VpnId-to-Rd
-                    long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
-                    rd = VpnUtil.getVpnRd(dataBroker, vpnName);
-                    vpnIdRdMap.put(vpnId, rd);
-                }
-            } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
-                Optional<VpnInterfaceOpDataEntry> opVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
-                        intfName, vpnName);
-                if (opVpnInterface.isPresent()) {
-                    VpnInterfaceOpDataEntry vpnInterface  = opVpnInterface.get();
-                    AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
-                    List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
-                            : Collections.emptyList();
-                    String prefix = null;
-                    long vpnId = VpnUtil.getVpnId(dataBroker, vpnInterface.getVpnInstanceName());
-                    if (vpnIdRdMap.containsKey(vpnId)) {
-                        rd = vpnIdRdMap.get(vpnId);
-                        LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {} srcTepIp "
-                                + "{} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp, destTepIp);
-                        for (Adjacency adj : adjList) {
-                            prefix = adj.getIpAddress();
-                            long label = adj.getLabel();
-                            if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
-                                    && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                                fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp, label);
-                            }
-
-                            if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
-                                    && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
-                                fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp, label);
+                } else if (method == TunnelEventProcessingMethod.MANAGEREMOTEROUTES) {
+                    Optional<VpnInterfaceOpDataEntry> opVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(intfName,
+                            vpnName);
+                    if (opVpnInterface.isPresent()) {
+                        VpnInterfaceOpDataEntry vpnInterface  = opVpnInterface.get();
+                        AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
+                        List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency()
+                                : Collections.emptyList();
+                        String prefix = null;
+                        long vpnId = vpnUtil.getVpnId(vpnInterface.getVpnInstanceName());
+                        if (vpnIdRdMap.containsKey(vpnId)) {
+                            rd = vpnIdRdMap.get(vpnId);
+                            LOG.info("handleTunnelEventForDPN: Remote DpnId {} VpnId {} rd {} VpnInterface {}"
+                                    + " srcTepIp {} destTepIp {}", remoteDpnId, vpnId, rd , vpnInterface, srcTepIp,
+                                    destTepIp);
+                            for (Adjacency adj : adjList) {
+                                prefix = adj.getIpAddress();
+                                long label = adj.getLabel();
+                                if (tunnelAction == TunnelAction.TUNNEL_EP_ADD
+                                        && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
+                                    fibManager.manageRemoteRouteOnDPN(true, srcDpnId, vpnId, rd, prefix, destTepIp,
+                                            label);
+                                }
+                                if (tunnelAction == TunnelAction.TUNNEL_EP_DELETE
+                                        && tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
+                                    fibManager.manageRemoteRouteOnDPN(false, srcDpnId, vpnId, rd, prefix, destTepIp,
+                                            label);
+                                }
                             }
                         }
                     }
                 }
             }
+        } catch (ReadFailedException e) {
+            LOG.error("handleTunnelEventForDPN: Failed to read data store for interface {} srcDpn {} srcTep {} "
+                    + "dstTep {}", intfName, srcDpnId, srcTepIp, destTepIp);
         }
     }
 
@@ -547,11 +566,12 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
 
     private void programDcGwLoadBalancingGroup(StateTunnelList tunnelState, int addOrRemove) {
         IpAddress dcGwIp = tunnelState.getDstInfo().getTepIp();
-        String dcGwIpAddress = String.valueOf(dcGwIp.getValue());
+        String dcGwIpAddress = dcGwIp.stringValue();
         List<String> availableDcGws = getDcGwIps();
         BigInteger dpId = new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
         boolean isTunnelUp = TunnelOperStatus.Up == tunnelState.getOperState();
-        fibManager.programDcGwLoadBalancingGroup(availableDcGws, dpId, dcGwIpAddress, addOrRemove, isTunnelUp);
+        fibManager.programDcGwLoadBalancingGroup(availableDcGws, dpId, dcGwIpAddress, addOrRemove, isTunnelUp,
+                tunnelState.getTransportType());
     }
 
     private List<String> getDcGwIps() {
@@ -565,7 +585,7 @@ public class TunnelInterfaceStateListener extends AsyncDataTreeChangeListenerBas
         return dcGatewayIpListConfig.getDcGatewayIp()
                 .stream()
                 .filter(dcGwIp -> dcGwIp.getTunnnelType().equals(TunnelTypeMplsOverGre.class))
-                .map(dcGwIp -> String.valueOf(dcGwIp.getIpAddress().getValue())).sorted()
+                .map(dcGwIp -> dcGwIp.getIpAddress().stringValue()).sorted()
                 .collect(toList());
     }