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