*/
package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities;
-import com.google.common.base.Optional;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
-import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceBindings;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.common.base.Optional;
public class FlowBasedServicesUtils {
private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)}));
int vlanId = 0;
IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
- if(l2vlan != null && l2vlan.getVlanId() != null){
- vlanId = l2vlan.getVlanId().getValue();
+ if(l2vlan != null && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent){
+ vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
}
if (vlanId > 0) {
matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[]{vlanId}));
}
String serviceRef = boundServiceNew.getServiceName();
- String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew);
+ String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew, boundServiceNew.getServicePriority());
StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
}
public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, Interface iface,
- WriteTransaction t, int interfaceTag) {
+ WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
LOG.debug("Installing LPort Dispatcher Flows {}, {}", dpId, iface);
- short serviceIndex = boundService.getServicePriority();
String serviceRef = boundService.getServiceName();
List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId, iface,
- interfaceTag, serviceIndex);
+ interfaceTag, currentServiceIndex);
// Get the metadata and mask from the service's write metadata instruction
StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
int instructionSize = serviceInstructions.size();
BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
- BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, ++serviceIndex, metadataValues[0]);
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
}
// build the flow and install it
- String flowRef = getFlowRef(dpId, iface.getName(), boundService);
- Flow ingressFlow = MDSALUtil.buildFlowNew(stypeOpenFlow.getDispatcherTableId(), flowRef,
+ String flowRef = getFlowRef(dpId, iface.getName(), boundService, currentServiceIndex);
+ Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
installFlow(dpId, ingressFlow, t);
}
public static void removeIngressFlow(Interface iface, BoundServices serviceOld, BigInteger dpId, WriteTransaction t) {
LOG.debug("Removing Ingress Flows");
- String flowKeyStr = getFlowRef(dpId, iface.getName(), serviceOld);
+ String flowKeyStr = getFlowRef(dpId, iface.getName(), serviceOld, serviceOld.getServicePriority());
FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
Node nodeDpn = buildInventoryDpnNode(dpId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
}
- public static void removeLPortDispatcherFlow(BigInteger dpId, Interface iface, BoundServices boundServicesOld, WriteTransaction t) {
+ public static void removeLPortDispatcherFlow(BigInteger dpId, Interface iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
LOG.debug("Removing LPort Dispatcher Flows {}, {}", dpId, iface);
StypeOpenflow stypeOpenFlow = boundServicesOld.getAugmentation(StypeOpenflow.class);
// build the flow and install it
- String flowRef = getFlowRef(dpId, iface.getName(), boundServicesOld);
+ String flowRef = getFlowRef(dpId, iface.getName(), boundServicesOld, currentServiceIndex);
FlowKey flowKey = new FlowKey(new FlowId(flowRef));
Node nodeDpn = buildInventoryDpnNode(dpId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
}
- private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service) {
- return new StringBuffer().append(dpnId).append( NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
- .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(service.getServiceName()).append(NwConstants.FLOWID_SEPARATOR)
- .append(service.getServicePriority()).toString();
+ private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service, short currentServiceIndex) {
+ return new StringBuffer().append(dpnId).append(NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
+ .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(currentServiceIndex).toString();
+ }
+
+ /**
+ * This util method returns an array of ServiceInfo in which index 0 will
+ * have the immediate lower priority service and index 1 will have the
+ * immediate higher priority service among the list of existing serviceInfos
+ *
+ * @param serviceInfos
+ * @param currentServiceInfo
+ * @return
+ */
+ public static BoundServices[] getHighAndLowPriorityService(
+ List<BoundServices> serviceInfos, BoundServices currentServiceInfo) {
+ BoundServices higher = null; // this will be used to hold the immediate higher service priority with respect to the currentServiceInfo
+ BoundServices lower = null; // this will be used to hold the immediate lower service priority with respect to the currentServiceInfo
+ if (serviceInfos == null || serviceInfos.isEmpty()) {
+ return new BoundServices[]{lower, higher};
+ }
+ List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+ Collections.sort(availableServiceInfos, new Comparator<BoundServices>() {
+ @Override
+ public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+ return serviceInfo2.getServicePriority().compareTo(serviceInfo1.getServicePriority());
+ }
+ });
+ for (BoundServices availableServiceInfo: availableServiceInfos) {
+ if (currentServiceInfo.getServicePriority() > availableServiceInfo.getServicePriority()) {
+ lower = availableServiceInfo;
+ break;
+ } else {
+ higher = availableServiceInfo;
+ }
+ }
+ return new BoundServices[]{lower,higher};
+ }
+
+ public static BoundServices getHighestPriorityService(List<BoundServices> serviceInfos) {
+ List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+ if (availableServiceInfos.isEmpty()) {
+ return null;
+ }
+ BoundServices highPriorityService = availableServiceInfos.get(0);
+ availableServiceInfos.remove(0);
+ for (BoundServices availableServiceInfo: availableServiceInfos) {
+ if (availableServiceInfo.getServicePriority() > highPriorityService.getServicePriority()) {
+ highPriorityService = availableServiceInfo;
+ }
+ }
+ return highPriorityService;
}
-}
\ No newline at end of file
+
+ public static void installVlanFlow(BigInteger dpId, long portNo, Interface iface,
+ WriteTransaction t, List<MatchInfo> matches, int lportTag) {
+ int vlanId = 0;
+ boolean isVlanTransparent = false;
+ IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
+ if(l2vlan != null){
+ vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
+ isVlanTransparent = l2vlan.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
+ }
+ int instructionKey = 0;
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, (short) 0);
+ BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher();
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ if (vlanId != 0 && !isVlanTransparent) {
+ instructions.add(MDSALUtil.buildAndGetPopVlanActionInstruction(lportTag, instructionKey++));
+ }
+ instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, instructionKey++));
+ instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.DHCP_TABLE, instructionKey++));
+ int priority = isVlanTransparent ? 1 : vlanId == 0 ? IfmConstants.FLOW_PRIORITY_FOR_UNTAGGED_VLAN : IfmConstants.FLOW_HIGH_PRIORITY;
+ String flowRef = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
+ Flow ingressFlow = MDSALUtil.buildFlowNew(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef, priority, flowRef, 0, 0,
+ IfmConstants.VLAN_TABLE_COOKIE, matches, instructions);
+ installFlow(dpId, ingressFlow, t);
+}
+
+ public static String getFlowRef(short tableId, BigInteger dpnId, String infName) {
+ return String.format("%d:%s:%s", tableId, dpnId, infName);
+ }
+
+ public static void removeIngressFlow(Interface iface, BigInteger dpId, WriteTransaction t) {
+ LOG.debug("Removing Ingress Flows");
+ String flowKeyStr = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
+ FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
+ Node nodeDpn = buildInventoryDpnNode(dpId);
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
+
+ t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ }
+
+
+}