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.*;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.*;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 public class FlowBasedServicesUtils {
53 private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
55 public enum ServiceMode {
60 public static final ImmutableBiMap SERVICE_MODE_MAP =
61 new ImmutableBiMap.Builder<ServiceMode, Class<? extends ServiceModeBase>>()
62 .put(ServiceMode.EGRESS, ServiceModeEgress.class)
63 .put(ServiceMode.INGRESS, ServiceModeIngress.class)
66 public static ServicesInfo getServicesInfoForInterface(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
67 DataBroker dataBroker) {
68 ServicesInfoKey servicesInfoKey = new ServicesInfoKey(interfaceName,serviceMode);
69 InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
70 InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
71 Optional<ServicesInfo> servicesInfoOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION,
72 servicesInfoIdentifierBuilder.build(), dataBroker);
74 if (servicesInfoOptional.isPresent()) {
75 return servicesInfoOptional.get();
81 public static NodeConnectorId getNodeConnectorIdFromInterface(String interfaceName, DataBroker dataBroker) {
82 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
83 InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
85 List<String> ofportIds = ifState.getLowerLayerIf();
86 return new NodeConnectorId(ofportIds.get(0));
91 public static NodeConnectorId getNodeConnectorIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
93 List<String> ofportIds = ifState.getLowerLayerIf();
94 return new NodeConnectorId(ofportIds.get(0));
99 public static BigInteger getDpnIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
100 NodeConnectorId nodeConnectorId = null;
101 if(ifState != null) {
102 List<String> ofportIds = ifState.getLowerLayerIf();
103 nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
105 return new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
108 public static List<MatchInfo> getMatchInfoForVlanPortAtIngressTable(BigInteger dpId, long portNo, Interface iface) {
109 List<MatchInfo> matches = new ArrayList<>();
110 matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)}));
112 IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
113 if(l2vlan != null && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent){
114 vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
117 matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[]{vlanId}));
122 public static List<MatchInfo> getMatchInfoForTunnelPortAtIngressTable(BigInteger dpId, long portNo) {
123 List<MatchInfo> matches = new ArrayList<>();
124 matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[]{dpId, BigInteger.valueOf(portNo)}));
128 public static List<MatchInfo> getMatchInfoForDispatcherTable(BigInteger dpId,
129 int interfaceTag, short servicePriority) {
130 List<MatchInfo> matches = new ArrayList<>();
131 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
132 MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, servicePriority),
133 MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
137 public static List<NxMatchInfo> getMatchInfoForEgressDispatcherTable(int interfaceTag, short serviceIndex) {
138 List<NxMatchInfo> matches = new ArrayList<>();
139 matches.add(new NxMatchInfo(NxMatchFieldType.nxm_reg_6, new long[] {
140 MetaDataUtil.getReg6ValueForLPortDispatcher(interfaceTag, serviceIndex)}));
144 public static void installInterfaceIngressFlow(BigInteger dpId, Interface iface,
145 BoundServices boundServiceNew,
147 List<MatchInfo> matches, int lportTag, short tableId) {
148 List<Instruction> instructions = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction();
150 int serviceInstructionsSize = instructions.size();
151 List<Instruction> instructionSet = new ArrayList<>();
153 IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
154 if(l2vlan != null && l2vlan.getVlanId() != null){
155 vlanId = l2vlan.getVlanId().getValue();
158 // incrementing instructionSize and using it as actionKey. Because it won't clash with any other instructions
159 int actionKey = ++serviceInstructionsSize;
160 instructionSet.add(MDSALUtil.buildAndGetPopVlanActionInstruction(actionKey, ++serviceInstructionsSize));
163 if (lportTag != 0L) {
164 BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
165 short sIndex = boundServiceNew.getServicePriority();
166 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
167 ++sIndex, metadataValues[0], isExternal(iface));
168 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(
169 MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
170 MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG, metadataValues[1]);
171 instructionSet.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask,
172 ++serviceInstructionsSize));
175 if (instructions != null && !instructions.isEmpty()) {
176 for (Instruction info : instructions) {
177 // Skip meta data write as that is handled already
178 if (info.getInstruction() instanceof WriteMetadataCase) {
181 instructionSet.add(info);
185 String serviceRef = boundServiceNew.getServiceName();
186 String flowRef = getFlowRef(dpId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, iface.getName(),
187 boundServiceNew, boundServiceNew.getServicePriority());
188 StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
189 Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
190 stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
191 stypeOpenflow.getFlowCookie(), matches, instructionSet);
192 installFlow(dpId, ingressFlow, t);
195 public static void installFlow(BigInteger dpId, Flow flow, WriteTransaction t) {
196 FlowKey flowKey = new FlowKey(new FlowId(flow.getId()));
197 Node nodeDpn = buildInventoryDpnNode(dpId);
198 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
199 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
200 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class,flowKey).build();
202 t.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
205 public static void removeFlow(String flowRef, BigInteger dpId, WriteTransaction t) {
206 LOG.debug("Removing Ingress Flows");
207 FlowKey flowKey = new FlowKey(new FlowId(flowRef));
208 Node nodeDpn = buildInventoryDpnNode(dpId);
209 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
210 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
211 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
213 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
216 private static Node buildInventoryDpnNode(BigInteger dpnId) {
217 NodeId nodeId = new NodeId("openflow:" + dpnId);
218 Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
223 public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, String interfaceName,
224 WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
225 LOG.debug("Installing LPort Dispatcher Flow {}, {}", dpId, interfaceName);
226 String serviceRef = boundService.getServiceName();
227 List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId,
228 interfaceTag, currentServiceIndex);
230 // Get the metadata and mask from the service's write metadata instruction
231 StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
232 List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
233 int instructionSize = serviceInstructions.size();
234 BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
235 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
236 BigInteger metadataMask = MetaDataUtil.getWriteMetaDataMaskForDispatcherTable();
238 // build the final instruction for LPort Dispatcher table flow entry
239 List<Instruction> instructions = new ArrayList<>();
240 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, ++instructionSize));
241 if (serviceInstructions != null && !serviceInstructions.isEmpty()) {
242 for (Instruction info : serviceInstructions) {
243 // Skip meta data write as that is handled already
244 if (info.getInstruction() instanceof WriteMetadataCase) {
247 instructions.add(info);
251 // build the flow and install it
252 String flowRef = getFlowRef(dpId, NwConstants.LPORT_DISPATCHER_TABLE, interfaceName, boundService, currentServiceIndex);
253 Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
254 boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
255 installFlow(dpId, ingressFlow, t);
258 public static void installEgressDispatcherFlow(BigInteger dpId, BoundServices boundService, String interfaceName,
259 WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
260 LOG.debug("Installing Egress Dispatcher Flows {}, {}", dpId, interfaceName);
261 String serviceRef = boundService.getServiceName();
262 List<? extends MatchInfoBase> matches;
263 matches = FlowBasedServicesUtils.getMatchInfoForEgressDispatcherTable(interfaceTag, currentServiceIndex);
265 // Get the metadata and mask from the service's write metadata instruction
266 StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
267 List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
268 int instructionSize = serviceInstructions.size();
270 // build the final instruction for LPort Dispatcher table flow entry
271 List<Instruction> instructions = new ArrayList<Instruction>();
272 if(boundService.getServicePriority() != NwConstants.DEFAULT_EGRESS_SERVICE_INDEX) {
273 BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
274 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
275 BigInteger metadataMask = MetaDataUtil.getWriteMetaDataMaskForDispatcherTable();
276 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, ++instructionSize));
277 instructions.add(MDSALUtil.buildAndGetSetReg6ActionInstruction(0, ++instructionSize, 0, 31,
278 MetaDataUtil.getReg6ValueForLPortDispatcher(interfaceTag, nextServiceIndex)));
280 if (serviceInstructions != null && !serviceInstructions.isEmpty()) {
281 for (Instruction info : serviceInstructions) {
282 // Skip meta data write as that is handled already
283 if (info.getInstruction() instanceof WriteMetadataCase) {
286 instructions.add(info);
290 // build the flow and install it
291 String flowRef = getFlowRef(dpId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, interfaceName, boundService, currentServiceIndex);
292 Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, flowRef,
293 boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
294 installFlow(dpId, ingressFlow, t);
298 public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
299 BigInteger cookie, List<Instruction> instructions) {
300 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority).setInstruction(instructions);
301 return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority))
302 .setServiceName(serviceName).setServicePriority(servicePriority)
303 .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
306 public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex) {
307 return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class,
308 new ServicesInfoKey(interfaceName, ServiceModeIngress.class))
309 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
312 public static void unbindDefaultEgressDispatcherService(DataBroker dataBroker, String interfaceName) {
313 IfmUtil.unbindService(dataBroker, interfaceName, buildServiceId(interfaceName, NwConstants.DEFAULT_EGRESS_SERVICE_INDEX),
314 ServiceModeEgress.class);
317 public static void bindDefaultEgressDispatcherService(Interface interfaceInfo, String portNo, String interfaceName,
318 WriteTransaction tx, int ifIndex) {
319 int priority = NwConstants.DEFAULT_EGRESS_SERVICE_INDEX;
320 List<Instruction> instructions = IfmUtil.getEgressInstructionsForInterface(interfaceInfo, portNo, null, true, ifIndex);
323 getBoundServices(String.format("%s.%s", "default", interfaceName),
324 NwConstants.DEFAULT_EGRESS_SERVICE_INDEX, priority,
325 NwConstants.EGRESS_DISPATCHER_TABLE_COOKIE, instructions);
326 IfmUtil.bindService(tx, interfaceName, serviceInfo, ServiceModeEgress.class);
329 public static void removeIngressFlow(String name, BoundServices serviceOld, BigInteger dpId, WriteTransaction t) {
330 LOG.debug("Removing Ingress Flows");
331 String flowKeyStr = getFlowRef(dpId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, name, serviceOld, serviceOld.getServicePriority());
332 FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
333 Node nodeDpn = buildInventoryDpnNode(dpId);
334 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
335 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
336 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
338 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
341 public static void removeLPortDispatcherFlow(BigInteger dpId, String iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
342 LOG.debug("Removing LPort Dispatcher Flows {}, {}", dpId, iface);
344 boundServicesOld.getAugmentation(StypeOpenflow.class);
345 // build the flow and install it
346 String flowRef = getFlowRef(dpId, NwConstants.LPORT_DISPATCHER_TABLE, iface, boundServicesOld, currentServiceIndex);
347 FlowKey flowKey = new FlowKey(new FlowId(flowRef));
348 Node nodeDpn = buildInventoryDpnNode(dpId);
349 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
350 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
351 .child(Table.class, new TableKey(NwConstants.LPORT_DISPATCHER_TABLE)).child(Flow.class, flowKey).build();
353 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
356 public static void removeEgressDispatcherFlow(BigInteger dpId, String iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
357 LOG.debug("Removing Egress Dispatcher Flows {}, {}", dpId, iface);
358 // build the flow and install it
359 String flowRef = getFlowRef(dpId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, iface, boundServicesOld, currentServiceIndex);
360 FlowKey flowKey = new FlowKey(new FlowId(flowRef));
361 Node nodeDpn = buildInventoryDpnNode(dpId);
362 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
363 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
364 .child(Table.class, new TableKey(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE)).child(Flow.class, flowKey).build();
366 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
369 private static String getFlowRef(BigInteger dpnId, short tableId, String iface, BoundServices service, short currentServiceIndex) {
370 return new StringBuffer().append(dpnId).append(tableId).append(NwConstants.FLOWID_SEPARATOR)
371 .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(currentServiceIndex).toString();
375 * This util method returns an array of ServiceInfo in which index 0 will
376 * have the immediate lower priority service and index 1 will have the
377 * immediate higher priority service among the list of existing serviceInfos
379 * @param serviceInfos
380 * @param currentServiceInfo
383 public static BoundServices[] getHighAndLowPriorityService(
384 List<BoundServices> serviceInfos, BoundServices currentServiceInfo) {
385 BoundServices higher = null; // this will be used to hold the immediate higher service priority with respect to the currentServiceInfo
386 BoundServices lower = null; // this will be used to hold the immediate lower service priority with respect to the currentServiceInfo
387 if (serviceInfos == null || serviceInfos.isEmpty()) {
388 return new BoundServices[]{lower, higher};
390 List <BoundServices> availableServiceInfos = new ArrayList<>(serviceInfos);
391 Collections.sort(availableServiceInfos, new Comparator<BoundServices>() {
393 public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
394 return serviceInfo1.getServicePriority().compareTo(serviceInfo2.getServicePriority());
397 for (BoundServices availableServiceInfo: availableServiceInfos) {
398 if (currentServiceInfo.getServicePriority() < availableServiceInfo.getServicePriority()) {
399 lower = availableServiceInfo;
402 higher = availableServiceInfo;
405 return new BoundServices[]{lower,higher};
408 public static BoundServices getHighestPriorityService(List<BoundServices> serviceInfos) {
409 List <BoundServices> availableServiceInfos = new ArrayList<>(serviceInfos);
410 if (availableServiceInfos.isEmpty()) {
413 BoundServices highPriorityService = availableServiceInfos.get(0);
414 availableServiceInfos.remove(0);
415 for (BoundServices availableServiceInfo: availableServiceInfos) {
416 if (availableServiceInfo.getServicePriority() < highPriorityService.getServicePriority()) {
417 highPriorityService = availableServiceInfo;
420 return highPriorityService;
423 public static void installVlanFlow(BigInteger dpId, long portNo, Interface iface,
424 WriteTransaction t, List<MatchInfo> matches, int lportTag) {
426 boolean isVlanTransparent = false;
427 IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
429 vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
430 isVlanTransparent = l2vlan.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
432 int instructionKey = 0;
433 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, (short) 0, BigInteger.ZERO, isExternal(iface));
434 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG);
435 List<Instruction> instructions = new ArrayList<>();
436 if (vlanId != 0 && !isVlanTransparent) {
437 instructions.add(MDSALUtil.buildAndGetPopVlanActionInstruction(lportTag, instructionKey++));
439 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, instructionKey++));
440 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.LPORT_DISPATCHER_TABLE, instructionKey++));
441 int priority = isVlanTransparent ? 1 : vlanId == 0 ? IfmConstants.FLOW_PRIORITY_FOR_UNTAGGED_VLAN : IfmConstants.FLOW_HIGH_PRIORITY;
442 String flowRef = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
443 Flow ingressFlow = MDSALUtil.buildFlowNew(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef, priority, flowRef, 0, 0,
444 NwConstants.VLAN_TABLE_COOKIE, matches, instructions);
445 installFlow(dpId, ingressFlow, t);
448 public static String getFlowRef(short tableId, BigInteger dpnId, String infName) {
449 return String.format("%d:%s:%s", tableId, dpnId, infName);
452 public static void removeIngressFlow(String interfaceName, BigInteger dpId, WriteTransaction t) {
456 LOG.debug("Removing Ingress Flows for {}", interfaceName);
457 String flowKeyStr = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, interfaceName);
458 FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
459 Node nodeDpn = buildInventoryDpnNode(dpId);
460 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
461 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
462 .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
464 t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
467 private static boolean isExternal(Interface iface) {
471 IfExternal ifExternal = iface.getAugmentation(IfExternal.class);
472 return ifExternal != null && Boolean.TRUE.equals(ifExternal.isExternal());