Use uint types in itm-impl
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / itmdirecttunnels / renderer / ovs / utilities / DirectTunnelUtils.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.genius.itm.itmdirecttunnels.renderer.ovs.utilities;
9
10 import com.google.common.collect.ImmutableMap;
11 import com.google.common.collect.ImmutableMap.Builder;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
14 import java.nio.charset.StandardCharsets;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Optional;
20 import java.util.UUID;
21 import java.util.concurrent.ExecutionException;
22 import java.util.function.Predicate;
23 import java.util.regex.Pattern;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
28 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
29 import org.opendaylight.genius.itm.globals.ITMConstants;
30 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
31 import org.opendaylight.genius.itm.impl.ItmUtils;
32 import org.opendaylight.genius.mdsalutil.ActionInfo;
33 import org.opendaylight.genius.mdsalutil.FlowEntity;
34 import org.opendaylight.genius.mdsalutil.InstructionInfo;
35 import org.opendaylight.genius.mdsalutil.MDSALUtil;
36 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
37 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
38 import org.opendaylight.genius.mdsalutil.NwConstants;
39 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
40 import org.opendaylight.genius.mdsalutil.actions.ActionSetTunnelDestinationIp;
41 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
42 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
43 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
44 import org.opendaylight.genius.mdsalutil.matches.MatchInPort;
45 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
46 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchTunnelSourceIp;
47 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
48 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
49 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
50 import org.opendaylight.mdsal.binding.api.DataBroker;
51 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
52 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
53 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
54 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
55 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBfd;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlanGpe;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.BridgeTunnelInfo;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.IfIndexesTunnelMap;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.OvsBridgeRefInfo;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210._if.indexes.tunnel.map.IfIndexTunnel;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210._if.indexes.tunnel.map.IfIndexTunnelKey;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntryKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepConfig;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTepKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTepKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfd;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
118 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
119 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
120 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
121 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
122 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
123 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
124 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
125 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
126 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
127 import org.opendaylight.yangtools.yang.common.OperationFailedException;
128 import org.opendaylight.yangtools.yang.common.RpcError;
129 import org.opendaylight.yangtools.yang.common.RpcResult;
130 import org.opendaylight.yangtools.yang.common.Uint16;
131 import org.opendaylight.yangtools.yang.common.Uint64;
132 import org.slf4j.Logger;
133 import org.slf4j.LoggerFactory;
134
135 @Singleton
136 public final class DirectTunnelUtils {
137
138     private static final Logger LOG = LoggerFactory.getLogger(DirectTunnelUtils.class);
139
140     private static final String BFD_PARAM_ENABLE = "enable";
141     private static final String BFD_PARAM_MIN_TX = "min_tx";
142     private static final String BFD_PARAM_FORWARDING_IF_RX = "forwarding_if_rx";
143     private static final String BFD_PARAM_REMOTE_DST_MAC = "bfd_remote_dst_mac";
144     private static final String BFD_PARAM_LOCAL_SRC_MAC = "bfd_local_src_mac";
145     private static final String BFD_PARAM_LOCAL_DST_MAC = "bfd_local_dst_mac";
146     // BFD parameters
147     private static final String BFD_ENABLE_KEY = "enable";
148     private static final String BFD_ENABLE_VALUE = "true";
149     public static final String BFD_OP_STATE = "state";
150     public static final String BFD_STATE_UP = "up";
151     private static final String BFD_MIN_TX_VAL = "100";
152     private static final String BFD_FORWARDING_IF_RX_VAL = "true";
153     private static final String BFD_REMOTE_DST_MAC_VAL = "de:ad:be:ef:00:00";
154     private static final String BFD_LOCAL_SRC_MAC_VAL = "de:ad:be:ef:00:01";
155     private static final String BFD_LOCAL_DST_MAC_VAL = "de:ad:be:ef:00:00";
156
157     // Tunnel options
158     public static final String TUNNEL_OPTIONS_KEY = "key";
159     public static final String TUNNEL_OPTIONS_LOCAL_IP = "local_ip";
160     public static final String TUNNEL_OPTIONS_REMOTE_IP = "remote_ip";
161     public static final String TUNNEL_OPTIONS_DESTINATION_PORT = "dst_port";
162     public static final String TUNNEL_OPTIONS_TOS = "tos";
163
164     // Option values for VxLAN-GPE + NSH tunnels
165     public static final String TUNNEL_OPTIONS_EXTS = "exts";
166     public static final String TUNNEL_OPTIONS_NSI = "nsi";
167     public static final String TUNNEL_OPTIONS_NSP = "nsp";
168     public static final String TUNNEL_OPTIONS_NSHC1 = "nshc1";
169     public static final String TUNNEL_OPTIONS_NSHC2 = "nshc2";
170     public static final String TUNNEL_OPTIONS_NSHC3 = "nshc3";
171     public static final String TUNNEL_OPTIONS_NSHC4 = "nshc4";
172
173     // Option values for VxLAN-GPE + NSH tunnels
174     public static final String TUNNEL_OPTIONS_VALUE_FLOW = "flow";
175     public static final String TUNNEL_OPTIONS_VALUE_GPE = "gpe";
176     // UDP port for VxLAN-GPE Tunnels
177     public static final String TUNNEL_OPTIONS_VALUE_GPE_DESTINATION_PORT = "4880";
178
179     //tos option value for tunnels
180     public static final String TUNNEL_OPTIONS_TOS_VALUE_INHERIT = "inherit";
181
182     private static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
183
184     private static final long INVALID_ID = 0;
185     private final NamedLocks<String> tunnelLocks = new NamedLocks<>();
186
187     // To keep the mapping between Tunnel Types and Tunnel Interfaces
188
189     public static final ImmutableMap<Class<? extends TunnelTypeBase>,
190             Class<? extends InterfaceTypeBase>> TUNNEL_TYPE_MAP = new ImmutableMap
191             .Builder<Class<? extends TunnelTypeBase>, Class<? extends InterfaceTypeBase>>()
192             .put(TunnelTypeGre.class, InterfaceTypeGre.class)
193             .put(TunnelTypeVxlan.class, InterfaceTypeVxlan.class)
194             .put(TunnelTypeVxlanGpe.class, InterfaceTypeVxlan.class).build();
195
196     private static final String TUNNEL_PORT_REGEX = "tun[0-9a-f]{11}";
197     private static final Pattern TUNNEL_PORT_PATTERN = Pattern.compile(TUNNEL_PORT_REGEX);
198     public  static final Predicate<String> TUNNEL_PORT_PREDICATE =
199         portName -> TUNNEL_PORT_PATTERN.matcher(portName).matches();
200
201     private final IdManagerService idManagerService;
202     private final IMdsalApiManager mdsalApiManager;
203     private final EntityOwnershipUtils entityOwnershipUtils;
204     private final ItmConfig itmConfig;
205
206     @Inject
207     public DirectTunnelUtils(final IdManagerService idManagerService, final IMdsalApiManager mdsalApiManager,
208                              final EntityOwnershipUtils entityOwnershipUtils, final ItmConfig itmConfig) {
209         this.idManagerService = idManagerService;
210         this.mdsalApiManager = mdsalApiManager;
211         this.entityOwnershipUtils = entityOwnershipUtils;
212         this.itmConfig = itmConfig;
213     }
214
215     @CheckReturnValue
216     public @NonNull Acquired lockTunnel(String tunnelName) {
217         return tunnelLocks.acquire(tunnelName);
218     }
219
220     public Uint64 getDpnId(DatapathId datapathId) {
221         if (datapathId != null) {
222             String dpIdStr = datapathId.getValue().replace(":", "");
223             return Uint64.valueOf(dpIdStr, 16);
224         }
225         return null;
226     }
227
228     public static Uint64 getDpnFromNodeConnectorId(NodeConnectorId portId) {
229         /*
230          * NodeConnectorId is of form 'openflow:dpnid:portnum'
231          */
232         return Uint64.valueOf(portId.getValue().split(ITMConstants.OF_URI_SEPARATOR)[1]);
233     }
234
235     public static long getPortNumberFromNodeConnectorId(NodeConnectorId portId) {
236         String portNo = getPortNoFromNodeConnectorId(portId);
237         try {
238             return Long.parseLong(portNo);
239         } catch (NumberFormatException ex) {
240             LOG.error("Unable to retrieve port number from nodeconnector id for {} ", portId, ex);
241             return ITMConstants.INVALID_PORT_NO;
242         }
243     }
244
245     private static String getPortNoFromNodeConnectorId(NodeConnectorId portId) {
246         /*
247          * NodeConnectorId is of form 'openflow:dpnid:portnum'
248          */
249         return portId.getValue().split(ITMConstants.OF_URI_SEPARATOR)[2];
250     }
251
252     // Convert Interface Oper State to Tunnel Oper state
253     public static TunnelOperStatus convertInterfaceToTunnelOperState(Interface.OperStatus opState) {
254
255         java.util.Optional<TunnelOperStatus> tunnelOperStatus = TunnelOperStatus.forName(opState.getName());
256         if (tunnelOperStatus.isPresent()) {
257             return tunnelOperStatus.get();
258         }
259         return TunnelOperStatus.Ignore;
260     }
261
262     public static InstanceIdentifier<OvsBridgeTunnelEntry> getBridgeTunnelEntryIdentifier(
263             OvsBridgeEntryKey bridgeEntryKey, OvsBridgeTunnelEntryKey bridgeInterfaceEntryKey) {
264         return InstanceIdentifier.builder(BridgeTunnelInfo.class)
265                 .child(OvsBridgeEntry.class, bridgeEntryKey)
266                 .child(OvsBridgeTunnelEntry.class, bridgeInterfaceEntryKey).build();
267
268     }
269
270     public static InstanceIdentifier<OvsBridgeRefEntry>
271         getOvsBridgeRefEntryIdentifier(OvsBridgeRefEntryKey bridgeRefEntryKey) {
272         return InstanceIdentifier.builder(OvsBridgeRefInfo.class)
273                 .child(OvsBridgeRefEntry.class, bridgeRefEntryKey).build();
274     }
275
276     public static InstanceIdentifier<DpnsTeps> createDpnTepsInstanceIdentifier(Uint64 sourceDpnId) {
277         return InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class,
278             new DpnsTepsKey(sourceDpnId)).build();
279     }
280
281     public static InstanceIdentifier<OvsBridgeEntry> getOvsBridgeEntryIdentifier(OvsBridgeEntryKey bridgeEntryKey) {
282         return InstanceIdentifier.builder(BridgeTunnelInfo.class).child(OvsBridgeEntry.class, bridgeEntryKey).build();
283     }
284
285     public static InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(
286             org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
287                     .network.topology.topology.NodeKey nodekey, String portName) {
288         InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier.create(NetworkTopology.class)
289                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
290                 .child(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
291                         .network.topology.topology.Node.class, nodekey)
292                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
293
294         LOG.debug("Termination point InstanceIdentifier generated : {}", terminationPointPath);
295         return terminationPointPath;
296     }
297
298     public static List<InterfaceBfd> getBfdParams(IfTunnel ifTunnel) {
299         List<InterfaceBfd> bfdParams = new ArrayList<>();
300         bfdParams.add(getIfBfdObj(BFD_PARAM_ENABLE,ifTunnel != null ? ifTunnel.isMonitorEnabled().toString()
301                 : "false"));
302         bfdParams.add(getIfBfdObj(BFD_PARAM_MIN_TX, ifTunnel != null &&  ifTunnel.getMonitorInterval() != null
303                 ? ifTunnel.getMonitorInterval().toString() : BFD_MIN_TX_VAL));
304         bfdParams.add(getIfBfdObj(BFD_PARAM_FORWARDING_IF_RX, BFD_FORWARDING_IF_RX_VAL));
305         bfdParams.add(getIfBfdObj(BFD_PARAM_REMOTE_DST_MAC, BFD_REMOTE_DST_MAC_VAL));
306         bfdParams.add(getIfBfdObj(BFD_PARAM_LOCAL_SRC_MAC, BFD_LOCAL_SRC_MAC_VAL));
307         bfdParams.add(getIfBfdObj(BFD_PARAM_LOCAL_DST_MAC, BFD_LOCAL_DST_MAC_VAL));
308         LOG.debug("getBfdParams {}", bfdParams);
309         return bfdParams;
310     }
311
312     public List<InterfaceBfd> getBfdParams(RemoteDpns remoteDpn) {
313         List<InterfaceBfd> bfdParams = new ArrayList<>();
314         bfdParams.add(getIfBfdObj(BFD_PARAM_ENABLE, remoteDpn != null ? remoteDpn.isMonitoringEnabled().toString()
315             : "false"));
316         bfdParams.add(getIfBfdObj(BFD_PARAM_MIN_TX, remoteDpn != null && remoteDpn.getMonitoringInterval() != null
317             ? remoteDpn.getMonitoringInterval().toString() : BFD_MIN_TX_VAL));
318         bfdParams.add(getIfBfdObj(BFD_PARAM_FORWARDING_IF_RX, BFD_FORWARDING_IF_RX_VAL));
319         bfdParams.add(getIfBfdObj(BFD_PARAM_REMOTE_DST_MAC, BFD_REMOTE_DST_MAC_VAL));
320         bfdParams.add(getIfBfdObj(BFD_PARAM_LOCAL_SRC_MAC, BFD_LOCAL_SRC_MAC_VAL));
321         bfdParams.add(getIfBfdObj(BFD_PARAM_LOCAL_DST_MAC, BFD_LOCAL_DST_MAC_VAL));
322         LOG.debug("getBfdParams {}", bfdParams);
323         LOG.debug("getBfdParams {}", bfdParams);
324         return bfdParams;
325     }
326
327     private static InterfaceBfd getIfBfdObj(String key, String value) {
328         InterfaceBfdBuilder bfdBuilder = new InterfaceBfdBuilder();
329         bfdBuilder.setBfdKey(key).withKey(new InterfaceBfdKey(key)).setBfdValue(value);
330         return bfdBuilder.build();
331     }
332
333     public static boolean bfdMonitoringEnabled(Map<InterfaceBfdKey, InterfaceBfd> interfaceBfds) {
334         if (interfaceBfds != null && !interfaceBfds.isEmpty()) {
335             for (InterfaceBfd interfaceBfd : interfaceBfds.values()) {
336                 if (BFD_ENABLE_KEY.equalsIgnoreCase(interfaceBfd.getBfdKey())) {
337                     return BFD_ENABLE_VALUE.equalsIgnoreCase(interfaceBfd.getBfdValue());
338                 }
339             }
340         }
341         return false;
342     }
343
344     public static boolean changeInBfdMonitoringDetected(OvsdbTerminationPointAugmentation tpOld,
345                                                         OvsdbTerminationPointAugmentation tpNew) {
346         return tpOld != null
347                 && bfdMonitoringEnabled(tpNew.getInterfaceBfd()) != bfdMonitoringEnabled(tpOld.getInterfaceBfd());
348     }
349
350     public static boolean ifBfdStatusNotEqual(OvsdbTerminationPointAugmentation tpOld,
351                                               OvsdbTerminationPointAugmentation tpNew) {
352         return tpNew.getInterfaceBfdStatus() != null
353                 && (tpOld == null || !tpNew.getInterfaceBfdStatus().equals(tpOld.getInterfaceBfdStatus()));
354     }
355
356     public int allocateId(String poolName, String idKey)
357             throws InterruptedException, ExecutionException , OperationFailedException {
358         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
359         RpcResult<AllocateIdOutput> rpcResult = idManagerService.allocateId(getIdInput).get();
360         if (rpcResult.isSuccessful()) {
361             return rpcResult.getResult().getIdValue().intValue();
362         } else {
363             Optional<RpcError> rpcError = rpcResult.getErrors().stream().findFirst();
364             String msg = String.format("RPC Call to Get Unique Id returned with Errors for the key %s", idKey);
365             if (rpcError.isPresent()) {
366                 throw new OperationFailedException(msg, rpcError.get());
367             }
368             else {
369                 throw new OperationFailedException(msg);
370             }
371         }
372     }
373
374     public static void createBridgeTunnelEntryInConfigDS(Uint64 dpId, String childInterface) {
375         OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpId);
376         OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(childInterface);
377         InstanceIdentifier<OvsBridgeTunnelEntry> bridgeTunnelEntryIid =
378                 getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey);
379         OvsBridgeTunnelEntryBuilder entryBuilder = new OvsBridgeTunnelEntryBuilder().withKey(bridgeTunnelEntryKey)
380                 .setTunnelName(childInterface);
381         ITMBatchingUtils.write(bridgeTunnelEntryIid, entryBuilder.build(), ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
382     }
383
384     public void addTunnelIngressFlow(TypedWriteTransaction<Configuration> tx, Uint64 dpnId, long portNo,
385                                      String interfaceName, int ifIndex, Ipv4Address ipAddress) {
386         LOG.debug("Adding tunnel ingress flow for {}", interfaceName);
387         List<MatchInfoBase> matches = new ArrayList<>();
388
389         List<InstructionInfo> mkInstructions = new ArrayList<>();
390         matches.add(new MatchInPort(dpnId, portNo));
391         if (itmConfig.isUseOfTunnels()) {
392             matches.add(new NxMatchTunnelSourceIp(ipAddress));
393         }
394         mkInstructions.add(new InstructionWriteMetadata(
395             Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(ifIndex).longValue() | 1L),
396             MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG));
397         short tableId = NwConstants.INTERNAL_TUNNEL_TABLE;
398         mkInstructions.add(new InstructionGotoTable(tableId));
399
400         String flowRef =
401             getTunnelInterfaceFlowRef(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
402
403         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef,
404             ITMConstants.DEFAULT_FLOW_PRIORITY, interfaceName, 0, 0, NwConstants.COOKIE_VM_INGRESS_TABLE, matches,
405             mkInstructions);
406         mdsalApiManager.addFlow(tx, flowEntity);
407     }
408
409     public void removeTunnelIngressFlow(TypedReadWriteTransaction<Configuration> tx, Uint64 dpnId,
410         String interfaceName) throws ExecutionException, InterruptedException {
411         LOG.debug("Removing tunnel ingress flow for {}", interfaceName);
412         String flowRef =
413             getTunnelInterfaceFlowRef(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
414
415         mdsalApiManager.removeFlow(tx, dpnId, flowRef, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
416     }
417
418     public void addTunnelEgressFlow(TypedWriteTransaction<Configuration> tx, Uint64 dpnId, String portNo,
419                                     int dstId, String interfaceName, IpAddress dstIp) {
420         LOG.debug("add tunnel egress flow for {}", interfaceName);
421         List<MatchInfoBase> matches = new ArrayList<>();
422         List<ActionInfo> actions = new ArrayList<>();
423         matches.add(new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId)));
424         if (itmConfig.isUseOfTunnels()) {
425             actions.add(new ActionSetTunnelDestinationIp(0, dstIp));
426             actions.add(new ActionOutput(1, new Uri(portNo)));
427         } else {
428             actions.add(new ActionOutput(0, new Uri(portNo)));
429         }
430         String flowRef = getTunnelInterfaceFlowRef(dpnId, NwConstants.EGRESS_TUNNEL_TABLE, interfaceName);
431         Instruction instruction = MDSALUtil.buildApplyActionsInstruction(MDSALUtil.buildActions(actions));
432         Flow egressFlow = MDSALUtil.buildFlowNew(NwConstants.EGRESS_TUNNEL_TABLE, flowRef, 5, flowRef,
433                 0, 0, NwConstants.COOKIE_ITM_EGRESS_TUNNEL_TABLE, matches,
434                 Collections.singletonMap(instruction.key(),instruction));
435         mdsalApiManager.addFlow(tx, dpnId, egressFlow);
436     }
437
438     public void removeTunnelEgressFlow(TypedReadWriteTransaction<Configuration> tx, Uint64 dpnId,
439                                        String interfaceName) throws ExecutionException, InterruptedException {
440         LOG.debug("remove tunnel egress flow for {}", interfaceName);
441         String flowRef =
442                 getTunnelInterfaceFlowRef(dpnId, NwConstants.EGRESS_TUNNEL_TABLE, interfaceName);
443         mdsalApiManager.removeFlow(tx, dpnId, flowRef, NwConstants.EGRESS_TUNNEL_TABLE);
444     }
445
446     private String getTunnelInterfaceFlowRef(Uint64 dpnId, short tableId, String ifName) {
447         return String.valueOf(dpnId) + tableId + ifName;
448     }
449
450     public void addTunnelPortToBridge(IfTunnel ifTunnel, InstanceIdentifier<?> bridgeIid,
451                                       org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
452                                               .interfaces.rev140508.interfaces.Interface iface, String portName) {
453         LOG.debug("adding tunnel port {} to bridge {}", portName, bridgeIid);
454
455         Class<? extends InterfaceTypeBase> type =
456                 DirectTunnelUtils.TUNNEL_TYPE_MAP.get(ifTunnel.getTunnelInterfaceType());
457         if (type == null) {
458             LOG.warn("Unknown Tunnel Type obtained while creating interface: {}", iface);
459             return;
460         }
461
462         int vlanId = 0;
463         IfL2vlan ifL2vlan = iface.augmentation(IfL2vlan.class);
464         if (ifL2vlan != null && ifL2vlan.getVlanId() != null) {
465             vlanId = ifL2vlan.getVlanId().getValue().toJava();
466         }
467
468         Builder<String, String> options = new ImmutableMap.Builder<>();
469
470         // Options common to any kind of tunnel
471         options.put(TUNNEL_OPTIONS_KEY, TUNNEL_OPTIONS_VALUE_FLOW);
472         IpAddress localIp = ifTunnel.getTunnelSource();
473         options.put(DirectTunnelUtils.TUNNEL_OPTIONS_LOCAL_IP, localIp.getIpv4Address().getValue());
474
475         if (itmConfig.isUseOfTunnels()) {
476             options.put(TUNNEL_OPTIONS_REMOTE_IP, TUNNEL_OPTIONS_VALUE_FLOW);
477         } else {
478             IpAddress remoteIp = ifTunnel.getTunnelDestination();
479             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_REMOTE_IP, remoteIp.getIpv4Address().getValue());
480         }
481
482         options.put(DirectTunnelUtils.TUNNEL_OPTIONS_TOS, DirectTunnelUtils.TUNNEL_OPTIONS_TOS_VALUE_INHERIT);
483
484         // Specific options for each type of tunnel
485         if (TunnelTypeVxlanGpe.class.equals(ifTunnel.getTunnelInterfaceType())) {
486             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_EXTS, DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_GPE);
487             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_NSI, DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_FLOW);
488             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_NSP, DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_FLOW);
489             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_NSHC1, DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_FLOW);
490             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_NSHC2, DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_FLOW);
491             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_NSHC3, DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_FLOW);
492             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_NSHC4, DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_FLOW);
493             // VxLAN-GPE interfaces will not use the default UDP port to avoid problems with other meshes
494             options.put(DirectTunnelUtils.TUNNEL_OPTIONS_DESTINATION_PORT,
495                     DirectTunnelUtils.TUNNEL_OPTIONS_VALUE_GPE_DESTINATION_PORT);
496         }
497         addTerminationPoint(bridgeIid, portName, vlanId, type, options.build(), ifTunnel);
498     }
499
500     private void addTerminationPoint(InstanceIdentifier<?> bridgeIid, String portName, int vlanId,
501                                      Class<? extends InterfaceTypeBase> type, Map<String, String> options,
502                                      IfTunnel ifTunnel) {
503         final InstanceIdentifier<TerminationPoint> tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier(
504                 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(
505                         org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
506                                 .network.topology.rev131021.network.topology.topology.Node.class)), portName);
507         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
508
509         tpAugmentationBuilder.setName(portName);
510
511         if (type != null) {
512             tpAugmentationBuilder.setInterfaceType(type);
513         }
514
515         if (options != null) {
516             List<Options> optionsList = new ArrayList<>();
517             for (Map.Entry<String, String> entry : options.entrySet()) {
518                 OptionsBuilder optionsBuilder = new OptionsBuilder();
519                 optionsBuilder.withKey(new OptionsKey(entry.getKey()));
520                 optionsBuilder.setOption(entry.getKey());
521                 optionsBuilder.setValue(entry.getValue());
522                 optionsList.add(optionsBuilder.build());
523             }
524             tpAugmentationBuilder.setOptions(optionsList);
525         }
526
527         if (vlanId != 0) {
528             tpAugmentationBuilder.setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Access);
529             tpAugmentationBuilder.setVlanTag(new VlanId(Uint16.valueOf(vlanId)));
530         }
531
532         if (itmConfig.isUseOfTunnels()) {
533             LOG.warn("BFD Monitoring not supported for OFTunnels");
534         } else if (ifTunnel.isMonitorEnabled()
535                 && TunnelMonitoringTypeBfd.class.isAssignableFrom(ifTunnel.getMonitorProtocol())) { //checkBfdMonEnabled
536             List<InterfaceBfd> bfdParams = DirectTunnelUtils.getBfdParams(ifTunnel);
537             tpAugmentationBuilder.setInterfaceBfd(bfdParams);
538         }
539
540         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
541         tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
542         tpBuilder.addAugmentation(tpAugmentationBuilder.build());
543
544         ITMBatchingUtils.write(tpIid, tpBuilder.build(), ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
545     }
546
547     public void removeLportTagInterfaceMap(String infName)
548             throws ExecutionException, InterruptedException, OperationFailedException {
549         // workaround to get the id to remove from lport tag interface map
550         Integer ifIndex = allocateId(IfmConstants.IFM_IDPOOL_NAME, infName);
551         releaseId(IfmConstants.IFM_IDPOOL_NAME, infName);
552         LOG.debug("removing lport tag to interface map for {}", infName);
553         InstanceIdentifier<IfIndexTunnel> id = InstanceIdentifier.builder(IfIndexesTunnelMap.class)
554                 .child(IfIndexTunnel.class, new IfIndexTunnelKey(ifIndex)).build();
555         ITMBatchingUtils.delete(id, ITMBatchingUtils.EntityType.DEFAULT_OPERATIONAL);
556     }
557
558     private void releaseId(String poolName, String idKey) throws InterruptedException, ExecutionException,
559             OperationFailedException {
560         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
561         ListenableFuture<RpcResult<ReleaseIdOutput>> result = idManagerService.releaseId(idInput);
562         RpcResult<ReleaseIdOutput> rpcResult = result.get();
563         if (!rpcResult.isSuccessful()) {
564             LOG.error("RPC Call to release Id with Key {} returned with Errors {}", idKey, rpcResult.getErrors());
565             Optional<RpcError> rpcError = rpcResult.getErrors().stream().findFirst();
566             String msg = String.format("RPC Call to release Id returned with Errors for the key %s", idKey);
567             if (rpcError.isPresent()) {
568                 throw new OperationFailedException(msg, rpcError.get());
569             }
570             else {
571                 throw new OperationFailedException(msg);
572             }
573         }
574     }
575
576     public void deleteTunnelStateEntry(String interfaceName) {
577         LOG.debug(" deleteTunnelStateEntry tunnels state for {}", interfaceName);
578         InstanceIdentifier<StateTunnelList> stateTnlId =
579                 ItmUtils.buildStateTunnelListId(new StateTunnelListKey(interfaceName));
580         ITMBatchingUtils.delete(stateTnlId, ITMBatchingUtils.EntityType.DEFAULT_OPERATIONAL);
581     }
582
583     public void updateBfdConfiguration(Uint64 srcDpnId, RemoteDpns remoteDpn,
584                                        Optional<OvsBridgeRefEntry> ovsBridgeRefEntry) {
585         if (ovsBridgeRefEntry.isPresent()) {
586             LOG.debug("creating bridge interface on dpn {}", srcDpnId);
587             InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid =
588                 (InstanceIdentifier<OvsdbBridgeAugmentation>) ovsBridgeRefEntry.get()
589                     .getOvsBridgeReference().getValue();
590             updateBfdParamtersForTerminationPoint(bridgeIid, remoteDpn);
591         }
592     }
593
594     public void updateBfdParamtersForTerminationPoint(InstanceIdentifier<?> bridgeIid, RemoteDpns remoteDpn) {
595         final InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
596             InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(
597                 org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
598                     .network.topology.rev131021.network.topology.topology.Node.class)), remoteDpn.getTunnelName());
599         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
600         List<InterfaceBfd> bfdParams = getBfdParams(remoteDpn);
601         tpAugmentationBuilder.setInterfaceBfd(bfdParams);
602         LOG.debug("OvsdbTerminationPointAugmentation: {}", tpAugmentationBuilder);
603         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
604         tpBuilder.withKey(InstanceIdentifier.keyOf(tpIid));
605         tpBuilder.addAugmentation(tpAugmentationBuilder.build());
606         ITMBatchingUtils.update(tpIid, tpBuilder.build(), ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
607     }
608
609     public boolean isEntityOwner() {
610         return entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY);
611     }
612
613     public static String generateOfPortName(Uint64 dpId, String tunnelType) {
614         String trunkInterfaceName = dpId + ":" + tunnelType;
615         return "of" + UUID.nameUUIDFromBytes(trunkInterfaceName.getBytes(StandardCharsets.UTF_8)).toString()
616                 .substring(0, 12).replace("-", "");
617     }
618
619     public void deleteOfTepStateEntry(String ofTepName) {
620         LOG.debug("deleteOfTepStateEntry ofTeps state for {}", ofTepName);
621         InstanceIdentifier<OfTep> ofTeplId =
622                 ItmUtils.buildStateOfTepListId(new OfTepKey(ofTepName));
623         ITMBatchingUtils.delete(ofTeplId, ITMBatchingUtils.EntityType.DEFAULT_OPERATIONAL);
624     }
625
626     public static void removeOfTepFromDpnsTepConfigDS(DataBroker dataBroker, Uint64 srcDpnId)
627             throws TransactionCommitFailedException {
628         // The source DPn id is the one to be removed
629         InstanceIdentifier<OfDpnTep> dpntepII = buildDpnTepInstanceIdentifier(srcDpnId);
630         SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, dpntepII);
631     }
632
633     private static InstanceIdentifier<OfDpnTep> buildDpnTepInstanceIdentifier(Uint64 srcDpnId) {
634         return InstanceIdentifier.builder(DpnTepConfig.class).child(OfDpnTep.class, new OfDpnTepKey(srcDpnId)).build();
635     }
636 }