2 * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.elan.l2gw.jobs;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
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;
45 public class BcGroupUpdateJob extends DataStoreJob {
47 private static final Logger LOG = LoggerFactory.getLogger(BcGroupUpdateJob.class);
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<>();
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;
59 private IInterfaceManager interfaceManager;
60 private IMdsalApiManager mdsalApiManager;
61 private ElanInstanceDpnsCache elanInstanceDpnsCache;
62 private ElanItmUtils elanItmUtils;
64 public BcGroupUpdateJob(String elanName,
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;
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;
87 public void submit() {
88 elanRefUtil.getElanClusterUtils().runOnlyInOwnerNode(super.jobKey, "BC Group Update Job", this);
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,
98 if (addedDpn != null && add) {
99 installDpnDefaultFlows(elanName, addedDpn);
100 } else if (addedL2gw != null && add) {
101 installDpnDefaultFlows(elanName, addedL2gw);
106 @SuppressWarnings("checkstyle:IllegalCatch")
107 public void installDpnDefaultFlows(String elan, L2GatewayDevice device) {
109 elanInstanceDpnsCache.getElanDpns().get(elan).forEach(dpn -> {
110 installDpnDefaultFlows(elan, dpn.getDpId(), device);
112 } catch (NullPointerException e) {
113 LOG.error("Runtime exception: Unable to install default dpn flows for elan {} and l2gateway device {}",
115 } catch (Exception e) {
116 LOG.error("Unable to install default dpn flows for elan {} and l2gateway device {}", elan, device);
120 @SuppressWarnings("checkstyle:IllegalCatch")
121 public void installDpnDefaultFlows(String elan, Uint64 dpnId) {
123 ElanL2GwCacheUtils.getInvolvedL2GwDevices(elan).values().forEach(device -> {
124 installDpnDefaultFlows(elan, dpnId, device);
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);
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) {
139 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
140 if (interfaceInfo == null) {
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());
147 if (INSTALLED_DEFAULT_FLOW.putIfAbsent(dpnId.toJava(), Boolean.TRUE) == null) {
148 setupTableMissForHandlingExternalTunnel(dpnId);
150 LOG.info("Installed default flows on DPN {} for TOR {} for elan {}",
151 dpnId, device.getHwvtepNodeId(), elan);
154 private void setupTableMissForHandlingExternalTunnel(Uint64 dpId) {
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);
161 FlowEntity flowEntity = new FlowEntityBuilder()
163 .setTableId(NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL)
164 .setFlowId("DHCPTableMissFlowForExternalTunnel")
166 .setFlowName("DHCP Table Miss Flow For External Tunnel")
169 .setCookie(DhcpMConstants.COOKIE_DHCP_BASE)
170 .setMatchInfoList(matches)
171 .setInstructionInfoList(mkInstructions)
174 //mdsalApiManager.batchedAddFlow(dpId, flowEntity);
175 mdsalApiManager.installFlow(dpId, flowEntity);
178 public static String getTunnelInterfaceFlowRef(Uint64 dpnId, short tableId, String ifName) {
179 return String.valueOf(dpnId) + tableId + ifName;
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));
192 String flowRef = getTunnelInterfaceFlowRef(dpnId,
193 NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
194 LOG.debug("Flow ref {}", flowRef);
196 FlowEntity flowEntity = new FlowEntityBuilder()
198 .setTableId(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)
200 .setPriority(ITMConstants.DEFAULT_FLOW_PRIORITY)
201 .setFlowName(interfaceName)
204 .setCookie(NwConstants.COOKIE_VM_INGRESS_TABLE)
205 .setMatchInfoList(matches)
206 .setInstructionInfoList(mkInstructions)
210 //mdsalApiManager.batchedAddFlow(dpnId, flowEntity);
211 mdsalApiManager.installFlow(dpnId, flowEntity);
214 public static void updateAllBcGroups(String elanName,
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();