Bug 5334 : Delete ELANport , ELAN instance VLAN and re-create
[vpnservice.git] / interfacemgr / interfacemgr-impl / src / main / java / org / opendaylight / vpnservice / interfacemgr / IfmUtil.java
1 /*
2  * Copyright (c) 2015 - 2016 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.vpnservice.interfacemgr;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
15
16 import com.google.common.base.Optional;
17
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
22 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
23 import org.opendaylight.vpnservice.interfacemgr.globals.VlanInterfaceInfo;
24 import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
25 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
26 import org.opendaylight.vpnservice.mdsalutil.ActionType;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan.L2vlanMode;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
55 import org.opendaylight.yangtools.yang.binding.DataObject;
56 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
58 import org.opendaylight.yangtools.yang.common.RpcResult;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 public class IfmUtil {
63     private static final Logger LOG = LoggerFactory.getLogger(IfmUtil.class);
64     private static final int INVALID_ID = 0;
65     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
66         /*
67          * NodeConnectorId is of form 'openflow:dpnid:portnum'
68          */
69         String[] split = portId.getValue().split(IfmConstants.OF_URI_SEPARATOR);
70         return split[1];
71     }
72
73     public static BigInteger getDpnFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState){
74         NodeConnectorId ncId = getNodeConnectorIdFromInterface(ifState);
75         if(ncId != null){
76             return new BigInteger(getDpnFromNodeConnectorId(ncId));
77         }
78         return null;
79     }
80     public static String getPortNoFromInterfaceName(String ifaceName, DataBroker broker) {
81         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
82                 InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(ifaceName, broker);
83
84         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
85         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
86         String portNo = IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId);
87
88         return portNo;
89     }
90
91     public static String getPortNoFromNodeConnectorId(NodeConnectorId portId) {
92         /*
93          * NodeConnectorId is of form 'openflow:dpnid:portnum'
94          */
95         String[] split = portId.getValue().split(IfmConstants.OF_URI_SEPARATOR);
96         return split[2];
97     }
98
99     public static NodeId buildDpnNodeId(BigInteger dpnId) {
100         return new NodeId(IfmConstants.OF_URI_PREFIX + dpnId);
101     }
102
103     public static InstanceIdentifier<Interface> buildId(String interfaceName) {
104         //TODO Make this generic and move to AbstractDataChangeListener or Utils.
105         InstanceIdentifierBuilder<Interface> idBuilder =
106                 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
107         InstanceIdentifier<Interface> id = idBuilder.build();
108         return id;
109     }
110
111     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
112         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
113                 InstanceIdentifier.builder(InterfacesState.class)
114                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
115                         new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
116         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
117         return id;
118     }
119
120     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey getStateInterfaceKeyFromName(
121                     String name) {
122         return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(name);
123     }
124
125     public static InstanceIdentifier<IdPool> getPoolId(String poolName){
126         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
127                         InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
128         InstanceIdentifier<IdPool> id = idBuilder.build();
129         return id;
130     }
131
132     public static List<String> getPortNameAndSuffixFromInterfaceName(String intfName) {
133         List<String> strList = new ArrayList<>(2);
134         int index = intfName.indexOf(":");
135         if (index != -1) {
136             strList.add(0, intfName.substring(0, index));
137             strList.add(1, intfName.substring(index));
138         }
139         return strList;
140     }
141
142     public static long getGroupId(long ifIndex, InterfaceInfo.InterfaceType infType) {
143         if (infType == InterfaceInfo.InterfaceType.LOGICAL_GROUP_INTERFACE) {
144             return ifIndex + IfmConstants.LOGICAL_GROUP_START;
145         }
146         else if (infType == InterfaceInfo.InterfaceType.VLAN_INTERFACE) {
147             return ifIndex + IfmConstants.VLAN_GROUP_START;
148         } else {
149             return ifIndex + IfmConstants.TRUNK_GROUP_START;
150         }
151     }
152
153     public static List<String> getDpIdPortNameAndSuffixFromInterfaceName(String intfName) {
154         List<String> strList = new ArrayList<>(3);
155         int index1 = intfName.indexOf(":");
156         if (index1 != -1) {
157             int index2 = intfName.indexOf(":", index1 + 1 );
158             strList.add(0, intfName.substring(0, index1));
159             if (index2 != -1) {
160                 strList.add(1, intfName.substring(index1, index2));
161                 strList.add(2, intfName.substring(index2));
162             } else {
163                 strList.add(1, intfName.substring(index1));
164                 strList.add(2, "");
165             }
166         }
167         return strList;
168     }
169
170     public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
171                                                           InstanceIdentifier<T> path, DataBroker broker) {
172
173         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
174
175         Optional<T> result = Optional.absent();
176         try {
177             result = tx.read(datastoreType, path).get();
178         } catch (Exception e) {
179             throw new RuntimeException(e);
180         }
181
182         return result;
183     }
184
185     public static List<Action> getEgressActions(String interfaceName, long serviceTag, DataBroker dataBroker) {
186         List<ActionInfo> listActionInfo = new ArrayList<>();
187         List<ActionInfo> interfaceActionList = IfmUtil.getEgressActionInfosForInterface(interfaceName, serviceTag, dataBroker);
188         listActionInfo.addAll(interfaceActionList);
189         List<Action> actionsList = new ArrayList<>();
190         for (ActionInfo actionInfo : listActionInfo) {
191             actionsList.add(actionInfo.buildAction());
192         }
193         return actionsList;
194     }
195
196     public static List<Action> getEgressActionsForInterface(String interfaceName, DataBroker dataBroker) {
197         List<ActionInfo> listActionInfo = getEgressActionInfosForInterface(interfaceName, 0, dataBroker);
198         List<Action> actionsList = new ArrayList<>();
199         for (ActionInfo actionInfo : listActionInfo) {
200             actionsList.add(actionInfo.buildAction());
201         }
202         return actionsList;
203     }
204
205     public static List<ActionInfo> getEgressActionInfosForInterface(String interfaceName, int actionKeyStart, DataBroker dataBroker) {
206         Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName),
207                 dataBroker);
208         List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
209         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
210                 InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
211
212         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
213         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
214         String portNo = IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId);
215         Class<? extends InterfaceType> ifType = interfaceInfo.getType();
216         if(L2vlan.class.equals(ifType)){
217             IfL2vlan vlanIface = interfaceInfo.getAugmentation(IfL2vlan.class);
218             LOG.trace("L2Vlan: {}",vlanIface);
219             long vlanVid = (vlanIface == null) ? 0 :
220                     vlanIface.getVlanId() == null ? 0 : vlanIface.getVlanId().getValue();
221             if (vlanVid != 0) {
222                 listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}, actionKeyStart));
223                 actionKeyStart++;
224                 listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
225                         new String[] { Long.toString(vlanVid) }, actionKeyStart));
226                 actionKeyStart++;
227             }
228             listActionInfo.add(new ActionInfo(ActionType.output, new String[] {portNo}, actionKeyStart));
229         }else if(Tunnel.class.equals(ifType)){
230             listActionInfo.add(new ActionInfo(ActionType.output, new String[] { portNo}, actionKeyStart));
231         }
232         return listActionInfo;
233     }
234
235     public static List<ActionInfo> getEgressActionInfosForInterface(String interfaceName, long serviceTag, DataBroker dataBroker) {
236         int actionKey = 0;
237         ActionInfo actionSetTunnel = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
238                 BigInteger.valueOf(serviceTag)}, actionKey) ;
239         List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
240         listActionInfo.add(actionSetTunnel);
241         actionKey++;
242         listActionInfo.addAll(getEgressActionInfosForInterface(interfaceName, actionKey, dataBroker));
243         return listActionInfo;
244      }
245
246     public static NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) {
247         return new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":")));
248     }
249
250     public static BigInteger[] mergeOpenflowMetadataWriteInstructions(List<Instruction> instructions) {
251         BigInteger metadata = new BigInteger("0", 16);
252         BigInteger metadataMask = new BigInteger("0", 16);
253         if (instructions != null && !instructions.isEmpty()) {
254             // check if metadata write instruction is present
255             for (Instruction instruction : instructions) {
256                 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction actualInstruction = instruction.getInstruction();
257                 if (actualInstruction instanceof WriteMetadataCase) {
258                     WriteMetadataCase writeMetaDataInstruction = (WriteMetadataCase) actualInstruction ;
259                     WriteMetadata availableMetaData = writeMetaDataInstruction.getWriteMetadata();
260                     metadata = metadata.or(availableMetaData.getMetadata());
261                     metadataMask = metadataMask.or(availableMetaData.getMetadataMask());
262                 }
263             }
264         }
265         return new BigInteger[] { metadata, metadataMask };
266     }
267
268     public static Integer allocateId(IdManagerService idManager, String poolName, String idKey) {
269         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
270                 .setPoolName(poolName)
271                 .setIdKey(idKey).build();
272         try {
273             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
274             RpcResult<AllocateIdOutput> rpcResult = result.get();
275             if(rpcResult.isSuccessful()) {
276                 return rpcResult.getResult().getIdValue().intValue();
277             } else {
278                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
279             }
280         } catch (InterruptedException | ExecutionException e) {
281             LOG.warn("Exception when getting Unique Id",e);
282         }
283         return INVALID_ID;
284     }
285
286     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
287         ReleaseIdInput idInput = new ReleaseIdInputBuilder()
288                 .setPoolName(poolName)
289                 .setIdKey(idKey).build();
290         try {
291             Future<RpcResult<Void>> result = idManager.releaseId(idInput);
292             RpcResult<Void> rpcResult = result.get();
293             if(!rpcResult.isSuccessful()) {
294                 LOG.warn("RPC Call to release Id {} with Key {} returned with Errors {}",
295                         idKey, rpcResult.getErrors());
296             }
297         } catch (InterruptedException | ExecutionException e) {
298             LOG.warn("Exception when releasing Id for key {}", idKey, e);
299         }
300     }
301
302     public static BigInteger getDpnId(DatapathId datapathId){
303         if (datapathId != null) {
304             // Adding logs for a random issue spotted during datapath id conversion
305             LOG.info("Received datapathId {}",datapathId.getValue());
306             String dpIdStr = datapathId.getValue().replace(":", "");
307             LOG.info("Received datapathId {}",dpIdStr);
308             BigInteger dpnId =  new BigInteger(dpIdStr, 16);
309             LOG.info("After conversion datapathId {}",dpnId);
310             return dpnId;
311         }
312         return null;
313     }
314
315     public static NodeConnectorId getNodeConnectorIdFromInterface(Interface iface, DataBroker dataBroker) {
316         return FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
317     }
318
319     public static NodeConnectorId getNodeConnectorIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState){
320         if(ifState != null) {
321             List<String> ofportIds = ifState.getLowerLayerIf();
322             return new NodeConnectorId(ofportIds.get(0));
323         }
324         return null;
325     }
326
327     public static InterfaceInfo.InterfaceType getInterfaceType(Interface iface) {
328         InterfaceInfo.InterfaceType interfaceType =
329                 org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType.UNKNOWN_INTERFACE;
330         Class<? extends org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType> ifType = iface.getType();
331
332         if (ifType.isAssignableFrom(L2vlan.class)) {
333             interfaceType =  org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType.VLAN_INTERFACE;
334         } else if (ifType.isAssignableFrom(Tunnel.class)) {
335             IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
336             Class<? extends  org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase> tunnelType = ifTunnel.getTunnelInterfaceType();
337             if (tunnelType.isAssignableFrom(TunnelTypeVxlan.class)) {
338                 interfaceType = InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE;
339             } else if (tunnelType.isAssignableFrom(TunnelTypeGre.class)) {
340                 interfaceType = InterfaceInfo.InterfaceType.GRE_TRUNK_INTERFACE;
341             }
342         }
343         // TODO: Check if the below condition is still needed/valid
344         //else if (ifType.isAssignableFrom(InterfaceGroup.class)) {
345         //    interfaceType =  org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType.LOGICAL_GROUP_INTERFACE;
346         //}
347         return interfaceType;
348     }
349
350     public static VlanInterfaceInfo getVlanInterfaceInfo(String interfaceName, Interface iface, BigInteger dpId){
351         IfL2vlan vlanIface = iface.getAugmentation(IfL2vlan.class);
352
353         short vlanId = 0;
354         //FIXME :Use this below thing properly
355         VlanInterfaceInfo vlanInterfaceInfo = new VlanInterfaceInfo(dpId, "someString", vlanId);
356
357         if (vlanIface != null) {
358             vlanId = vlanIface.getVlanId() == null ? 0 : vlanIface.getVlanId().getValue().shortValue();
359             L2vlanMode l2VlanMode = vlanIface.getL2vlanMode();
360
361             if (l2VlanMode == L2vlanMode.Transparent) {
362                 vlanInterfaceInfo.setVlanTransparent(true);
363             }
364             if (l2VlanMode == L2vlanMode.NativeUntagged) {
365                 vlanInterfaceInfo.setUntaggedVlan(true);
366             }
367             vlanInterfaceInfo.setVlanId(vlanId);
368
369         }
370         return vlanInterfaceInfo;
371     }
372 }