import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import java.math.BigInteger;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
import org.opendaylight.l2switch.util.InstanceIdentifierUtils;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicLong;
-
/**
- * Implementation of FlowWriterService{@link org.opendaylight.l2switch.flow.FlowWriterService},
- * that builds required flow and writes to configuration data store using provided DataBrokerService
+ * Implementation of
+ * FlowWriterService{@link org.opendaylight.l2switch.flow.FlowWriterService},
+ * that builds required flow and writes to configuration data store using
+ * provided DataBrokerService
* {@link org.opendaylight.controller.sal.binding.api.data.DataBrokerService}
*/
public class FlowWriterServiceImpl implements FlowWriterService {
- private static final Logger _logger = LoggerFactory.getLogger(FlowWriterServiceImpl.class);
- private SalFlowService salFlowService;
- private short flowTableId;
- private int flowPriority;
- private int flowIdleTimeout;
- private int flowHardTimeout;
-
- private AtomicLong flowIdInc = new AtomicLong();
- private AtomicLong flowCookieInc = new AtomicLong(0x2a00000000000000L);
- private final Integer DEFAULT_TABLE_ID = 0;
- private final Integer DEFAULT_PRIORITY = 10;
- private final Integer DEFAULT_HARD_TIMEOUT = 3600;
- private final Integer DEFAULT_IDLE_TIMEOUT = 1800;
-
- public FlowWriterServiceImpl(SalFlowService salFlowService) {
- Preconditions.checkNotNull(salFlowService, "salFlowService should not be null.");
- this.salFlowService = salFlowService;
- }
-
- public void setFlowTableId(short flowTableId) {
- this.flowTableId = flowTableId;
- }
-
- public void setFlowPriority(int flowPriority) {
- this.flowPriority = flowPriority;
- }
-
- public void setFlowIdleTimeout(int flowIdleTimeout) {
- this.flowIdleTimeout = flowIdleTimeout;
- }
-
- public void setFlowHardTimeout(int flowHardTimeout) {
- this.flowHardTimeout = flowHardTimeout;
- }
-
- /**
- * Writes a flow that forwards packets to destPort if destination mac in packet is destMac and
- * source Mac in packet is sourceMac. If sourceMac is null then flow would not set any source mac,
- * resulting in all packets with destMac being forwarded to destPort.
- *
- * @param sourceMac
- * @param destMac
- * @param destNodeConnectorRef
- */
- @Override
- public void addMacToMacFlow(MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destNodeConnectorRef) {
-
- Preconditions.checkNotNull(destMac, "Destination mac address should not be null.");
- Preconditions.checkNotNull(destNodeConnectorRef, "Destination port should not be null.");
-
-
- // do not add flow if both macs are same.
- if(sourceMac != null && destMac.equals(sourceMac)) {
- _logger.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
- return;
+ private static final Logger LOG = LoggerFactory.getLogger(FlowWriterServiceImpl.class);
+ private SalFlowService salFlowService;
+ private short flowTableId;
+ private int flowPriority;
+ private int flowIdleTimeout;
+ private int flowHardTimeout;
+
+ private AtomicLong flowIdInc = new AtomicLong();
+ private AtomicLong flowCookieInc = new AtomicLong(0x2a00000000000000L);
+ private final Integer DEFAULT_TABLE_ID = 0;
+ private final Integer DEFAULT_PRIORITY = 10;
+ private final Integer DEFAULT_HARD_TIMEOUT = 3600;
+ private final Integer DEFAULT_IDLE_TIMEOUT = 1800;
+
+ public FlowWriterServiceImpl(SalFlowService salFlowService) {
+ Preconditions.checkNotNull(salFlowService, "salFlowService should not be null.");
+ this.salFlowService = salFlowService;
+ }
+
+ public void setFlowTableId(short flowTableId) {
+ this.flowTableId = flowTableId;
+ }
+
+ public void setFlowPriority(int flowPriority) {
+ this.flowPriority = flowPriority;
}
- // get flow table key
- TableKey flowTableKey = new TableKey((short) flowTableId);
-
- //build a flow path based on node connector to program flow
- InstanceIdentifier<Flow> flowPath = buildFlowPath(destNodeConnectorRef, flowTableKey);
-
- // build a flow that target given mac id
- Flow flowBody = createMacToMacFlow(flowTableKey.getId(), flowPriority, sourceMac, destMac, destNodeConnectorRef);
-
- // commit the flow in config data
- writeFlowToConfigData(flowPath, flowBody);
- }
-
- /**
- * Writes mac-to-mac flow on all ports that are in the path between given source and destination ports.
- * It uses path provided by org.opendaylight.l2switch.loopremover.topology.NetworkGraphService
- * to find a links
- * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
- * between given ports. And then writes appropriate flow on each port that is covered in that path.
- *
- * @param sourceMac
- * @param sourceNodeConnectorRef
- * @param destMac
- * @param destNodeConnectorRef
- */
- @Override
- public void addBidirectionalMacToMacFlows(MacAddress sourceMac,
- NodeConnectorRef sourceNodeConnectorRef,
- MacAddress destMac,
- NodeConnectorRef destNodeConnectorRef) {
- Preconditions.checkNotNull(sourceMac, "Source mac address should not be null.");
- Preconditions.checkNotNull(sourceNodeConnectorRef, "Source port should not be null.");
- Preconditions.checkNotNull(destMac, "Destination mac address should not be null.");
- Preconditions.checkNotNull(destNodeConnectorRef, "Destination port should not be null.");
-
- if(sourceNodeConnectorRef.equals(destNodeConnectorRef)) {
- _logger.info("In addMacToMacFlowsUsingShortestPath: No flows added. Source and Destination ports are same.");
- return;
+ public void setFlowIdleTimeout(int flowIdleTimeout) {
+ this.flowIdleTimeout = flowIdleTimeout;
+ }
+
+ public void setFlowHardTimeout(int flowHardTimeout) {
+ this.flowHardTimeout = flowHardTimeout;
+ }
+
+ /**
+ * Writes a flow that forwards packets to destPort if destination mac in
+ * packet is destMac and source Mac in packet is sourceMac. If sourceMac is
+ * null then flow would not set any source mac, resulting in all packets
+ * with destMac being forwarded to destPort.
+ *
+ * @param sourceMac
+ * @param destMac
+ * @param destNodeConnectorRef
+ */
+ @Override
+ public void addMacToMacFlow(MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destNodeConnectorRef) {
+
+ Preconditions.checkNotNull(destMac, "Destination mac address should not be null.");
+ Preconditions.checkNotNull(destNodeConnectorRef, "Destination port should not be null.");
+
+ // do not add flow if both macs are same.
+ if (sourceMac != null && destMac.equals(sourceMac)) {
+ LOG.info("In addMacToMacFlow: No flows added. Source and Destination mac are same.");
+ return;
+ }
+
+ // get flow table key
+ TableKey flowTableKey = new TableKey((short) flowTableId);
+
+ // build a flow path based on node connector to program flow
+ InstanceIdentifier<Flow> flowPath = buildFlowPath(destNodeConnectorRef, flowTableKey);
+
+ // build a flow that target given mac id
+ Flow flowBody = createMacToMacFlow(flowTableKey.getId(), flowPriority, sourceMac, destMac,
+ destNodeConnectorRef);
+
+ // commit the flow in config data
+ writeFlowToConfigData(flowPath, flowBody);
+ }
+
+ /**
+ * Writes mac-to-mac flow on all ports that are in the path between given
+ * source and destination ports. It uses path provided by
+ * org.opendaylight.l2switch.loopremover.topology.NetworkGraphService to
+ * find a links
+ * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
+ * between given ports. And then writes appropriate flow on each port that
+ * is covered in that path.
+ *
+ * @param sourceMac
+ * @param sourceNodeConnectorRef
+ * @param destMac
+ * @param destNodeConnectorRef
+ */
+ @Override
+ public void addBidirectionalMacToMacFlows(MacAddress sourceMac, NodeConnectorRef sourceNodeConnectorRef,
+ MacAddress destMac, NodeConnectorRef destNodeConnectorRef) {
+ Preconditions.checkNotNull(sourceMac, "Source mac address should not be null.");
+ Preconditions.checkNotNull(sourceNodeConnectorRef, "Source port should not be null.");
+ Preconditions.checkNotNull(destMac, "Destination mac address should not be null.");
+ Preconditions.checkNotNull(destNodeConnectorRef, "Destination port should not be null.");
+
+ if (sourceNodeConnectorRef.equals(destNodeConnectorRef)) {
+ LOG.info(
+ "In addMacToMacFlowsUsingShortestPath: No flows added. Source and Destination ports are same.");
+ return;
+
+ }
+
+ // add destMac-To-sourceMac flow on source port
+ addMacToMacFlow(destMac, sourceMac, sourceNodeConnectorRef);
+
+ // add sourceMac-To-destMac flow on destination port
+ addMacToMacFlow(sourceMac, destMac, destNodeConnectorRef);
+ }
+
+ /**
+ * @param nodeConnectorRef
+ * @return
+ */
+ private InstanceIdentifier<Flow> buildFlowPath(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
+
+ // generate unique flow key
+ FlowId flowId = new FlowId(String.valueOf(flowIdInc.getAndIncrement()));
+ FlowKey flowKey = new FlowKey(flowId);
+
+ return InstanceIdentifierUtils.generateFlowInstanceIdentifier(nodeConnectorRef, flowTableKey, flowKey);
+ }
+ /**
+ * @param tableId
+ * @param priority
+ * @param sourceMac
+ * @param destMac
+ * @param destPort
+ * @return {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder}
+ * builds flow that forwards all packets with destMac to given port
+ */
+ private Flow createMacToMacFlow(Short tableId, int priority, MacAddress sourceMac, MacAddress destMac,
+ NodeConnectorRef destPort) {
+
+ // start building flow
+ FlowBuilder macToMacFlow = new FlowBuilder() //
+ .setTableId(tableId) //
+ .setFlowName("mac2mac");
+
+ // use its own hash code for id.
+ macToMacFlow.setId(new FlowId(Long.toString(macToMacFlow.hashCode())));
+
+ // create a match that has mac to mac ethernet match
+ EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder() //
+ .setEthernetDestination(new EthernetDestinationBuilder() //
+ .setAddress(destMac) //
+ .build());
+ // set source in the match only if present
+ if (sourceMac != null) {
+ ethernetMatchBuilder.setEthernetSource(new EthernetSourceBuilder().setAddress(sourceMac).build());
+ }
+ EthernetMatch ethernetMatch = ethernetMatchBuilder.build();
+ Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).build();
+
+ Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+
+ Action outputToControllerAction = new ActionBuilder() //
+ .setOrder(0)
+ .setAction(new OutputActionCaseBuilder() //
+ .setOutputAction(new OutputActionBuilder() //
+ .setMaxLength(0xffff) //
+ .setOutputNodeConnector(destPortUri) //
+ .build()) //
+ .build()) //
+ .build();
+
+ // Create an Apply Action
+ ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
+ .build();
+
+ // Wrap our Apply Action in an Instruction
+ Instruction applyActionsInstruction = new InstructionBuilder() //
+ .setOrder(0)
+ .setInstruction(new ApplyActionsCaseBuilder()//
+ .setApplyActions(applyActions) //
+ .build()) //
+ .build();
+
+ // Put our Instruction in a list of Instructions
+ macToMacFlow.setMatch(match) //
+ .setInstructions(new InstructionsBuilder() //
+ .setInstruction(ImmutableList.of(applyActionsInstruction)) //
+ .build()) //
+ .setPriority(priority) //
+ .setBufferId(OFConstants.OFP_NO_BUFFER) //
+ .setHardTimeout(flowHardTimeout) //
+ .setIdleTimeout(flowIdleTimeout) //
+ .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
+ .setFlags(new FlowModFlags(false, false, false, false, false));
+
+ return macToMacFlow.build();
}
- // add destMac-To-sourceMac flow on source port
- addMacToMacFlow(destMac, sourceMac, sourceNodeConnectorRef);
-
- // add sourceMac-To-destMac flow on destination port
- addMacToMacFlow(sourceMac, destMac, destNodeConnectorRef);
- }
-
- /**
- * @param nodeConnectorRef
- * @return
- */
- private InstanceIdentifier<Flow> buildFlowPath(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
-
- // generate unique flow key
- FlowId flowId = new FlowId(String.valueOf(flowIdInc.getAndIncrement()));
- FlowKey flowKey = new FlowKey(flowId);
-
- return InstanceIdentifierUtils.generateFlowInstanceIdentifier(nodeConnectorRef, flowTableKey, flowKey);
- }
-
- /**
- * @param tableId
- * @param priority
- * @param sourceMac
- * @param destMac
- * @param destPort
- * @return {@link org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder}
- * builds flow that forwards all packets with destMac to given port
- */
- private Flow createMacToMacFlow(Short tableId, int priority,
- MacAddress sourceMac, MacAddress destMac, NodeConnectorRef destPort) {
-
- // start building flow
- FlowBuilder macToMacFlow = new FlowBuilder() //
- .setTableId(tableId) //
- .setFlowName("mac2mac");
-
- // use its own hash code for id.
- macToMacFlow.setId(new FlowId(Long.toString(macToMacFlow.hashCode())));
-
- // create a match that has mac to mac ethernet match
- EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder() //
- .setEthernetDestination(new EthernetDestinationBuilder() //
- .setAddress(destMac) //
- .build());
- // set source in the match only if present
- if(sourceMac != null) {
- ethernetMatchBuilder.setEthernetSource(new EthernetSourceBuilder()
- .setAddress(sourceMac)
- .build());
+ /**
+ * Starts and commits data change transaction which modifies provided flow
+ * path with supplied body.
+ *
+ * @param flowPath
+ * @param flow
+ * @return transaction commit
+ */
+ private Future<RpcResult<AddFlowOutput>> writeFlowToConfigData(InstanceIdentifier<Flow> flowPath, Flow flow) {
+ final InstanceIdentifier<Table> tableInstanceId = flowPath.<Table>firstIdentifierOf(Table.class);
+ final InstanceIdentifier<Node> nodeInstanceId = flowPath.<Node>firstIdentifierOf(Node.class);
+ final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowRef(new FlowRef(flowPath));
+ builder.setFlowTable(new FlowTableRef(tableInstanceId));
+ builder.setTransactionUri(new Uri(flow.getId().getValue()));
+ return salFlowService.addFlow(builder.build());
}
- EthernetMatch ethernetMatch = ethernetMatchBuilder.build();
- Match match = new MatchBuilder()
- .setEthernetMatch(ethernetMatch)
- .build();
-
-
- Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
-
- Action outputToControllerAction = new ActionBuilder() //
- .setOrder(0)
- .setAction(new OutputActionCaseBuilder() //
- .setOutputAction(new OutputActionBuilder() //
- .setMaxLength(0xffff) //
- .setOutputNodeConnector(destPortUri) //
- .build()) //
- .build()) //
- .build();
-
- // Create an Apply Action
- ApplyActions applyActions = new ApplyActionsBuilder().setAction(ImmutableList.of(outputToControllerAction))
- .build();
-
- // Wrap our Apply Action in an Instruction
- Instruction applyActionsInstruction = new InstructionBuilder() //
- .setOrder(0)
- .setInstruction(new ApplyActionsCaseBuilder()//
- .setApplyActions(applyActions) //
- .build()) //
- .build();
-
- // Put our Instruction in a list of Instructions
- macToMacFlow
- .setMatch(match) //
- .setInstructions(new InstructionsBuilder() //
- .setInstruction(ImmutableList.of(applyActionsInstruction)) //
- .build()) //
- .setPriority(priority) //
- .setBufferId(OFConstants.OFP_NO_BUFFER) //
- .setHardTimeout(flowHardTimeout) //
- .setIdleTimeout(flowIdleTimeout) //
- .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
- .setFlags(new FlowModFlags(false, false, false, false, false));
-
- return macToMacFlow.build();
- }
-
- /**
- * Starts and commits data change transaction which
- * modifies provided flow path with supplied body.
- *
- * @param flowPath
- * @param flow
- * @return transaction commit
- */
- private Future<RpcResult<AddFlowOutput>> writeFlowToConfigData(InstanceIdentifier<Flow> flowPath,
- Flow flow) {
- final InstanceIdentifier<Table> tableInstanceId = flowPath.<Table>firstIdentifierOf(Table.class);
- final InstanceIdentifier<Node> nodeInstanceId = flowPath.<Node>firstIdentifierOf(Node.class);
- final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow);
- builder.setNode(new NodeRef(nodeInstanceId));
- builder.setFlowRef(new FlowRef(flowPath));
- builder.setFlowTable(new FlowTableRef(tableInstanceId));
- builder.setTransactionUri(new Uri(flow.getId().getValue()));
- return salFlowService.addFlow(builder.build());
- }
}