2 * Copyright (c) 2016 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.interfacemanager.servicebindings.flowbased.utilities;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.ImmutableBiMap;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.List;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.genius.interfacemanager.IfmConstants;
22 import org.opendaylight.genius.interfacemanager.IfmUtil;
23 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
24 import org.opendaylight.genius.mdsalutil.MatchFieldType;
25 import org.opendaylight.genius.mdsalutil.MatchInfo;
26 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
27 import org.opendaylight.genius.mdsalutil.MDSALUtil;
28 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
29 import org.opendaylight.genius.mdsalutil.NwConstants;
30 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
31 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
32 import org.opendaylight.genius.utils.ServiceIndex;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
66 public class FlowBasedServicesUtils {
67 private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
69 public enum ServiceMode {
74 public static final ImmutableBiMap SERVICE_MODE_MAP =
75 new ImmutableBiMap.Builder<ServiceMode, Class<? extends ServiceModeBase>>()
76 .put(ServiceMode.EGRESS, ServiceModeEgress.class)
77 .put(ServiceMode.INGRESS, ServiceModeIngress.class)
80 public static ServicesInfo getServicesInfoForInterface(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
81 DataBroker dataBroker) {
82 ServicesInfoKey servicesInfoKey = new ServicesInfoKey(interfaceName,serviceMode);
83 InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
84 InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
85 Optional<ServicesInfo> servicesInfoOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION,
86 servicesInfoIdentifierBuilder.build(), dataBroker);
88 if (servicesInfoOptional.isPresent()) {
89 return servicesInfoOptional.get();
95 public static NodeConnectorId getNodeConnectorIdFromInterface(String interfaceName, DataBroker dataBroker) {
96 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
97 InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
99 List<String> ofportIds = ifState.getLowerLayerIf();
100 return new NodeConnectorId(ofportIds.get(0));
105 public static NodeConnectorId getNodeConnectorIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
106 if(ifState != null) {
107 List<String> ofportIds = ifState.getLowerLayerIf();
108 return new NodeConnectorId(ofportIds.get(0));
113 public static BigInteger getDpnIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
114 NodeConnectorId nodeConnectorId = null;
115 if(ifState != null) {
116 List<String> ofportIds = ifState.getLowerLayerIf();
117 nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
119 return new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
122 public static List<MatchInfo> getMatchInfoForVlanPortAtIngressTable(BigInteger dpId, long portNo, Interface iface) {
123 List<MatchInfo> matches = new ArrayList<>();
124 matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)}));
126 IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
127 if(l2vlan != null && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent){
128 vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
131 matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[]{vlanId}));
136 public static List<MatchInfo> getMatchInfoForTunnelPortAtIngressTable(BigInteger dpId, long portNo) {
137 List<MatchInfo> matches = new ArrayList<>();
138 matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[]{dpId, BigInteger.valueOf(portNo)}));
142 public static List<MatchInfo> getMatchInfoForDispatcherTable(BigInteger dpId,
143 int interfaceTag, short servicePriority) {
144 List<MatchInfo> matches = new ArrayList<>();
145 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
146 MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, servicePriority),
147 MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
151 public static List<NxMatchInfo> getMatchInfoForEgressDispatcherTable(int interfaceTag, short serviceIndex) {
152 List<NxMatchInfo> matches = new ArrayList<>();
153 matches.add(new NxMatchInfo(NxMatchFieldType.nxm_reg_6, new long[] {
154 MetaDataUtil.getReg6ValueForLPortDispatcher(interfaceTag, serviceIndex)}));
158 public static void installInterfaceIngressFlow(BigInteger dpId, Interface iface,
159 BoundServices boundServiceNew,
161 List<MatchInfo> matches, int lportTag, short tableId) {
162 List<Instruction> instructions = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction();
164 int serviceInstructionsSize = instructions.size();
165 List<Instruction> instructionSet = new ArrayList<>();
167 IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
168 if(l2vlan != null && l2vlan.getVlanId() != null){
169 vlanId = l2vlan.getVlanId().getValue();
172 // incrementing instructionSize and using it as actionKey. Because it won't clash with any other instructions
173 int actionKey = ++serviceInstructionsSize;
174 instructionSet.add(MDSALUtil.buildAndGetPopVlanActionInstruction(actionKey, ++serviceInstructionsSize));
177 if (lportTag != 0L) {
178 BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
179 short sIndex = boundServiceNew.getServicePriority();
180 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
181 ++sIndex, metadataValues[0], isExternal(iface));
182 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(
183 MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
184 MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG, metadataValues[1]);
185 instructionSet.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask,
186 ++serviceInstructionsSize));
189 if (instructions != null && !instructions.isEmpty()) {
190 for (Instruction info : instructions) {
191 // Skip meta data write as that is handled already
192 if (info.getInstruction() instanceof WriteMetadataCase) {
195 instructionSet.add(info);
199 String serviceRef = boundServiceNew.getServiceName();
200 String flowRef = getFlowRef(dpId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, iface.getName(),
201 boundServiceNew, boundServiceNew.getServicePriority());
202 StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
203 Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
204 stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
205 stypeOpenflow.getFlowCookie(), matches, instructionSet);
206 installFlow(dpId, ingressFlow, t);
209 public static void installFlow(BigInteger dpId, Flow flow, WriteTransaction t) {
210 FlowKey flowKey = new FlowKey(new FlowId(flow.getId()));
211 Node nodeDpn = buildInventoryDpnNode(dpId);
212 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
213 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
214 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class,flowKey).build();
216 t.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
219 public static void removeFlow(String flowRef, BigInteger dpId, WriteTransaction t) {
220 LOG.debug("Removing Ingress Flows");
221 FlowKey flowKey = new FlowKey(new FlowId(flowRef));
222 Node nodeDpn = buildInventoryDpnNode(dpId);
223 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
224 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
225 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
227 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
230 private static Node buildInventoryDpnNode(BigInteger dpnId) {
231 NodeId nodeId = new NodeId("openflow:" + dpnId);
232 Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
237 public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, String interfaceName,
238 WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
239 LOG.debug("Installing LPort Dispatcher Flow {}, {}", dpId, interfaceName);
240 String serviceRef = boundService.getServiceName();
241 List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId,
242 interfaceTag, currentServiceIndex);
244 // Get the metadata and mask from the service's write metadata instruction
245 StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
246 List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
247 int instructionSize = serviceInstructions.size();
248 BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
249 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
250 BigInteger metadataMask = MetaDataUtil.getWriteMetaDataMaskForDispatcherTable();
252 // build the final instruction for LPort Dispatcher table flow entry
253 List<Instruction> instructions = new ArrayList<>();
254 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, ++instructionSize));
255 if (serviceInstructions != null && !serviceInstructions.isEmpty()) {
256 for (Instruction info : serviceInstructions) {
257 // Skip meta data write as that is handled already
258 if (info.getInstruction() instanceof WriteMetadataCase) {
261 instructions.add(info);
265 // build the flow and install it
266 String flowRef = getFlowRef(dpId, NwConstants.LPORT_DISPATCHER_TABLE, interfaceName, boundService, currentServiceIndex);
267 Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
268 boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
269 installFlow(dpId, ingressFlow, t);
272 public static void installEgressDispatcherFlow(BigInteger dpId, BoundServices boundService, String interfaceName,
273 WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
274 LOG.debug("Installing Egress Dispatcher Flows {}, {}", dpId, interfaceName);
275 String serviceRef = boundService.getServiceName();
276 List<? extends MatchInfoBase> matches;
277 matches = FlowBasedServicesUtils.getMatchInfoForEgressDispatcherTable(interfaceTag, currentServiceIndex);
279 // Get the metadata and mask from the service's write metadata instruction
280 StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
281 List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
282 int instructionSize = serviceInstructions.size();
284 // build the final instruction for LPort Dispatcher table flow entry
285 List<Instruction> instructions = new ArrayList<Instruction>();
286 if(boundService.getServicePriority() != ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME, NwConstants.DEFAULT_EGRESS_SERVICE_INDEX)) {
287 BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
288 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
289 BigInteger metadataMask = MetaDataUtil.getWriteMetaDataMaskForDispatcherTable();
290 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, ++instructionSize));
291 instructions.add(MDSALUtil.buildAndGetSetReg6ActionInstruction(0, ++instructionSize, 0, 31,
292 MetaDataUtil.getReg6ValueForLPortDispatcher(interfaceTag, nextServiceIndex)));
294 if (serviceInstructions != null && !serviceInstructions.isEmpty()) {
295 for (Instruction info : serviceInstructions) {
296 // Skip meta data write as that is handled already
297 if (info.getInstruction() instanceof WriteMetadataCase) {
300 instructions.add(info);
304 // build the flow and install it
305 String flowRef = getFlowRef(dpId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, interfaceName, boundService, currentServiceIndex);
306 Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, flowRef,
307 boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
308 installFlow(dpId, ingressFlow, t);
312 public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
313 BigInteger cookie, List<Instruction> instructions) {
314 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority).setInstruction(instructions);
315 return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority))
316 .setServiceName(serviceName).setServicePriority(servicePriority)
317 .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
320 public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex) {
321 return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class,
322 new ServicesInfoKey(interfaceName, ServiceModeIngress.class))
323 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
326 public static void unbindDefaultEgressDispatcherService(DataBroker dataBroker, String interfaceName) {
327 IfmUtil.unbindService(dataBroker, interfaceName, buildServiceId(interfaceName,
328 ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME, NwConstants.DEFAULT_EGRESS_SERVICE_INDEX)),
329 ServiceModeEgress.class);
332 public static void bindDefaultEgressDispatcherService(DataBroker dataBroker, List<ListenableFuture<Void>> futures,
333 Interface interfaceInfo, String portNo,
334 String interfaceName, int ifIndex) {
335 WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
336 int priority = ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME, NwConstants.DEFAULT_EGRESS_SERVICE_INDEX);
337 List<Instruction> instructions = IfmUtil.getEgressInstructionsForInterface(interfaceInfo, portNo, null, true, ifIndex);
340 getBoundServices(String.format("%s.%s", "default", interfaceName),
341 ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME, NwConstants.DEFAULT_EGRESS_SERVICE_INDEX), priority,
342 NwConstants.EGRESS_DISPATCHER_TABLE_COOKIE, instructions);
343 IfmUtil.bindService(tx, interfaceName, serviceInfo, ServiceModeEgress.class);
344 futures.add(tx.submit());
347 public static void removeIngressFlow(String name, BoundServices serviceOld, BigInteger dpId, WriteTransaction t) {
348 LOG.debug("Removing Ingress Flows");
349 String flowKeyStr = getFlowRef(dpId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, name, serviceOld, serviceOld.getServicePriority());
350 FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
351 Node nodeDpn = buildInventoryDpnNode(dpId);
352 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
353 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
354 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
356 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
359 public static void removeLPortDispatcherFlow(BigInteger dpId, String iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
360 LOG.debug("Removing LPort Dispatcher Flows {}, {}", dpId, iface);
362 boundServicesOld.getAugmentation(StypeOpenflow.class);
363 // build the flow and install it
364 String flowRef = getFlowRef(dpId, NwConstants.LPORT_DISPATCHER_TABLE, iface, boundServicesOld, currentServiceIndex);
365 FlowKey flowKey = new FlowKey(new FlowId(flowRef));
366 Node nodeDpn = buildInventoryDpnNode(dpId);
367 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
368 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
369 .child(Table.class, new TableKey(NwConstants.LPORT_DISPATCHER_TABLE)).child(Flow.class, flowKey).build();
371 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
374 public static void removeEgressDispatcherFlow(BigInteger dpId, String iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
375 LOG.debug("Removing Egress Dispatcher Flows {}, {}", dpId, iface);
376 // build the flow and install it
377 String flowRef = getFlowRef(dpId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, iface, boundServicesOld, currentServiceIndex);
378 FlowKey flowKey = new FlowKey(new FlowId(flowRef));
379 Node nodeDpn = buildInventoryDpnNode(dpId);
380 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
381 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
382 .child(Table.class, new TableKey(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE)).child(Flow.class, flowKey).build();
384 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
387 private static String getFlowRef(BigInteger dpnId, short tableId, String iface, BoundServices service, short currentServiceIndex) {
388 return new StringBuffer().append(dpnId).append(tableId).append(NwConstants.FLOWID_SEPARATOR)
389 .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(currentServiceIndex).toString();
393 * This util method returns an array of ServiceInfo in which index 0 will
394 * have the immediate lower priority service and index 1 will have the
395 * immediate higher priority service among the list of existing serviceInfos
397 * @param serviceInfos
398 * @param currentServiceInfo
401 public static BoundServices[] getHighAndLowPriorityService(
402 List<BoundServices> serviceInfos, BoundServices currentServiceInfo) {
403 BoundServices higher = null; // this will be used to hold the immediate higher service priority with respect to the currentServiceInfo
404 BoundServices lower = null; // this will be used to hold the immediate lower service priority with respect to the currentServiceInfo
405 if (serviceInfos == null || serviceInfos.isEmpty()) {
406 return new BoundServices[]{lower, higher};
408 List <BoundServices> availableServiceInfos = new ArrayList<>(serviceInfos);
409 Collections.sort(availableServiceInfos, new Comparator<BoundServices>() {
411 public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
412 return serviceInfo1.getServicePriority().compareTo(serviceInfo2.getServicePriority());
415 for (BoundServices availableServiceInfo: availableServiceInfos) {
416 if (currentServiceInfo.getServicePriority() < availableServiceInfo.getServicePriority()) {
417 lower = availableServiceInfo;
420 higher = availableServiceInfo;
423 return new BoundServices[]{lower,higher};
426 public static BoundServices getHighestPriorityService(List<BoundServices> serviceInfos) {
427 List <BoundServices> availableServiceInfos = new ArrayList<>(serviceInfos);
428 if (availableServiceInfos.isEmpty()) {
431 BoundServices highPriorityService = availableServiceInfos.get(0);
432 availableServiceInfos.remove(0);
433 for (BoundServices availableServiceInfo: availableServiceInfos) {
434 if (availableServiceInfo.getServicePriority() < highPriorityService.getServicePriority()) {
435 highPriorityService = availableServiceInfo;
438 return highPriorityService;
441 public static void installLportIngressFlow(BigInteger dpId, long portNo, Interface iface,
442 List<ListenableFuture<Void>> futures, DataBroker dataBroker,
445 boolean isVlanTransparent = false;
446 WriteTransaction inventoryConfigShardTransaction = dataBroker.newWriteOnlyTransaction();
447 List<MatchInfo> matches = getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
448 IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
450 vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
451 isVlanTransparent = l2vlan.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
453 int instructionKey = 0;
454 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, (short) 0, BigInteger.ZERO, isExternal(iface));
455 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG);
456 List<Instruction> instructions = new ArrayList<>();
457 if (vlanId != 0 && !isVlanTransparent) {
458 instructions.add(MDSALUtil.buildAndGetPopVlanActionInstruction(lportTag, instructionKey++));
460 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, instructionKey++));
461 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.LPORT_DISPATCHER_TABLE, instructionKey++));
462 int priority = isVlanTransparent ? 1 : vlanId == 0 ? IfmConstants.FLOW_PRIORITY_FOR_UNTAGGED_VLAN : IfmConstants.FLOW_HIGH_PRIORITY;
463 String flowRef = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
464 Flow ingressFlow = MDSALUtil.buildFlowNew(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef, priority, flowRef, 0, 0,
465 NwConstants.VLAN_TABLE_COOKIE, matches, instructions);
466 installFlow(dpId, ingressFlow, inventoryConfigShardTransaction);
467 futures.add(inventoryConfigShardTransaction.submit());
470 public static String getFlowRef(short tableId, BigInteger dpnId, String infName) {
471 return String.format("%d:%s:%s", tableId, dpnId, infName);
474 public static void removeIngressFlow(String interfaceName, BigInteger dpId, DataBroker dataBroker,
475 List<ListenableFuture<Void>> futures) {
479 LOG.debug("Removing Ingress Flows for {}", interfaceName);
480 WriteTransaction t = dataBroker.newWriteOnlyTransaction();
481 String flowKeyStr = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, interfaceName);
482 FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
483 Node nodeDpn = buildInventoryDpnNode(dpId);
484 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
485 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
486 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
488 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
489 futures.add(t.submit());
492 private static boolean isExternal(Interface iface) {
496 IfExternal ifExternal = iface.getAugmentation(IfExternal.class);
497 return ifExternal != null && Boolean.TRUE.equals(ifExternal.isExternal());