Moving TableIds into a single constants file
[vpnservice.git] / interfacemgr / interfacemgr-impl / src / main / java / org / opendaylight / vpnservice / interfacemgr / servicebindings / flowbased / utilities / FlowBasedServicesUtils.java
1 /*
2  * Copyright (c) 2015 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.servicebindings.flowbased.utilities;
9
10 import com.google.common.base.Optional;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
15 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
16 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
17 import org.opendaylight.vpnservice.mdsalutil.*;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceBindings;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflow;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfoKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import java.math.BigInteger;
44 import java.util.ArrayList;
45 import java.util.List;
46
47 public class FlowBasedServicesUtils {
48     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
49
50     public static ServicesInfo getServicesInfoForInterface(String interfaceName, DataBroker dataBroker) {
51         ServicesInfoKey servicesInfoKey = new ServicesInfoKey(interfaceName);
52         InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
53                 InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
54         Optional<ServicesInfo> servicesInfoOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION,
55                 servicesInfoIdentifierBuilder.build(), dataBroker);
56
57         if (servicesInfoOptional.isPresent()) {
58             return servicesInfoOptional.get();
59         }
60
61         return null;
62     }
63
64     public static NodeConnectorId getNodeConnectorIdFromInterface(Interface iface, DataBroker dataBroker) {
65         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
66                 InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(iface.getName(), dataBroker);
67         if(ifState != null) {
68             List<String> ofportIds = ifState.getLowerLayerIf();
69             return new NodeConnectorId(ofportIds.get(0));
70         }
71         return null;
72     }
73
74     public static List<MatchInfo> getMatchInfoForVlanPortAtIngressTable(BigInteger dpId, long portNo, Interface iface) {
75         List<MatchInfo> matches = new ArrayList<>();
76         matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)}));
77         int vlanId = 0;
78         IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
79         if(l2vlan != null){
80             vlanId = l2vlan.getVlanId().getValue();
81         }
82         if (vlanId > 0) {
83             LOG.error("VlanId matching support is not fully available in Be.");
84             matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[]{vlanId}));
85         }
86         return matches;
87     }
88
89     public static List<MatchInfo> getMatchInfoForTunnelPortAtIngressTable(BigInteger dpId, long portNo, Interface iface) {
90         List<MatchInfo> matches = new ArrayList<MatchInfo>();
91         matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[]{dpId, BigInteger.valueOf(portNo)}));
92         return matches;
93     }
94
95     public static List<MatchInfo> getMatchInfoForDispatcherTable(BigInteger dpId, Interface iface,
96                                                                  int interfaceTag, short servicePriority) {
97         List<MatchInfo> matches = new ArrayList<MatchInfo>();
98         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
99                 MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, servicePriority),
100                 MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
101         return matches;
102     }
103
104     public static Long getLPortTag(Interface iface, DataBroker dataBroker) {
105         /*ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
106         String portName = parentRefs.getParentInterface();
107         BigInteger dpIdFromInterface = parentRefs.getDatapathNodeIdentifier();
108         String portKey = FlowBasedServicesUtils.getInterfaceRefInfo(dpIdFromInterface.toString(), portName);
109         if (iface.getType().isAssignableFrom(L2vlan.class)) {
110             InterfacesMetaKey interfacesMetaKey = new InterfacesMetaKey(portKey);
111             InterfacesInfoKey interfacesInfoKey = new InterfacesInfoKey(iface.getName());
112             InterfacesInfo interfacesInfo = VlanInterfaceUtilities.getInterfacesInfoFromConfigDS(interfacesMetaKey,
113                     interfacesInfoKey, dataBroker);
114             return interfacesInfo.getLporttag();
115         } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
116             TunnelInterfaceRefInfoKey tunnelInterfaceRefInfoKey = new TunnelInterfaceRefInfoKey(portKey);
117             TunnelInterfaceEntries tunnelInterfaceEntries =
118                     TunnelInterfaceUtilities.getTunnelInterfaceRefEntriesFromConfigDs(
119                             tunnelInterfaceRefInfoKey, iface.getName(), dataBroker);
120             return tunnelInterfaceEntries.getLportTag();
121         } */
122         return 0L;
123     }
124
125     public static void installInterfaceIngressFlow(BigInteger dpId, Interface iface,
126                                                    BoundServices boundServiceNew,
127                                                    WriteTransaction t,
128                                                    List<MatchInfo> matches, int lportTag, short tableId) {
129         List<Instruction> instructions = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction();
130
131         int serviceInstructionsSize = instructions.size();
132         List<Instruction> instructionSet = new ArrayList<Instruction>();
133         int vlanId = 0;
134         IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
135         if(l2vlan != null){
136             vlanId = l2vlan.getVlanId().getValue();
137         }
138         if (vlanId != 0) {
139             // incrementing instructionSize and using it as actionKey. Because it won't clash with any other instructions
140             int actionKey = ++serviceInstructionsSize;
141             instructionSet.add(MDSALUtil.buildAndGetPopVlanActionInstruction(actionKey, ++serviceInstructionsSize));
142         }
143
144         if (lportTag != 0L) {
145             BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
146             short sIndex = boundServiceNew.getServicePriority();
147             BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
148                     ++sIndex, metadataValues[0]);
149             BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(
150                     MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
151                     MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
152             instructionSet.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask,
153                     ++serviceInstructionsSize));
154         }
155
156         if (instructions != null && !instructions.isEmpty()) {
157             for (Instruction info : instructions) {
158                 // Skip meta data write as that is handled already
159                 if (info.getInstruction() instanceof WriteMetadataCase) {
160                     continue;
161                 }
162                 instructionSet.add(info);
163             }
164         }
165
166         String serviceRef = boundServiceNew.getServiceName();
167         String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew);
168         StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
169         Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
170                 stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
171                 stypeOpenflow.getFlowCookie(), matches, instructionSet);
172         installFlow(dpId, ingressFlow, t);
173     }
174
175     public static void installFlow(BigInteger dpId, Flow flow, WriteTransaction t) {
176         FlowKey flowKey = new FlowKey(new FlowId(flow.getId()));
177         Node nodeDpn = buildInventoryDpnNode(dpId);
178         InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
179                 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
180                 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class,flowKey).build();
181
182         t.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
183     }
184
185     public static void removeFlow(String flowRef, BigInteger dpId, WriteTransaction t) {
186         LOG.debug("Removing Ingress Flows");
187         FlowKey flowKey = new FlowKey(new FlowId(flowRef));
188         Node nodeDpn = buildInventoryDpnNode(dpId);
189         InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
190                 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
191                 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
192
193         t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
194     }
195
196     private static Node buildInventoryDpnNode(BigInteger dpnId) {
197         NodeId nodeId = new NodeId("openflow:" + dpnId);
198         Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
199
200         return nodeDpn;
201     }
202
203     public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, Interface iface,
204                                                   WriteTransaction t, int interfaceTag) {
205         LOG.debug("Installing LPort Dispatcher Flows {}, {}", dpId, iface);
206         short serviceIndex = boundService.getServicePriority();
207         String serviceRef = boundService.getServiceName();
208         List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId, iface,
209                 interfaceTag, serviceIndex);
210
211         // Get the metadata and mask from the service's write metadata instruction
212         StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
213         List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
214         int instructionSize = serviceInstructions.size();
215         BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
216         BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, ++serviceIndex, metadataValues[0]);
217         BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
218                 MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
219
220         // build the final instruction for LPort Dispatcher table flow entry
221         List<Instruction> instructions = new ArrayList<Instruction>();
222         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, ++instructionSize));
223         if (serviceInstructions != null && !serviceInstructions.isEmpty()) {
224             for (Instruction info : serviceInstructions) {
225                 // Skip meta data write as that is handled already
226                 if (info.getInstruction() instanceof WriteMetadataCase) {
227                     continue;
228                 }
229                 instructions.add(info);
230             }
231         }
232
233         // build the flow and install it
234         String flowRef = getFlowRef(dpId, iface.getName(), boundService);
235         Flow ingressFlow = MDSALUtil.buildFlowNew(stypeOpenFlow.getDispatcherTableId(), flowRef,
236                 boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
237         installFlow(dpId, ingressFlow, t);
238     }
239
240     public static void removeIngressFlow(Interface iface, BoundServices serviceOld, BigInteger dpId, WriteTransaction t) {
241         LOG.debug("Removing Ingress Flows");
242         String flowKeyStr = getFlowRef(dpId, iface.getName(), serviceOld);
243         FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
244         Node nodeDpn = buildInventoryDpnNode(dpId);
245         InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
246                 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
247                 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
248
249         t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
250     }
251
252     public static void removeLPortDispatcherFlow(BigInteger dpId, Interface iface, BoundServices boundServicesOld, WriteTransaction t) {
253         LOG.debug("Removing LPort Dispatcher Flows {}, {}", dpId, iface);
254
255         StypeOpenflow stypeOpenFlow = boundServicesOld.getAugmentation(StypeOpenflow.class);
256         // build the flow and install it
257         String flowRef = getFlowRef(dpId, iface.getName(), boundServicesOld);
258         FlowKey flowKey = new FlowKey(new FlowId(flowRef));
259         Node nodeDpn = buildInventoryDpnNode(dpId);
260         InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
261                 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
262                 .child(Table.class, new TableKey(stypeOpenFlow.getDispatcherTableId())).child(Flow.class, flowKey).build();
263
264         t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
265     }
266
267     private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service) {
268         return new StringBuffer().append(dpnId).append( NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
269                 .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(service.getServiceName()).append(NwConstants.FLOWID_SEPARATOR)
270                 .append(service.getServicePriority()).toString();
271     }
272 }