Bulk merge of l2gw changes
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / jobs / BcGroupUpdateJob.java
1 /*
2  * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netvirt.elan.l2gw.jobs;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Optional;
16 import java.util.concurrent.ConcurrentHashMap;
17 import org.apache.commons.lang3.tuple.Pair;
18 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
19 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
20 import org.opendaylight.genius.itm.globals.ITMConstants;
21 import org.opendaylight.genius.mdsalutil.FlowEntity;
22 import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
23 import org.opendaylight.genius.mdsalutil.InstructionInfo;
24 import org.opendaylight.genius.mdsalutil.MatchInfo;
25 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
26 import org.opendaylight.genius.mdsalutil.NwConstants;
27 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
28 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
29 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
30 import org.opendaylight.genius.mdsalutil.matches.MatchInPort;
31 import org.opendaylight.netvirt.dhcpservice.api.DhcpMConstants;
32 import org.opendaylight.netvirt.elan.cache.ElanInstanceDpnsCache;
33 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
34 import org.opendaylight.netvirt.elan.l2gw.utils.ElanRefUtil;
35 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
36 import org.opendaylight.netvirt.elan.utils.ElanUtils;
37 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
38 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
41 import org.opendaylight.yangtools.yang.common.Uint64;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class BcGroupUpdateJob extends DataStoreJob {
46
47     private static final Logger LOG = LoggerFactory.getLogger(BcGroupUpdateJob.class);
48
49     static final Map<BigInteger, Boolean> INSTALLED_DEFAULT_FLOW = new ConcurrentHashMap<>();
50     static final Map<Pair<BigInteger, IpAddress>, Boolean> INSTALLED_FLOW_FOR_TUNNEL = new ConcurrentHashMap<>();
51
52     private final String elanName;
53     private final boolean add;
54     private Uint64 addedDpn;
55     private L2GatewayDevice addedL2gw;
56     private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
57     private final ElanRefUtil elanRefUtil;
58
59     private IInterfaceManager interfaceManager;
60     private IMdsalApiManager mdsalApiManager;
61     private ElanInstanceDpnsCache elanInstanceDpnsCache;
62     private ElanItmUtils elanItmUtils;
63
64     public BcGroupUpdateJob(String elanName,
65                             boolean add,
66                             Uint64 addedDpn,
67                             L2GatewayDevice addedL2gw,
68                             ElanRefUtil elanRefUtil,
69                             ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
70                             IMdsalApiManager mdsalApiManager,
71                             ElanInstanceDpnsCache elanInstanceDpnsCache,
72                             ElanItmUtils elanItmUtils) {
73         super(ElanUtils.getBcGroupUpdateKey(elanName),
74                 elanRefUtil.getScheduler(), elanRefUtil.getJobCoordinator());
75         this.elanName = elanName;
76         this.add = add;
77         this.addedDpn = addedDpn;
78         this.addedL2gw = addedL2gw;
79         this.elanRefUtil = elanRefUtil;
80         this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
81         this.interfaceManager = elanL2GatewayMulticastUtils.getInterfaceManager();
82         this.mdsalApiManager = mdsalApiManager;
83         this.elanInstanceDpnsCache = elanInstanceDpnsCache;
84         this.elanItmUtils = elanItmUtils;
85     }
86
87     public void submit() {
88         elanRefUtil.getElanClusterUtils().runOnlyInOwnerNode(super.jobKey, "BC Group Update Job", this);
89     }
90
91     @Override
92     public List<ListenableFuture<?>> call() throws Exception {
93         Optional<ElanInstance> elanInstanceOptional =  elanRefUtil.getElanInstanceCache().get(elanName);
94         if (elanInstanceOptional.isPresent()) {
95             elanL2GatewayMulticastUtils.updateRemoteBroadcastGroupForAllElanDpns(elanInstanceOptional.get(), add,
96                     addedDpn);
97         }
98         if (addedDpn != null && add) {
99             installDpnDefaultFlows(elanName, addedDpn);
100         } else if (addedL2gw != null && add) {
101             installDpnDefaultFlows(elanName, addedL2gw);
102         }
103         return null;
104     }
105
106     @SuppressWarnings("checkstyle:IllegalCatch")
107     public void installDpnDefaultFlows(String elan, L2GatewayDevice device) {
108         try {
109             elanInstanceDpnsCache.getElanDpns().get(elan).forEach(dpn -> {
110                 installDpnDefaultFlows(elan, dpn.getDpId(), device);
111             });
112         } catch (NullPointerException e) {
113             LOG.error("Runtime exception: Unable to install default dpn flows for elan {} and l2gateway device {}",
114                     elan, device);
115         } catch (Exception e) {
116             LOG.error("Unable to install default dpn flows for elan {} and l2gateway device {}", elan, device);
117         }
118     }
119
120     @SuppressWarnings("checkstyle:IllegalCatch")
121     public void installDpnDefaultFlows(String elan, Uint64 dpnId) {
122         try {
123             ElanL2GwCacheUtils.getInvolvedL2GwDevices(elan).values().forEach(device -> {
124                 installDpnDefaultFlows(elan, dpnId, device);
125             });
126         } catch (NullPointerException e) {
127             LOG.error("Runtime exception: Unable to install default dpn flows for elan {} and dpnId {}", elan, dpnId);
128         } catch (Exception e) {
129             LOG.error("Unable to install default dpn flows for elan {} and dpnId {}", elan, dpnId);
130         }
131     }
132
133     public void installDpnDefaultFlows(String elan, Uint64 dpnId, L2GatewayDevice device) {
134         String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
135                 device.getHwvtepNodeId());
136         if (interfaceName == null) {
137             return;
138         }
139         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
140         if (interfaceInfo == null) {
141             return;
142         }
143         if (INSTALLED_FLOW_FOR_TUNNEL
144             .putIfAbsent(Pair.of(dpnId.toJava(), device.getTunnelIp()),Boolean.TRUE) == null) {
145             makeTunnelIngressFlow(dpnId, interfaceInfo.getPortNo(), interfaceName, interfaceInfo.getInterfaceTag());
146         }
147         if (INSTALLED_DEFAULT_FLOW.putIfAbsent(dpnId.toJava(), Boolean.TRUE) == null) {
148             setupTableMissForHandlingExternalTunnel(dpnId);
149         }
150         LOG.info("Installed default flows on DPN {} for TOR {} for elan {}",
151             dpnId, device.getHwvtepNodeId(), elan);
152     }
153
154     private void setupTableMissForHandlingExternalTunnel(Uint64 dpId) {
155
156         List<MatchInfo> matches = new ArrayList<>();
157         List<InstructionInfo> mkInstructions = new ArrayList<>();
158         mkInstructions.add(new InstructionGotoTable(NwConstants.EXTERNAL_TUNNEL_TABLE));
159         LOG.debug("mk instructions {}", mkInstructions);
160
161         FlowEntity flowEntity = new FlowEntityBuilder()
162                 .setDpnId(dpId)
163                 .setTableId(NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL)
164                 .setFlowId("DHCPTableMissFlowForExternalTunnel")
165                 .setPriority(0)
166                 .setFlowName("DHCP Table Miss Flow For External Tunnel")
167                 .setIdleTimeOut(0)
168                 .setHardTimeOut(0)
169                 .setCookie(DhcpMConstants.COOKIE_DHCP_BASE)
170                 .setMatchInfoList(matches)
171                 .setInstructionInfoList(mkInstructions)
172                 .build();
173
174         //mdsalApiManager.batchedAddFlow(dpId, flowEntity);
175         mdsalApiManager.installFlow(dpId, flowEntity);
176     }
177
178     public static String getTunnelInterfaceFlowRef(Uint64 dpnId, short tableId, String ifName) {
179         return String.valueOf(dpnId) + tableId + ifName;
180     }
181
182     public void makeTunnelIngressFlow(Uint64 dpnId, long portNo, String interfaceName, int ifIndex) {
183         List<MatchInfo> matches = new ArrayList<>();
184         List<InstructionInfo> mkInstructions = new ArrayList<>();
185         matches.add(new MatchInPort(dpnId, portNo));
186         mkInstructions.add(new InstructionWriteMetadata(
187             Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(ifIndex).longValue() | 1L),
188             MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG));
189         short tableId = NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL;
190         mkInstructions.add(new InstructionGotoTable(tableId));
191
192         String flowRef = getTunnelInterfaceFlowRef(dpnId,
193                 NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
194         LOG.debug("Flow ref {}", flowRef);
195
196         FlowEntity flowEntity = new FlowEntityBuilder()
197                 .setDpnId(dpnId)
198                 .setTableId(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)
199                 .setFlowId(flowRef)
200                 .setPriority(ITMConstants.DEFAULT_FLOW_PRIORITY)
201                 .setFlowName(interfaceName)
202                 .setIdleTimeOut(0)
203                 .setHardTimeOut(0)
204                 .setCookie(NwConstants.COOKIE_VM_INGRESS_TABLE)
205                 .setMatchInfoList(matches)
206                 .setInstructionInfoList(mkInstructions)
207                 .build();
208
209
210         //mdsalApiManager.batchedAddFlow(dpnId, flowEntity);
211         mdsalApiManager.installFlow(dpnId, flowEntity);
212     }
213
214     public static void updateAllBcGroups(String elanName,
215                                          boolean add,
216                                          Uint64 addedDpn,
217                                          L2GatewayDevice addedL2gw,
218                                          ElanRefUtil elanRefUtil,
219                                          ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
220                                          IMdsalApiManager mdsalApiManager,
221                                          ElanInstanceDpnsCache elanInstanceDpnsCache,
222                                          ElanItmUtils elanItmUtils) {
223         new BcGroupUpdateJob(elanName, add, addedDpn, addedL2gw, elanRefUtil, elanL2GatewayMulticastUtils,
224                 mdsalApiManager, elanInstanceDpnsCache, elanItmUtils).submit();
225     }
226 }