blob: 4b2ef124e65ea2bbcac826374d18f2d3437017fc [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Laboratory
*
* 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.mapping;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.onosproject.mapping.addresses.MappingAddress;
import org.onosproject.mapping.instructions.MappingInstruction;
import org.onosproject.mapping.instructions.MappingInstructions;
import org.onosproject.mapping.instructions.MulticastMappingInstruction;
import org.onosproject.mapping.instructions.MulticastMappingInstruction.MulticastType;
import org.onosproject.mapping.instructions.UnicastMappingInstruction;
import org.onosproject.mapping.instructions.UnicastMappingInstruction.UnicastType;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Default implementation of mapping treatment.
*/
public final class DefaultMappingTreatment implements MappingTreatment {
private final List<MappingInstruction> instructions;
private final MappingAddress address;
/**
* Create a new mapping treatment from the specified list of mapping instructions.
*
* @param instructions mapping instructions
*/
private DefaultMappingTreatment(MappingAddress address,
List<MappingInstruction> instructions) {
this.address = address;
this.instructions = ImmutableList.copyOf(checkNotNull(instructions));
}
@Override
public MappingAddress address() {
return address;
}
@Override
public List<MappingInstruction> instructions() {
return ImmutableList.copyOf(instructions);
}
@Override
public int hashCode() {
return Objects.hash(address, instructions);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultMappingTreatment) {
DefaultMappingTreatment that = (DefaultMappingTreatment) obj;
return Objects.equals(address, that.address) &&
Objects.equals(instructions, that.instructions);
}
return false;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("address", address)
.add("mapping instructions", instructions)
.toString();
}
/**
* Returns a new mapping treatment builder.
*
* @return mapping treatment builder
*/
public static Builder builder() {
return new Builder();
}
/**
* Returns a new mapping treatment builder primed to produce entities
* patterned after the supplied mapping treatment.
*
* @param treatment base mapping treatment
* @return mapping treatment builder
*/
public static Builder builder(MappingTreatment treatment) {
return new Builder(treatment);
}
/**
* Builds a mapping treatment.
*/
public static final class Builder implements MappingTreatment.Builder {
private List<MappingInstruction> instructions = Lists.newArrayList();
private MappingAddress address;
private Map<UnicastType, Integer> unicastTypeMap = Maps.newConcurrentMap();
private Map<MulticastType, Integer> multicastTypeMap = Maps.newConcurrentMap();
// creates a new builder
private Builder() {
initTypeMap();
}
// creates a new builder based off an existing mapping treatment
private Builder(MappingTreatment treatment) {
treatment.instructions().forEach(i -> instructions.add(i));
address = treatment.address();
initTypeMap();
}
/**
* Initializes type map.
*/
private void initTypeMap() {
unicastTypeMap.put(UnicastType.WEIGHT, 0);
unicastTypeMap.put(UnicastType.PRIORITY, 0);
multicastTypeMap.put(MulticastType.WEIGHT, 0);
multicastTypeMap.put(MulticastType.PRIORITY, 0);
}
@Override
public Builder withAddress(MappingAddress address) {
this.address = address;
return this;
}
@Override
public Builder add(MappingInstruction instruction) {
switch (instruction.type()) {
case UNICAST:
unicastTypeMap.compute(((UnicastMappingInstruction)
instruction).subtype(), (k, v) -> v + 1);
instructions.add(instruction);
break;
case MULTICAST:
multicastTypeMap.compute(((MulticastMappingInstruction)
instruction).subtype(), (k, v) -> v + 1);
instructions.add(instruction);
break;
case EXTENSION:
instructions.add(instruction);
break;
default:
throw new IllegalArgumentException("Unknown mapping " +
"instruction type: " + instruction.type());
}
return this;
}
@Override
public Builder setUnicastWeight(int weight) {
return add(MappingInstructions.unicastWeight(weight));
}
@Override
public Builder setUnicastPriority(int priority) {
return add(MappingInstructions.unicastPriority(priority));
}
@Override
public Builder setMulticastWeight(int weight) {
return add(MappingInstructions.multicastWeight(weight));
}
@Override
public Builder setMulticastPriority(int priority) {
return add(MappingInstructions.multicastPriority(priority));
}
@Override
public Builder extension(ExtensionTreatment extension, DeviceId deviceId) {
return add(MappingInstructions.extension(extension, deviceId));
}
@Override
public MappingTreatment build() {
unicastTypeMap.forEach((k, v) -> checkArgument(v <= 1,
"Should not specify more than one " + k.toString()));
multicastTypeMap.forEach((k, v) -> checkArgument(v <= 1,
"Should not specify more than one " + k.toString()));
return new DefaultMappingTreatment(address, instructions);
}
}
}