X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fopenflow%2Fmd%2Fcore%2Fsal%2Fconvertor%2FFlowConvertor.java;h=6837255dc90b7b8c64e0a0ed40c077fa054705e5;hb=958a836b772d6f8bec46279c767609aac023e720;hp=b0cbfb0a8d5482433a77a2871cfe212b4f1ca4cf;hpb=42ced541976153113d9fac7b1c9a7a2a97df711e;p=openflowplugin.git diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/FlowConvertor.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/FlowConvertor.java index b0cbfb0a8d..6837255dc9 100644 --- a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/FlowConvertor.java +++ b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/FlowConvertor.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2013 Ericsson. and others. All rights reserved. + * Copyright (c) 2013-2014 Ericsson. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -12,267 +12,563 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; +import org.opendaylight.openflowplugin.api.OFConstants; +import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flowflag.FlowFlagReactor; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor; import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.ActionList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.clear.actions._case.ClearActions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstructionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstructionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstructionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstructionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.Instructions; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.InstructionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ClearActionsCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.GotoTableCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.MeterCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteActionsCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice._goto.table._case.GotoTableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.meter._case.MeterBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.actions._case.WriteActionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.write.metadata._case.WriteMetadataBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MatchTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.Ordering; + /** * Utility class for converting a MD-SAL Flow into the OF flow mod */ public class FlowConvertor { - private static final Logger logger = LoggerFactory.getLogger(FlowConvertor.class); + private static final Logger LOG = LoggerFactory.getLogger(FlowConvertor.class); // Default values for when things are null - private static final BigInteger DEFAULT_COOKIE = BigInteger.ZERO; - private static final BigInteger DEFAULT_COOKIE_MASK = BigInteger.ZERO; - private static final TableId DEFAULT_TABLE_ID = new TableId(new Long(0)); - private static final Integer DEFAULT_IDLE_TIMEOUT = new Integer(5 * 60); - private static final Integer DEFAULT_HARD_TIMEOUT = new Integer(10 * 60); - private static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16); - private static final Long DEFAULT_BUFFER_ID = Long.parseLong("ffffffff", 16); + private static final TableId DEFAULT_TABLE_ID = new TableId(0L); + /** + * Default idle timeout + */ + public static final Integer DEFAULT_IDLE_TIMEOUT = 5 * 60; + /** + * Default hard timeout + */ + public static final Integer DEFAULT_HARD_TIMEOUT = 10 * 60; + /** + * Default priority + */ + public static final Integer DEFAULT_PRIORITY = Integer.parseInt("8000", 16); + private static final Long DEFAULT_BUFFER_ID = OFConstants.OFP_NO_BUFFER; private static final Long OFPP_ANY = Long.parseLong("ffffffff", 16); private static final Long DEFAULT_OUT_PORT = OFPP_ANY; private static final Long OFPG_ANY = Long.parseLong("ffffffff", 16); private static final Long DEFAULT_OUT_GROUP = OFPG_ANY; - /** flow flag: remove */ - public static final boolean DEFAULT_OFPFF_FLOW_REM = true; - /** flow flag: check overlap */ + /** + * flow flag: remove + */ + public static final boolean DEFAULT_OFPFF_FLOW_REM = false; + /** + * flow flag: check overlap + */ public static final boolean DEFAULT_OFPFF_CHECK_OVERLAP = false; - /** flow flag: reset counts */ + /** + * flow flag: reset counts + */ public static final boolean DEFAULT_OFPFF_RESET_COUNTS = false; - /** flow flag: don't keep track of packet counts */ + /** + * flow flag: don't keep track of packet counts + */ public static final boolean DEFAULT_OFPFF_NO_PKT_COUNTS = false; - /** flow flag: don't keep track of byte counts */ + /** + * flow flag: don't keep track of byte counts + */ public static final boolean DEFAULT_OFPFF_NO_BYT_COUNTS = false; - /** flow flag: emergency [OFP-1.0] */ + /** + * flow flag: emergency [OFP-1.0] + */ public static final boolean DEFAULT_OFPFF_EMERGENCY = false; - /** OxmMatch type */ + /** + * OxmMatch type + */ public static final Class DEFAULT_MATCH_TYPE = OxmMatchType.class; - /** default match entries - empty */ - public static final List DEFAULT_MATCH_ENTRIES = new ArrayList(); + /** + * default match entries - empty + */ + public static final List DEFAULT_MATCH_ENTRIES = new ArrayList(); + + + private FlowConvertor() { + //hiding implicit constructor + } + + /** + * This method converts the SAL Flow to OF Flow. + * It checks if there is a set-vlan-id (1.0) action made on OF1.3. + * If yes its handled separately + */ + public static List toFlowModInputs(Flow srcFlow, short version, BigInteger datapathId) { + List list = new ArrayList<>(); + + if (version >= OFConstants.OFP_VERSION_1_3 && isSetVlanIdActionCasePresent(srcFlow)) { + list.addAll(handleSetVlanIdForOF13(srcFlow, version, datapathId)); + } else { + list.add(toFlowModInput(srcFlow, version, datapathId)); + } + return list; + } + + public static FlowModInputBuilder toFlowModInput(Flow flow, short version, BigInteger datapathid) { - public static FlowModInput toFlowModInput(Flow flow, short version) { FlowModInputBuilder flowMod = new FlowModInputBuilder(); - if (flow.getCookie() != null) { - flowMod.setCookie(flow.getCookie()); + salToOFFlowCookie(flow, flowMod); + salToOFFlowCookieMask(flow, flowMod); + salToOFFlowTableId(flow, flowMod); + salToOFFlowCommand(flow, flowMod); + salToOFFlowIdleTimeout(flow, flowMod); + salToOFFlowHardTimeout(flow, flowMod); + salToOFFlowPriority(flow, flowMod); + salToOFFlowBufferId(flow, flowMod); + salToOFFlowOutPort(flow, flowMod); + salToOFFlowOutGroup(flow, flowMod); + + // convert and inject flowFlags + FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod, datapathid); + + // convert and inject match + MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod, datapathid); + + if (flow.getInstructions() != null) { + flowMod.setInstruction(toInstructions(flow, version, datapathid)); + flowMod.setAction(getActions(version, datapathid, flow)); + } + flowMod.setVersion(version); + + return flowMod; + } + + private static void salToOFFlowOutGroup(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getOutGroup() != null) { + flowMod.setOutGroup(flow.getOutGroup()); } else { - flowMod.setCookie(DEFAULT_COOKIE); + flowMod.setOutGroup(DEFAULT_OUT_GROUP); } + } - if (flow.getCookieMask() != null) { - flowMod.setCookieMask(new BigInteger(flow.getCookieMask().toString())); + private static void salToOFFlowOutPort(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getOutPort() != null) { + flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue())); } else { - flowMod.setCookieMask(DEFAULT_COOKIE_MASK); + flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT)); } + } - if (flow.getTableId() != null) { - flowMod.setTableId(new TableId(flow.getTableId().longValue())); + private static void salToOFFlowBufferId(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getBufferId() != null) { + flowMod.setBufferId(flow.getBufferId()); } else { - flowMod.setTableId(DEFAULT_TABLE_ID); + flowMod.setBufferId(DEFAULT_BUFFER_ID); } + } + private static void salToOFFlowPriority(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getPriority() != null) { + flowMod.setPriority(flow.getPriority()); + } else { + flowMod.setPriority(DEFAULT_PRIORITY); + } + } + + private static void salToOFFlowHardTimeout(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getHardTimeout() != null) { + flowMod.setHardTimeout(flow.getHardTimeout()); + } else { + flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT); + } + } + + private static void salToOFFlowIdleTimeout(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getIdleTimeout() != null) { + flowMod.setIdleTimeout(flow.getIdleTimeout()); + } else { + flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT); + } + } + + private static void salToOFFlowCommand(Flow flow, FlowModInputBuilder flowMod) { if (flow instanceof AddFlowInput) { flowMod.setCommand(FlowModCommand.OFPFCADD); } else if (flow instanceof RemoveFlowInput) { - if (flow.isStrict() != null && flow.isStrict()) { + if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) { flowMod.setCommand(FlowModCommand.OFPFCDELETESTRICT); } else { flowMod.setCommand(FlowModCommand.OFPFCDELETE); } } else if (flow instanceof UpdatedFlow) { - if (flow.isStrict() != null && flow.isStrict()) { + if (Objects.firstNonNull(flow.isStrict(), Boolean.FALSE)) { flowMod.setCommand(FlowModCommand.OFPFCMODIFYSTRICT); } else { flowMod.setCommand(FlowModCommand.OFPFCMODIFY); } } - if (flow.getIdleTimeout() != null) { - flowMod.setIdleTimeout(flow.getIdleTimeout()); - } else { - flowMod.setIdleTimeout(DEFAULT_IDLE_TIMEOUT); - } - if (flow.getHardTimeout() != null) { - flowMod.setHardTimeout(flow.getHardTimeout()); - } else { - flowMod.setHardTimeout(DEFAULT_HARD_TIMEOUT); - } - if (flow.getPriority() != null) { - flowMod.setPriority(flow.getPriority()); - } else { - flowMod.setPriority(DEFAULT_PRIORITY); - } - if (flow.getBufferId() != null) { - flowMod.setBufferId(flow.getBufferId()); - } else { - flowMod.setBufferId(DEFAULT_BUFFER_ID); - } + } - if (flow.getOutPort() != null) { - flowMod.setOutPort(new PortNumber(flow.getOutPort().longValue())); + private static void salToOFFlowTableId(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getTableId() != null) { + flowMod.setTableId(new TableId(flow.getTableId().longValue())); } else { - flowMod.setOutPort(new PortNumber(DEFAULT_OUT_PORT)); + flowMod.setTableId(DEFAULT_TABLE_ID); } - if (flow.getOutGroup() != null) { - flowMod.setOutGroup(flow.getOutGroup()); + } + + private static void salToOFFlowCookieMask(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getCookieMask() != null) { + flowMod.setCookieMask(flow.getCookieMask().getValue()); } else { - flowMod.setOutGroup(DEFAULT_OUT_GROUP); + flowMod.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK); } + } - - // convert and inject flowFlags - FlowFlagReactor.getInstance().convert(flow.getFlags(), version, flowMod); - - // convert and inject match - MatchReactor.getInstance().convert(flow.getMatch(), version, flowMod); - - if (flow.getInstructions() != null) { - flowMod.setInstructions(toInstructions(flow.getInstructions(), version)); - flowMod.setActionsList(getActionsList(flow.getInstructions(), version)); + private static void salToOFFlowCookie(Flow flow, FlowModInputBuilder flowMod) { + if (flow.getCookie() != null) { + flowMod.setCookie(flow.getCookie().getValue()); + } else { + flowMod.setCookie(OFConstants.DEFAULT_COOKIE); } - flowMod.setVersion(version); - - return flowMod.build(); } - private static List toInstructions( - org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions, - short version) { - List instructionsList = new ArrayList<>(); + private static List toInstructions( + Flow flow, + short version, BigInteger datapathid) { + List instructionsList = new ArrayList<>(); + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions(); for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions .getInstruction()) { - InstructionsBuilder instructionBuilder = new InstructionsBuilder(); + InstructionBuilder instructionBuilder = new InstructionBuilder(); org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction .getInstruction(); if (curInstruction instanceof GoToTableCase) { GoToTableCase goToTablecase = (GoToTableCase) curInstruction; GoToTable goToTable = goToTablecase.getGoToTable(); - instructionBuilder - .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable.class); - TableIdInstructionBuilder tableBuilder = new TableIdInstructionBuilder(); - tableBuilder.setTableId(goToTable.getTableId()); - instructionBuilder.addAugmentation(TableIdInstruction.class, tableBuilder.build()); + GotoTableCaseBuilder gotoTableCaseBuilder = new GotoTableCaseBuilder(); + GotoTableBuilder gotoTableBuilder = new GotoTableBuilder(); + gotoTableBuilder.setTableId(goToTable.getTableId()); + gotoTableCaseBuilder.setGotoTable(gotoTableBuilder.build()); + instructionBuilder.setInstructionChoice(gotoTableCaseBuilder.build()); instructionsList.add(instructionBuilder.build()); - } - - else if (curInstruction instanceof WriteMetadataCase) { + } else if (curInstruction instanceof WriteMetadataCase) { WriteMetadataCase writeMetadatacase = (WriteMetadataCase) curInstruction; WriteMetadata writeMetadata = writeMetadatacase.getWriteMetadata(); - instructionBuilder - .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata.class); - MetadataInstructionBuilder metadataBuilder = new MetadataInstructionBuilder(); - metadataBuilder.setMetadata(ByteUtil.convertBigIntegerTo64Bit(writeMetadata.getMetadata())); - metadataBuilder - .setMetadataMask(ByteUtil.convertBigIntegerTo64Bit(writeMetadata.getMetadataMask())); - instructionBuilder.addAugmentation(MetadataInstruction.class, metadataBuilder.build()); + + WriteMetadataCaseBuilder writeMetadataCaseBuilder = new WriteMetadataCaseBuilder(); + WriteMetadataBuilder writeMetadataBuilder = new WriteMetadataBuilder(); + writeMetadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadata(), + OFConstants.SIZE_OF_LONG_IN_BYTES)); + writeMetadataBuilder.setMetadataMask(ByteUtil.convertBigIntegerToNBytes(writeMetadata.getMetadataMask(), + OFConstants.SIZE_OF_LONG_IN_BYTES)); + writeMetadataCaseBuilder.setWriteMetadata(writeMetadataBuilder.build()); + instructionBuilder.setInstructionChoice(writeMetadataCaseBuilder.build()); instructionsList.add(instructionBuilder.build()); - } - - else if (curInstruction instanceof WriteActionsCase) { + } else if (curInstruction instanceof WriteActionsCase) { WriteActionsCase writeActionscase = (WriteActionsCase) curInstruction; WriteActions writeActions = writeActionscase.getWriteActions(); - instructionBuilder - .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions.class); - ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder(); - actionsInstructionBuilder.setActionsList(ActionConvertor.getActionList(writeActions.getAction(), - version)); - instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build()); + WriteActionsCaseBuilder writeActionsCaseBuilder = new WriteActionsCaseBuilder(); + WriteActionsBuilder writeActionsBuilder = new WriteActionsBuilder(); + writeActionsBuilder.setAction(ActionConvertor.getActions(writeActions.getAction(),version, datapathid, flow)); + writeActionsCaseBuilder.setWriteActions(writeActionsBuilder.build()); + instructionBuilder.setInstructionChoice(writeActionsCaseBuilder.build()); instructionsList.add(instructionBuilder.build()); - } - - else if (curInstruction instanceof ApplyActionsCase) { + } else if (curInstruction instanceof ApplyActionsCase) { ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction; ApplyActions applyActions = applyActionscase.getApplyActions(); - instructionBuilder - .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions.class); - ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder(); - actionsInstructionBuilder.setActionsList(ActionConvertor.getActionList(applyActions.getAction(), - version)); - instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build()); + org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder applyActionsCaseBuilder = + new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.ApplyActionsCaseBuilder(); + org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder applyActionsBuilder = + new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.apply.actions._case.ApplyActionsBuilder(); + applyActionsBuilder.setAction(ActionConvertor.getActions(applyActions.getAction(), version, datapathid, flow)); + applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build()); + instructionBuilder.setInstructionChoice(applyActionsCaseBuilder.build()); instructionsList.add(instructionBuilder.build()); - } - - else if (curInstruction instanceof ClearActionsCase) { - ClearActionsCase clearActionscase = (ClearActionsCase) curInstruction; - ClearActions clearActions = clearActionscase.getClearActions(); - instructionBuilder - .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions.class); - ActionsInstructionBuilder actionsInstructionBuilder = new ActionsInstructionBuilder(); - actionsInstructionBuilder.setActionsList(ActionConvertor.getActionList(clearActions.getAction(), - version)); - instructionBuilder.addAugmentation(ActionsInstruction.class, actionsInstructionBuilder.build()); + } else if (curInstruction instanceof ClearActionsCase) { + ClearActionsCaseBuilder clearActionsCaseBuilder = new ClearActionsCaseBuilder(); + instructionBuilder.setInstructionChoice(clearActionsCaseBuilder.build()); instructionsList.add(instructionBuilder.build()); - } - - else if (curInstruction instanceof MeterCase) { + } else if (curInstruction instanceof MeterCase) { MeterCase metercase = (MeterCase) curInstruction; Meter meter = metercase.getMeter(); - instructionBuilder - .setType(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter.class); - MeterIdInstructionBuilder meterBuilder = new MeterIdInstructionBuilder(); + MeterCaseBuilder meterCaseBuilder = new MeterCaseBuilder(); + MeterBuilder meterBuilder = new MeterBuilder(); Long meterId = meter.getMeterId().getValue(); meterBuilder.setMeterId(meterId); - instructionBuilder.addAugmentation(MeterIdInstruction.class, meterBuilder.build()); + meterCaseBuilder.setMeter(meterBuilder.build()); + instructionBuilder.setInstructionChoice(meterCaseBuilder.build()); instructionsList.add(instructionBuilder.build()); } } return instructionsList; } - - private static List getActionsList( - org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions, - short version) { - for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : instructions - .getInstruction()) { + private static List getActions(short version, BigInteger datapathid, Flow flow) { + + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions instructions = flow.getInstructions(); + List sortedInstructions = + Ordering.from(OrderComparator.build()) + .sortedCopy(instructions.getInstruction()); + + for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : sortedInstructions) { org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction .getInstruction(); if (curInstruction instanceof ApplyActionsCase) { ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction; ApplyActions applyActions = applyActionscase.getApplyActions(); - return ActionConvertor.getActionList(applyActions.getAction(), version); + return ActionConvertor.getActions(applyActions.getAction(), version, datapathid, flow); } - } return null; } -} \ No newline at end of file + + // check if set vlanid action is present in the flow + private static boolean isSetVlanIdActionCasePresent(Flow flow) { + boolean isPresent = false; + // we are trying to find if there is a set-vlan-id action (OF1.0) action present in the flow. + // If yes,then we would need to two flows + if (flow.getInstructions() != null) { + for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction instruction : + flow.getInstructions().getInstruction()) { + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = + instruction.getInstruction(); + + if (curInstruction instanceof ApplyActionsCase) { + ApplyActionsCase applyActionscase = (ApplyActionsCase) curInstruction; + ApplyActions applyActions = applyActionscase.getApplyActions(); + for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action action : + applyActions.getAction()) { + if (action.getAction() instanceof SetVlanIdActionCase) { + isPresent = true; + break; + } + } + } + } + } + return isPresent; + } + + + /** + * A) If user provided flow's match includes vlan match  and action has set_vlan_field + * Install following rules + *    1) match on (OFPVID_PRESENT |value) without mask + action [set_field] + *

+ * B) if user provided flow's match doesn't include vlan match but action has set_vlan field + *     1) Match on (OFPVID_NONE ) without mask + action [push vlan tag + set_field] + *     2) Match on (OFPVID_PRESENT) with mask (OFPVID_PRESENT ) + action [ set_field] + */ + private static List handleSetVlanIdForOF13(Flow srcFlow, short version, BigInteger datapathId) { + List list = new ArrayList<>(); + + VlanMatch srcVlanMatch = srcFlow.getMatch().getVlanMatch(); + boolean hasVlanMatch = (srcFlow.getMatch() != null && srcVlanMatch != null); + if (hasVlanMatch) { + //create flow with setfield and match + // match on vlan tag or vlanid with no mask + VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(srcVlanMatch); + VlanIdBuilder vlanIdBuilder = new VlanIdBuilder(); + vlanIdBuilder.setVlanIdPresent(srcVlanMatch.getVlanId().isVlanIdPresent()); + vlanIdBuilder.setVlanId(srcVlanMatch.getVlanId().getVlanId()); + vlanMatchBuilder.setVlanId(vlanIdBuilder.build()); + Match match = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder.build()).build(); + + Optional optional = injectMatchToFlow(srcFlow, match); + if (optional.isPresent()) { + list.add(toFlowModInput(optional.get(), version, datapathId)); + } + } else { + // create 2 flows + //flow 1 + // match on no vlan tag with no mask + VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder(); + VlanIdBuilder vlanIdBuilder = new VlanIdBuilder(); + vlanIdBuilder.setVlanIdPresent(false); + vlanIdBuilder.setVlanId(new VlanId(0)); + vlanMatchBuilder.setVlanId(vlanIdBuilder.build()); + Match match1 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder.build()).build(); + + Optional optional1 = injectMatchAndAction(srcFlow, match1); + if (optional1.isPresent()) { + list.add(toFlowModInput(optional1.get(), version, datapathId)); + } + + //flow2 + // match on vlan tag with mask + VlanMatchBuilder vlanMatchBuilder2 = new VlanMatchBuilder(); + VlanIdBuilder vlanIdBuilder2 = new VlanIdBuilder(); + vlanIdBuilder2.setVlanIdPresent(true); + vlanIdBuilder2.setVlanId(new VlanId(0)); + vlanMatchBuilder2.setVlanId(vlanIdBuilder2.build()); + Match match2 = new MatchBuilder(srcFlow.getMatch()).setVlanMatch(vlanMatchBuilder2.build()).build(); + Optional optional2 = injectMatchToFlow(srcFlow, match2); + if (optional2.isPresent()) { + list.add(toFlowModInput(optional2.get(), version, datapathId)); + } + } + return list; + } + + + private static Optional injectMatchToFlow(Flow sourceFlow, Match match) { + if (sourceFlow instanceof AddFlowInput) { + return Optional.of(new AddFlowInputBuilder(sourceFlow).setMatch(match).build()); + } else if (sourceFlow instanceof RemoveFlowInput) { + return Optional.of(new RemoveFlowInputBuilder(sourceFlow).setMatch(match).build()); + } else if (sourceFlow instanceof UpdatedFlow) { + return Optional.of(new UpdatedFlowBuilder(sourceFlow).setMatch(match).build()); + } else { + return Optional.absent(); + } + } + + private static Optional injectMatchAndAction(Flow sourceFlow, Match match) { + + Instructions instructions = (new InstructionsBuilder()) + .setInstruction(injectPushActionToInstruction(sourceFlow)) + .build(); + + if (sourceFlow instanceof AddFlowInput) { + return Optional.of(new AddFlowInputBuilder(sourceFlow) + .setMatch(match).setInstructions(instructions).build()); + } else if (sourceFlow instanceof RemoveFlowInput) { + return Optional.of(new RemoveFlowInputBuilder(sourceFlow) + .setMatch(match).setInstructions(instructions).build()); + } else if (sourceFlow instanceof UpdatedFlow) { + return Optional.of(new UpdatedFlowBuilder(sourceFlow) + .setMatch(match).setInstructions(instructions).build()); + } else { + return Optional.absent(); + } + } + + private static List + injectPushActionToInstruction(final Flow sourceFlow) { + + List srcInstructionList = + sourceFlow.getInstructions().getInstruction(); + + List targetInstructionList = new ArrayList<>(srcInstructionList.size()); + List targetActionList = new ArrayList<>(); + + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder instructionBuilder = + new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder(); + + for (int i = 0; i < srcInstructionList.size(); i++) { + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction srcInstruction = + srcInstructionList.get(i); + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curSrcInstruction = + srcInstruction.getInstruction(); + + if (curSrcInstruction instanceof ApplyActionsCase) { + ApplyActionsCase applyActionscase = (ApplyActionsCase) curSrcInstruction; + ApplyActions applyActions = applyActionscase.getApplyActions(); + List srcActionList = applyActions.getAction(); + + int offset = 0; + for (int j = 0; j < srcActionList.size(); j++) { + // check if its a set-vlan-action. If yes, then add the injected-action + + org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action actionItem = srcActionList.get(j); + if (actionItem.getAction() instanceof SetVlanIdActionCase) { + SetVlanIdActionCase setVlanIdActionCase = (SetVlanIdActionCase) actionItem.getAction(); + + PushVlanActionCaseBuilder pushVlanActionCaseBuilder = new PushVlanActionCaseBuilder(); + PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder(); + + pushVlanActionBuilder.setCfi(new VlanCfi(1)) + .setVlanId(setVlanIdActionCase.getSetVlanIdAction().getVlanId()) + .setEthernetType(sourceFlow.getMatch().getEthernetMatch() + .getEthernetType().getType().getValue().intValue()) + .setTag(sourceFlow.getMatch().getEthernetMatch() + .getEthernetType().getType().getValue().intValue()); + pushVlanActionCaseBuilder.setPushVlanAction(pushVlanActionBuilder.build()); + PushVlanActionCase injectedAction = pushVlanActionCaseBuilder.build(); + + org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = new ActionBuilder(); + actionBuilder.setAction(injectedAction) + .setKey(actionItem.getKey()) + .setOrder(actionItem.getOrder() + offset); + + targetActionList.add(actionBuilder.build()); + offset++; + } + + if (offset > 0) { + // we need to increment the order for all the actions added after injection + org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder actionBuilder = + new org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder(actionItem); + actionBuilder.setOrder(actionItem.getOrder() + offset); + actionItem = actionBuilder.build(); + } + + targetActionList.add(actionItem); + } + + ApplyActionsCaseBuilder applyActionsCaseBuilder = new ApplyActionsCaseBuilder(); + ApplyActionsBuilder applyActionsBuilder = new ApplyActionsBuilder(); + applyActionsBuilder.setAction(targetActionList); + applyActionsCaseBuilder.setApplyActions(applyActionsBuilder.build()); + + instructionBuilder.setInstruction(applyActionsCaseBuilder.build()); + } else { + instructionBuilder.setInstruction(curSrcInstruction); + } + + instructionBuilder + .setKey(srcInstruction.getKey()) + .setOrder(srcInstruction.getOrder()); + targetInstructionList.add(instructionBuilder.build()); + + } + + return targetInstructionList; + } + +}