Bulk merge of l2gw changes
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / jobs / BcGroupUpdateJob.java
index 0bc394c7f52a8b569ef9f19ecb19beb18462a383..14d1d24f9b152b4ca66ce54d117ae7a3fbef82b7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2018 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,
  */
 package org.opendaylight.netvirt.elan.l2gw.jobs;
 
-import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
-
-import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
-import java.util.concurrent.Callable;
-import org.opendaylight.mdsal.binding.api.DataBroker;
-import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
-import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
+import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
+import org.opendaylight.genius.itm.globals.ITMConstants;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
+import org.opendaylight.genius.mdsalutil.InstructionInfo;
+import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.mdsalutil.matches.MatchInPort;
+import org.opendaylight.netvirt.dhcpservice.api.DhcpMConstants;
+import org.opendaylight.netvirt.elan.cache.ElanInstanceDpnsCache;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanRefUtil;
+import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
+import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BcGroupUpdateJob implements Callable<List<? extends ListenableFuture<?>>> {
+public class BcGroupUpdateJob extends DataStoreJob {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BcGroupUpdateJob.class);
 
-    private static final Logger LOG = LoggerFactory.getLogger("HwvtepEventLogger");
+    static final Map<BigInteger, Boolean> INSTALLED_DEFAULT_FLOW = new ConcurrentHashMap<>();
+    static final Map<Pair<BigInteger, IpAddress>, Boolean> INSTALLED_FLOW_FOR_TUNNEL = new ConcurrentHashMap<>();
 
     private final String elanName;
+    private final boolean add;
+    private Uint64 addedDpn;
+    private L2GatewayDevice addedL2gw;
     private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
     private final ElanRefUtil elanRefUtil;
-    private final ManagedNewTransactionRunner txRunner;
-    protected String jobKey;
-    private final boolean createCase;
+
+    private IInterfaceManager interfaceManager;
+    private IMdsalApiManager mdsalApiManager;
+    private ElanInstanceDpnsCache elanInstanceDpnsCache;
+    private ElanItmUtils elanItmUtils;
 
     public BcGroupUpdateJob(String elanName,
+                            boolean add,
+                            Uint64 addedDpn,
+                            L2GatewayDevice addedL2gw,
                             ElanRefUtil elanRefUtil,
                             ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
-                            DataBroker dataBroker, boolean createCase) {
-        this.jobKey = ElanUtils.getBcGroupUpdateKey(elanName);
-        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+                            IMdsalApiManager mdsalApiManager,
+                            ElanInstanceDpnsCache elanInstanceDpnsCache,
+                            ElanItmUtils elanItmUtils) {
+        super(ElanUtils.getBcGroupUpdateKey(elanName),
+                elanRefUtil.getScheduler(), elanRefUtil.getJobCoordinator());
         this.elanName = elanName;
+        this.add = add;
+        this.addedDpn = addedDpn;
+        this.addedL2gw = addedL2gw;
         this.elanRefUtil = elanRefUtil;
         this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
-        this.createCase = createCase;
+        this.interfaceManager = elanL2GatewayMulticastUtils.getInterfaceManager();
+        this.mdsalApiManager = mdsalApiManager;
+        this.elanInstanceDpnsCache = elanInstanceDpnsCache;
+        this.elanItmUtils = elanItmUtils;
     }
 
     public void submit() {
-        elanRefUtil.getElanClusterUtils().runOnlyInOwnerNode(this.jobKey, "BC Group Update Job", this);
+        elanRefUtil.getElanClusterUtils().runOnlyInOwnerNode(super.jobKey, "BC Group Update Job", this);
     }
 
     @Override
     public List<ListenableFuture<?>> call() throws Exception {
         Optional<ElanInstance> elanInstanceOptional =  elanRefUtil.getElanInstanceCache().get(elanName);
         if (elanInstanceOptional.isPresent()) {
-            return Lists.newArrayList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
-                confTx -> elanL2GatewayMulticastUtils.updateRemoteBroadcastGroupForAllElanDpns(
-                        elanInstanceOptional.get(), createCase, confTx)));
+            elanL2GatewayMulticastUtils.updateRemoteBroadcastGroupForAllElanDpns(elanInstanceOptional.get(), add,
+                    addedDpn);
+        }
+        if (addedDpn != null && add) {
+            installDpnDefaultFlows(elanName, addedDpn);
+        } else if (addedL2gw != null && add) {
+            installDpnDefaultFlows(elanName, addedL2gw);
         }
         return null;
     }
 
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    public void installDpnDefaultFlows(String elan, L2GatewayDevice device) {
+        try {
+            elanInstanceDpnsCache.getElanDpns().get(elan).forEach(dpn -> {
+                installDpnDefaultFlows(elan, dpn.getDpId(), device);
+            });
+        } catch (NullPointerException e) {
+            LOG.error("Runtime exception: Unable to install default dpn flows for elan {} and l2gateway device {}",
+                    elan, device);
+        } catch (Exception e) {
+            LOG.error("Unable to install default dpn flows for elan {} and l2gateway device {}", elan, device);
+        }
+    }
+
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    public void installDpnDefaultFlows(String elan, Uint64 dpnId) {
+        try {
+            ElanL2GwCacheUtils.getInvolvedL2GwDevices(elan).values().forEach(device -> {
+                installDpnDefaultFlows(elan, dpnId, device);
+            });
+        } catch (NullPointerException e) {
+            LOG.error("Runtime exception: Unable to install default dpn flows for elan {} and dpnId {}", elan, dpnId);
+        } catch (Exception e) {
+            LOG.error("Unable to install default dpn flows for elan {} and dpnId {}", elan, dpnId);
+        }
+    }
+
+    public void installDpnDefaultFlows(String elan, Uint64 dpnId, L2GatewayDevice device) {
+        String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
+                device.getHwvtepNodeId());
+        if (interfaceName == null) {
+            return;
+        }
+        InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+        if (interfaceInfo == null) {
+            return;
+        }
+        if (INSTALLED_FLOW_FOR_TUNNEL
+            .putIfAbsent(Pair.of(dpnId.toJava(), device.getTunnelIp()),Boolean.TRUE) == null) {
+            makeTunnelIngressFlow(dpnId, interfaceInfo.getPortNo(), interfaceName, interfaceInfo.getInterfaceTag());
+        }
+        if (INSTALLED_DEFAULT_FLOW.putIfAbsent(dpnId.toJava(), Boolean.TRUE) == null) {
+            setupTableMissForHandlingExternalTunnel(dpnId);
+        }
+        LOG.info("Installed default flows on DPN {} for TOR {} for elan {}",
+            dpnId, device.getHwvtepNodeId(), elan);
+    }
+
+    private void setupTableMissForHandlingExternalTunnel(Uint64 dpId) {
+
+        List<MatchInfo> matches = new ArrayList<>();
+        List<InstructionInfo> mkInstructions = new ArrayList<>();
+        mkInstructions.add(new InstructionGotoTable(NwConstants.EXTERNAL_TUNNEL_TABLE));
+        LOG.debug("mk instructions {}", mkInstructions);
+
+        FlowEntity flowEntity = new FlowEntityBuilder()
+                .setDpnId(dpId)
+                .setTableId(NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL)
+                .setFlowId("DHCPTableMissFlowForExternalTunnel")
+                .setPriority(0)
+                .setFlowName("DHCP Table Miss Flow For External Tunnel")
+                .setIdleTimeOut(0)
+                .setHardTimeOut(0)
+                .setCookie(DhcpMConstants.COOKIE_DHCP_BASE)
+                .setMatchInfoList(matches)
+                .setInstructionInfoList(mkInstructions)
+                .build();
+
+        //mdsalApiManager.batchedAddFlow(dpId, flowEntity);
+        mdsalApiManager.installFlow(dpId, flowEntity);
+    }
+
+    public static String getTunnelInterfaceFlowRef(Uint64 dpnId, short tableId, String ifName) {
+        return String.valueOf(dpnId) + tableId + ifName;
+    }
+
+    public void makeTunnelIngressFlow(Uint64 dpnId, long portNo, String interfaceName, int ifIndex) {
+        List<MatchInfo> matches = new ArrayList<>();
+        List<InstructionInfo> mkInstructions = new ArrayList<>();
+        matches.add(new MatchInPort(dpnId, portNo));
+        mkInstructions.add(new InstructionWriteMetadata(
+            Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(ifIndex).longValue() | 1L),
+            MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG));
+        short tableId = NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL;
+        mkInstructions.add(new InstructionGotoTable(tableId));
+
+        String flowRef = getTunnelInterfaceFlowRef(dpnId,
+                NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
+        LOG.debug("Flow ref {}", flowRef);
+
+        FlowEntity flowEntity = new FlowEntityBuilder()
+                .setDpnId(dpnId)
+                .setTableId(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)
+                .setFlowId(flowRef)
+                .setPriority(ITMConstants.DEFAULT_FLOW_PRIORITY)
+                .setFlowName(interfaceName)
+                .setIdleTimeOut(0)
+                .setHardTimeOut(0)
+                .setCookie(NwConstants.COOKIE_VM_INGRESS_TABLE)
+                .setMatchInfoList(matches)
+                .setInstructionInfoList(mkInstructions)
+                .build();
+
+
+        //mdsalApiManager.batchedAddFlow(dpnId, flowEntity);
+        mdsalApiManager.installFlow(dpnId, flowEntity);
+    }
+
     public static void updateAllBcGroups(String elanName,
+                                         boolean add,
+                                         Uint64 addedDpn,
+                                         L2GatewayDevice addedL2gw,
                                          ElanRefUtil elanRefUtil,
                                          ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
-                                         DataBroker dataBroker, boolean createCase) {
-        new BcGroupUpdateJob(elanName, elanRefUtil, elanL2GatewayMulticastUtils, dataBroker, createCase).submit();
+                                         IMdsalApiManager mdsalApiManager,
+                                         ElanInstanceDpnsCache elanInstanceDpnsCache,
+                                         ElanItmUtils elanItmUtils) {
+        new BcGroupUpdateJob(elanName, add, addedDpn, addedL2gw, elanRefUtil, elanL2GatewayMulticastUtils,
+                mdsalApiManager, elanInstanceDpnsCache, elanItmUtils).submit();
     }
 }