blob: 7f839cf39cfda95673bc456a9ca5f252be58ccd5 [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.segmentrouting.grouphandler;
import org.onosproject.net.DeviceId;
import org.slf4j.Logger;
import com.google.common.base.MoreObjects.ToStringHelper;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import static com.google.common.base.MoreObjects.toStringHelper;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Representation of a set of destination switch dpids along with their edge-node
* labels. Meant to be used as a lookup-key in a hash-map to retrieve an ECMP-group
* that hashes packets towards a specific destination switch,
* or paired-destination switches.
*/
public class DestinationSet {
public static final int NO_EDGE_LABEL = -1;
private static final int NOT_ASSIGNED = 0;
private boolean mplsSet;
private final DeviceId dstSw1;
private final int edgeLabel1;
private final DeviceId dstSw2;
private final int edgeLabel2;
private static final Logger log = getLogger(DestinationSet.class);
/**
* Constructor for a single destination with no Edge label.
*
* @param isMplsSet indicates if it is a mpls destination set
* @param dstSw the destination switch
*/
public DestinationSet(boolean isMplsSet, DeviceId dstSw) {
this.edgeLabel1 = NO_EDGE_LABEL;
this.mplsSet = isMplsSet;
this.dstSw1 = dstSw;
this.edgeLabel2 = NOT_ASSIGNED;
this.dstSw2 = null;
}
/**
* Constructor for a single destination with Edge label.
*
* @param isMplsSet indicates if it is a mpls destination set
* @param edgeLabel label to be pushed as part of group operation
* @param dstSw the destination switch
*/
public DestinationSet(boolean isMplsSet,
int edgeLabel, DeviceId dstSw) {
this.mplsSet = isMplsSet;
this.edgeLabel1 = edgeLabel;
this.dstSw1 = dstSw;
this.edgeLabel2 = NOT_ASSIGNED;
this.dstSw2 = null;
}
/**
* Constructor for paired destination switches and their associated
* edge labels.
*
* @param isMplsSet indicates if it is a mpls destination set
* @param edgeLabel1 label to be pushed as part of group operation for dstSw1
* @param dstSw1 one of the paired destination switches
* @param edgeLabel2 label to be pushed as part of group operation for dstSw2
* @param dstSw2 the other paired destination switch
*/
public DestinationSet(boolean isMplsSet,
int edgeLabel1, DeviceId dstSw1,
int edgeLabel2, DeviceId dstSw2) {
this.mplsSet = isMplsSet;
if (dstSw1.toString().compareTo(dstSw2.toString()) <= 0) {
this.edgeLabel1 = edgeLabel1;
this.dstSw1 = dstSw1;
this.edgeLabel2 = edgeLabel2;
this.dstSw2 = dstSw2;
} else {
this.edgeLabel1 = edgeLabel2;
this.dstSw1 = dstSw2;
this.edgeLabel2 = edgeLabel1;
this.dstSw2 = dstSw1;
}
}
/**
* Default constructor for kryo serialization.
*/
public DestinationSet() {
this.edgeLabel1 = NOT_ASSIGNED;
this.edgeLabel2 = NOT_ASSIGNED;
this.mplsSet = true;
this.dstSw1 = DeviceId.NONE;
this.dstSw2 = DeviceId.NONE;
}
/**
* Factory method for DestinationSet hierarchy.
*
* @param random the expected behavior.
* @param isMplsSet indicates if it is a mpls destination set
* @param dstSw the destination switch
* @return the destination set object.
*/
public static DestinationSet destinationSet(boolean random,
boolean isMplsSet, DeviceId dstSw) {
return random ? new RandomDestinationSet(dstSw)
: new DestinationSet(isMplsSet, dstSw);
}
/**
* Factory method for DestinationSet hierarchy.
*
* @param random the expected behavior.
* @param isMplsSet indicates if it is a mpls destination set
* @param edgeLabel label to be pushed as part of group operation
* @param dstSw the destination switch
* @return the destination set object
*/
public static DestinationSet destinationSet(boolean random,
boolean isMplsSet, int edgeLabel,
DeviceId dstSw) {
return random ? new RandomDestinationSet(edgeLabel, dstSw)
: new DestinationSet(isMplsSet, edgeLabel, dstSw);
}
/**
* Factory method for DestinationSet hierarchy.
*
* @param random the expected behavior.
* @return the destination set object
*/
public static DestinationSet destinationSet(boolean random) {
return random ? new RandomDestinationSet() : new DestinationSet();
}
/**
* Gets the label associated with given destination switch.
*
* @param dstSw the destination switch
* @return integer the label associated with the destination switch
*/
public int getEdgeLabel(DeviceId dstSw) {
if (dstSw.equals(dstSw1)) {
return edgeLabel1;
} else if (dstSw.equals(dstSw2)) {
return edgeLabel2;
}
return NOT_ASSIGNED;
}
/**
* Gets all the destination switches in this destination set.
*
* @return a set of destination switch ids
*/
public Set<DeviceId> getDestinationSwitches() {
Set<DeviceId> dests = new HashSet<>();
dests.add(dstSw1);
if (dstSw2 != null) {
dests.add(dstSw2);
}
return dests;
}
/**
* Gets the value of mplsSet.
*
* @return the value of mplsSet
*/
public boolean mplsSet() {
return mplsSet;
}
// The list of destination ids and label are used for comparison.
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof DestinationSet)) {
return false;
}
DestinationSet that = (DestinationSet) o;
boolean equal = (this.edgeLabel1 == that.edgeLabel1 &&
this.mplsSet == that.mplsSet &&
this.dstSw1.equals(that.dstSw1));
if (this.dstSw2 != null && that.dstSw2 == null ||
this.dstSw2 == null && that.dstSw2 != null) {
return false;
}
if (this.dstSw2 != null && that.dstSw2 != null) {
equal = equal && (this.edgeLabel2 == that.edgeLabel2 &&
this.dstSw2.equals(that.dstSw2));
}
return equal;
}
// The list of destination ids and label are used for comparison.
@Override
public int hashCode() {
if (dstSw2 == null) {
return Objects.hash(mplsSet, edgeLabel1, dstSw1);
}
return Objects.hash(mplsSet, edgeLabel1, dstSw1, edgeLabel2, dstSw2);
}
@Override
public String toString() {
ToStringHelper h = toStringHelper(this)
.add("MplsSet", mplsSet)
.add("DstSw1", dstSw1)
.add("Label1", edgeLabel1);
if (dstSw2 != null) {
h.add("DstSw2", dstSw2)
.add("Label2", edgeLabel2);
}
return h.toString();
}
}