import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.apache.commons.lang3.StringUtils;
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.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizon;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.BoundServicesStateList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.bound.services.state.list.BoundServicesState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.bound.services.state.list.BoundServicesStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.bound.services.state.list.BoundServicesStateKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
public class FlowBasedServicesUtils {
private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
+ private static final int DEFAULT_DISPATCHER_PRIORITY = 10;
public enum ServiceMode {
INGRESS, EGRESS
public static NodeConnectorId getNodeConnectorIdFromInterface(String interfaceName, DataBroker dataBroker) {
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
.ietf.interfaces.rev140508.interfaces.state.Interface ifState = InterfaceManagerCommonUtils
- .getInterfaceStateFromOperDS(interfaceName, dataBroker);
+ .getInterfaceState(interfaceName, dataBroker);
if (ifState != null) {
List<String> ofportIds = ifState.getLowerLayerIf();
return new NodeConnectorId(ofportIds.get(0));
matches.add(new MatchInPort(dpId, portNo));
int vlanId = 0;
IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
- if (l2vlan != null && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent) {
+ if (l2vlan != null) {
vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
}
- if (vlanId > 0) {
+ if (vlanId >= 0 && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent) {
matches.add(new MatchVlanVid(vlanId));
}
return matches;
}
String serviceRef = boundServiceNew.getServiceName();
- String flowRef = getFlowRef(dpId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, iface.getName(), boundServiceNew,
- boundServiceNew.getServicePriority());
+ String flowRef = getFlowRef(dpId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, iface.getName(),
+ boundServiceNew, boundServiceNew.getServicePriority());
StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef, stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
stypeOpenflow.getFlowCookie(), matches, instructionSet);
writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
}
- public static void removeFlow(String flowRef, BigInteger dpId, WriteTransaction writeTransaction) {
- LOG.debug("Removing Ingress Flows");
- FlowKey flowKey = new FlowKey(new FlowId(flowRef));
- 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();
-
- writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
- }
-
private static Node buildInventoryDpnNode(BigInteger dpnId) {
NodeId nodeId = new NodeId("openflow:" + dpnId);
Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, String interfaceName,
WriteTransaction writeTransaction, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
- LOG.debug("Installing LPort Dispatcher Flow {}, {}", dpId, interfaceName);
String serviceRef = boundService.getServiceName();
List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId, interfaceTag,
currentServiceIndex);
}
// build the flow and install it
- String flowRef = getFlowRef(dpId, NwConstants.LPORT_DISPATCHER_TABLE, interfaceName, boundService,
- currentServiceIndex);
+ String flowRef = getFlowRef(dpId, NwConstants.LPORT_DISPATCHER_TABLE, interfaceName,
+ boundService, currentServiceIndex);
Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
- boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches,
+ DEFAULT_DISPATCHER_PRIORITY, serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches,
instructions);
+ LOG.debug("Installing LPort Dispatcher Flow on DPN {}, for interface {}, with flowRef {}", dpId,
+ interfaceName, flowRef);
installFlow(dpId, ingressFlow, writeTransaction);
}
public static void installEgressDispatcherFlows(BigInteger dpId, BoundServices boundService, String interfaceName,
WriteTransaction writeTransaction, int interfaceTag, short currentServiceIndex, short nextServiceIndex,
Interface iface) {
- LOG.debug("Installing Egress Dispatcher Flows {}, {}", dpId, interfaceName);
+ LOG.debug("Installing Egress Dispatcher Flows on dpn : {}, for interface : {}", dpId, interfaceName);
installEgressDispatcherFlow(dpId, boundService, interfaceName, writeTransaction, interfaceTag,
currentServiceIndex, nextServiceIndex);
private static void installEgressDispatcherFlow(BigInteger dpId, BoundServices boundService, String interfaceName,
WriteTransaction writeTransaction, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
- String serviceRef = boundService.getServiceName();
- List<? extends MatchInfoBase> matches = FlowBasedServicesUtils
- .getMatchInfoForEgressDispatcherTable(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();
+ // Get the metadata and mask from the service's write metadata instruction
+ StypeOpenflow stypeOpenflow = boundService.getAugmentation(StypeOpenflow.class);
+ if (stypeOpenflow == null) {
+ LOG.warn("Could not install egress dispatcher flow, missing service openflow configuration");
+ return;
+ }
+ List<Instruction> serviceInstructions = stypeOpenflow.getInstruction() != null
+ ? stypeOpenflow.getInstruction()
+ : Collections.emptyList();
// build the final instruction for LPort Dispatcher table flow entry
+ List<Action> finalApplyActions = new ArrayList<>();
List<Instruction> instructions = new ArrayList<>();
if (boundService.getServicePriority() != ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
NwConstants.DEFAULT_EGRESS_SERVICE_INDEX)) {
BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
BigInteger metadataMask = MetaDataUtil.getWriteMetaDataMaskForEgressDispatcherTable();
instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadataValues[0], metadataMask,
- ++instructionSize));
- instructions.add(MDSALUtil.buildAndGetSetReg6ActionInstruction(0, ++instructionSize, 0, 31,
+ instructions.size()));
+ finalApplyActions.add(MDSALUtil.createSetReg6Action(finalApplyActions.size(), 0, 31,
MetaDataUtil.getReg6ValueForLPortDispatcher(interfaceTag, nextServiceIndex)));
}
- if (serviceInstructions != null && !serviceInstructions.isEmpty()) {
- for (Instruction info : serviceInstructions) {
+
+ final int applyActionsOffset = finalApplyActions.size();
+ for (Instruction info : serviceInstructions) {
+ if (info.getInstruction() instanceof WriteActionsCase) {
+ List<Action> writeActions = ActionConverterUtil.convertServiceActionToFlowAction(
+ ((WriteActionsCase) info.getInstruction()).getWriteActions().getAction());
+ instructions.add(MDSALUtil.buildWriteActionsInstruction(writeActions, instructions.size()));
+ } else if (info.getInstruction() instanceof ApplyActionsCase) {
+ List<Action> applyActions = ActionConverterUtil.convertServiceActionToFlowAction(
+ ((ApplyActionsCase) info.getInstruction()).getApplyActions().getAction(),
+ applyActionsOffset);
+ finalApplyActions.addAll(applyActions);
+ } else if (!(info.getInstruction() instanceof WriteMetadataCase)) {
// Skip meta data write as that is handled already
- if (info.getInstruction() instanceof WriteMetadataCase) {
- continue;
- } else if (info.getInstruction() instanceof WriteActionsCase) {
- info = MDSALUtil.buildWriteActionsInstruction(ActionConverterUtil.convertServiceActionToFlowAction(
- ((WriteActionsCase) info.getInstruction()).getWriteActions().getAction()));
- } else if (info.getInstruction() instanceof ApplyActionsCase) {
- info = MDSALUtil.buildApplyActionsInstruction(ActionConverterUtil.convertServiceActionToFlowAction(
- ((ApplyActionsCase) info.getInstruction()).getApplyActions().getAction()));
- }
- instructions.add(info);
+ instructions.add(MDSALUtil.buildInstruction(info, instructions.size()));
}
}
+ if (!finalApplyActions.isEmpty()) {
+ instructions.add(MDSALUtil.buildApplyActionsInstruction(finalApplyActions, instructions.size()));
+ }
// build the flow and install it
+ String serviceRef = boundService.getServiceName();
+ List<? extends MatchInfoBase> matches = FlowBasedServicesUtils
+ .getMatchInfoForEgressDispatcherTable(interfaceTag, currentServiceIndex);
String flowRef = getFlowRef(dpId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, interfaceName, boundService,
- currentServiceIndex);
+ currentServiceIndex);
Flow egressFlow = MDSALUtil.buildFlowNew(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, flowRef,
- boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches,
+ boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenflow.getFlowCookie(), matches,
instructions);
- LOG.debug("Installing Egress Dispatcher Flow {}, {}", flowRef, interfaceName);
+ LOG.debug("Installing Egress Dispatcher Flow for interface : {}, with flow-ref : {}", interfaceName, flowRef);
installFlow(dpId, egressFlow, writeTransaction);
}
}
public static void bindDefaultEgressDispatcherService(DataBroker dataBroker, List<ListenableFuture<Void>> futures,
- Interface interfaceInfo, String portNo, String interfaceName, int ifIndex) {
+ Interface interfaceInfo, String portNo,
+ String interfaceName, int ifIndex) {
+ List<Instruction> instructions =
+ IfmUtil.getEgressInstructionsForInterface(interfaceInfo, portNo, null, true, ifIndex, 0);
+ bindDefaultEgressDispatcherService(dataBroker, futures, interfaceName, instructions);
+ }
+
+ public static void bindDefaultEgressDispatcherService(DataBroker dataBroker, List<ListenableFuture<Void>> futures,
+ Interface interfaceInfo, String interfaceName, int ifIndex, long groupId) {
+ List<Instruction> instructions =
+ IfmUtil.getEgressInstructionsForInterface(interfaceInfo, StringUtils.EMPTY, null, true, ifIndex, groupId);
+ bindDefaultEgressDispatcherService(dataBroker, futures, interfaceName, instructions);
+ }
+
+ public static void bindDefaultEgressDispatcherService(DataBroker dataBroker, List<ListenableFuture<Void>> futures,
+ String interfaceName, List<Instruction> instructions) {
WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
int priority = ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
- NwConstants.DEFAULT_EGRESS_SERVICE_INDEX);
- List<Instruction> instructions = IfmUtil.getEgressInstructionsForInterface(interfaceInfo, portNo, null, true,
- ifIndex);
- BoundServices serviceInfo = getBoundServices(String.format("%s.%s", "default", interfaceName),
- ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
- NwConstants.DEFAULT_EGRESS_SERVICE_INDEX),
- priority, NwConstants.EGRESS_DISPATCHER_TABLE_COOKIE, instructions);
+ NwConstants.DEFAULT_EGRESS_SERVICE_INDEX);
+ BoundServices
+ serviceInfo =
+ getBoundServices(String.format("%s.%s", "default", interfaceName),
+ ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
+ NwConstants.DEFAULT_EGRESS_SERVICE_INDEX),
+ priority, NwConstants.EGRESS_DISPATCHER_TABLE_COOKIE, instructions);
IfmUtil.bindService(tx, interfaceName, serviceInfo, ServiceModeEgress.class);
futures.add(tx.submit());
}
boundServicesOld.getAugmentation(StypeOpenflow.class);
// build the flow and install it
String flowRef = getFlowRef(dpId, NwConstants.LPORT_DISPATCHER_TABLE, iface, boundServicesOld,
- currentServiceIndex);
+ currentServiceIndex);
FlowKey flowKey = new FlowKey(new FlowId(flowRef));
Node nodeDpn = buildInventoryDpnNode(dpId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
short currentServiceIndex, BoundServices boundServicesOld) {
// build the flow and install it
String flowRef = getFlowRef(dpId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, iface, boundServicesOld,
- currentServiceIndex);
+ currentServiceIndex);
FlowKey flowKey = new FlowKey(new FlowId(flowRef));
Node nodeDpn = buildInventoryDpnNode(dpId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
return String.format("%d:%s:%s", tableId, dpnId, infName);
}
- private static String getFlowRef(BigInteger dpnId, short tableId, String iface, BoundServices service,
- short currentServiceIndex) {
- return String.valueOf(dpnId) + tableId + NwConstants.FLOWID_SEPARATOR + iface + NwConstants.FLOWID_SEPARATOR
- + currentServiceIndex;
+ private static String getFlowRef(BigInteger dpnId, short tableId, String iface,BoundServices service,
+ short currentServiceIndex) {
+ return String.valueOf(dpnId) + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + iface
+ + NwConstants.FLOWID_SEPARATOR + currentServiceIndex;
}
private static String getSplitHorizonFlowRef(BigInteger dpnId, short tableId, String iface,
short currentServiceIndex, BigInteger shFlag) {
- return new StringBuffer().append(dpnId).append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(iface)
- .append(NwConstants.FLOWID_SEPARATOR).append(shFlag.toString()).toString();
+ return new StringBuffer().append(dpnId).append(NwConstants.FLOWID_SEPARATOR).append(tableId).append(NwConstants
+ .FLOWID_SEPARATOR).append(iface).append(NwConstants.FLOWID_SEPARATOR)
+ .append(shFlag.toString()).toString();
}
/**
futures.add(inventoryConfigShardTransaction.submit());
}
+ public static BoundServicesState buildBoundServicesState(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
+ interfaceState, Class<? extends ServiceModeBase> serviceMode) {
+ NodeConnectorId nodeConnectorId = IfmUtil.getNodeConnectorIdFromInterface(interfaceState);
+ BigInteger dpId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
+ long portNo = IfmUtil.getPortNumberFromNodeConnectorId(nodeConnectorId);
+ BoundServicesStateKey boundServicesStateKey = new BoundServicesStateKey(interfaceState.getName(), serviceMode);
+ return new BoundServicesStateBuilder().setDpid(dpId).setIfIndex(interfaceState.getIfIndex())
+ .setInterfaceName(interfaceState.getName()).setInterfaceType(interfaceState.getType()).setPortNo(portNo)
+ .setServiceMode(serviceMode).setKey(boundServicesStateKey).build();
+ }
+
+ public static BoundServicesState getBoundServicesState(DataBroker dataBroker,
+ String interfaceName,
+ Class<? extends ServiceModeBase>
+ serviceMode) {
+ InstanceIdentifier<BoundServicesState> id = InstanceIdentifier.builder(BoundServicesStateList.class)
+ .child(BoundServicesState.class, new BoundServicesStateKey(interfaceName, serviceMode)).build();
+ return IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, dataBroker).orNull();
+ }
+
+ public static void addBoundServicesState(List<ListenableFuture<Void>> futures,
+ DataBroker dataBroker, String interfaceName,
+ BoundServicesState interfaceBoundServicesState) {
+ LOG.info("adding bound-service state information for interface : {}, service-mode : {}",
+ interfaceBoundServicesState.getInterfaceName(), interfaceBoundServicesState.getServiceMode().getName());
+ InstanceIdentifier<BoundServicesState> id = InstanceIdentifier.builder(BoundServicesStateList.class)
+ .child(BoundServicesState.class, new BoundServicesStateKey(interfaceName,
+ interfaceBoundServicesState.getServiceMode())).build();
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+ writeTransaction.put(LogicalDatastoreType.OPERATIONAL, id, interfaceBoundServicesState, true);
+ futures.add(writeTransaction.submit());
+ }
+
+ public static void removeBoundServicesState(List<ListenableFuture<Void>> futures,
+ DataBroker dataBroker,
+ String interfaceName, Class<? extends ServiceModeBase> serviceMode) {
+ LOG.info("remove bound-service state information for interface : {}, service-mode : {}", interfaceName,
+ serviceMode.getName());
+ InstanceIdentifier<BoundServicesState> id = InstanceIdentifier.builder(BoundServicesStateList.class)
+ .child(BoundServicesState.class, new BoundServicesStateKey(interfaceName, serviceMode)).build();
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+ writeTransaction.delete(LogicalDatastoreType.OPERATIONAL, id);
+ futures.add(writeTransaction.submit());
+ }
+
private static boolean isExternal(Interface iface) {
if (iface == null) {
return false;