import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
/**
* Simple Learning Switch implementation which does mac learning for one switch.
- *
- *
*/
public class LearningSwitchHandlerSimpleImpl implements LearningSwitchHandler, PacketProcessingListener {
private static final Logger LOG = LoggerFactory.getLogger(LearningSwitchHandlerSimpleImpl.class);
-
private static final byte[] ETH_TYPE_IPV4 = new byte[] { 0x08, 0x00 };
-
private static final int DIRECT_FLOW_PRIORITY = 512;
- private DataChangeListenerRegistrationHolder registrationPublisher;
- private FlowCommitWrapper dataStoreAccessor;
- private PacketProcessingService packetProcessingService;
+ private final DataTreeChangeListenerRegistrationHolder registrationPublisher;
+ private final FlowCommitWrapper dataStoreAccessor;
+ private final PacketProcessingService packetProcessingService;
- private boolean iAmLearning = false;
+ private volatile boolean isLearning = false;
private NodeId nodeId;
- private AtomicLong flowIdInc = new AtomicLong();
- private AtomicLong flowCookieInc = new AtomicLong(0x2a00000000000000L);
+ private final AtomicLong flowIdInc = new AtomicLong();
+ private final AtomicLong flowCookieInc = new AtomicLong(0x2a00000000000000L);
private InstanceIdentifier<Node> nodePath;
- private InstanceIdentifier<Table> tablePath;
+ private volatile InstanceIdentifier<Table> tablePath;
private Map<MacAddress, NodeConnectorRef> mac2portMapping;
- private Set<String> coveredMacPaths;
+ private final Set<String> coveredMacPaths = new HashSet<>();
+
+ public LearningSwitchHandlerSimpleImpl(@Nonnull FlowCommitWrapper dataStoreAccessor,
+ @Nonnull PacketProcessingService packetProcessingService,
+ @Nullable DataTreeChangeListenerRegistrationHolder registrationPublisher) {
+ this.dataStoreAccessor = Objects.requireNonNull(dataStoreAccessor);
+ this.packetProcessingService = Objects.requireNonNull(packetProcessingService);
+ this.registrationPublisher = registrationPublisher;
+ }
@Override
public synchronized void onSwitchAppeared(InstanceIdentifier<Table> appearedTablePath) {
- if (iAmLearning) {
+ if (isLearning) {
LOG.debug("already learning a node, skipping {}", nodeId.getValue());
return;
}
// disable listening - simple learning handles only one node (switch)
if (registrationPublisher != null) {
- try {
- LOG.debug("closing dataChangeListenerRegistration");
- registrationPublisher.getDataChangeListenerRegistration().close();
- } catch (Exception e) {
- LOG.warn("closing registration upon flowCapable node update listener failed: {}", e.getMessage());
- LOG.debug("closing registration upon flowCapable node update listener failed.. ", e);
- }
+ LOG.debug("closing dataTreeChangeListenerRegistration");
+ registrationPublisher.getDataTreeChangeListenerRegistration().close();
}
- iAmLearning = true;
+ isLearning = true;
tablePath = appearedTablePath;
nodePath = tablePath.firstIdentifierOf(Node.class);
nodeId = nodePath.firstKeyOf(Node.class, NodeKey.class).getId();
mac2portMapping = new HashMap<>();
- coveredMacPaths = new HashSet<>();
// start forwarding all packages to controller
FlowId flowId = new FlowId(String.valueOf(flowIdInc.getAndIncrement()));
dataStoreAccessor.writeFlowToConfig(flowPath, allToCtrlFlow.build());
}
- @Override
- public void setRegistrationPublisher(DataChangeListenerRegistrationHolder registrationPublisher) {
- this.registrationPublisher = registrationPublisher;
- }
-
- @Override
- public void setDataStoreAccessor(FlowCommitWrapper dataStoreAccessor) {
- this.dataStoreAccessor = dataStoreAccessor;
- }
-
- @Override
- public void setPacketProcessingService(PacketProcessingService packetProcessingService) {
- this.packetProcessingService = packetProcessingService;
- }
-
@Override
public void onPacketReceived(PacketReceived notification) {
- if (!iAmLearning) {
+ if (!isLearning) {
// ignoring packets - this should not happen
return;
}
}
- /**
- * @param srcMac
- * @param dstMac
- * @param destNodeConnector
- */
private void addBridgeFlow(MacAddress srcMac, MacAddress dstMac, NodeConnectorRef destNodeConnector) {
synchronized (coveredMacPaths) {
String macPath = srcMac.toString() + dstMac.toString();
private void flood(byte[] payload, NodeConnectorRef ingress) {
NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(nodeConnectorId("0xfffffffb"));
- InstanceIdentifier<?> nodeConnectorPath = InstanceIdentifierUtils.createNodeConnectorPath(nodePath, nodeConnectorKey);
+ InstanceIdentifier<?> nodeConnectorPath = InstanceIdentifierUtils.createNodeConnectorPath(
+ nodePath, nodeConnectorKey);
NodeConnectorRef egressConnectorRef = new NodeConnectorRef(nodeConnectorPath);
sendPacketOut(payload, ingress, egressConnectorRef);
.setEgress(egress)
.setIngress(ingress)
.build();
- packetProcessingService.transmitPacket(input);
+ JdkFutures.addErrorLogging(packetProcessingService.transmitPacket(input), LOG, "transmitPacket");
}
}