/* * Copyright 2014-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.net.intent; import com.google.common.annotations.Beta; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import org.onosproject.core.ApplicationId; import org.onosproject.net.ConnectPoint; import org.onosproject.net.FilteredConnectPoint; import org.onosproject.net.ResourceGroup; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.TrafficTreatment; import org.slf4j.Logger; import java.util.Set; import java.util.List; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static org.slf4j.LoggerFactory.getLogger; /** * Abstraction of single source, multiple destination connectivity intent. */ @Beta public final class SinglePointToMultiPointIntent extends ConnectivityIntent { private final FilteredConnectPoint ingressPoint; private final Set<FilteredConnectPoint> egressPoints; /** * Creates a new single-to-multi point connectivity intent. * * @param appId application identifier * @param key intent key * @param selector traffic selector * @param treatment treatment * @param ingressPoint port on which traffic will ingress * @param egressPoints set of ports on which traffic will egress * @param constraints constraints to apply to the intent * @param priority priority to use for flows generated by this intent * @throws NullPointerException if {@code ingressPoint} or * {@code egressPoints} is null * @throws IllegalArgumentException if the size of {@code egressPoints} is * not more than 1 */ private SinglePointToMultiPointIntent(ApplicationId appId, Key key, TrafficSelector selector, TrafficTreatment treatment, FilteredConnectPoint ingressPoint, Set<FilteredConnectPoint> egressPoints, List<Constraint> constraints, int priority, ResourceGroup resourceGroup) { super(appId, key, ImmutableList.of(), selector, treatment, constraints, priority, resourceGroup); checkNotNull(egressPoints); checkNotNull(ingressPoint); checkArgument(!egressPoints.isEmpty(), "Egress point set cannot be empty"); checkArgument(!egressPoints.contains(ingressPoint), "Set of egresses should not contain ingress (ingress: %s)", ingressPoint); this.ingressPoint = ingressPoint; this.egressPoints = Sets.newHashSet(egressPoints); } /** * Returns a new single point to multi point intent builder. The application id, * ingress point and egress points are required fields. If they are * not set by calls to the appropriate methods, an exception will * be thrown. * * @return single point to multi point builder */ public static Builder builder() { return new Builder(); } /** * Creates a new builder pre-populated with the information in the given * intent. * * @param intent initial intent * @return intent builder */ public static Builder builder(SinglePointToMultiPointIntent intent) { return new Builder(intent); } /** * Builder of a single point to multi point intent. */ public static final class Builder extends ConnectivityIntent.Builder { private final Logger log = getLogger(getClass()); private FilteredConnectPoint ingressPoint; private Set<FilteredConnectPoint> egressPoints; private Builder() { // Hide constructor } /** * Creates a new builder pre-populated with information from the given * intent. * * @param intent initial intent */ protected Builder(SinglePointToMultiPointIntent intent) { super(intent); this.filteredEgressPoints(intent.filteredEgressPoints()) .filteredIngressPoint(intent.filteredIngressPoint()); } @Override public Builder appId(ApplicationId appId) { return (Builder) super.appId(appId); } @Override public Builder key(Key key) { return (Builder) super.key(key); } @Override public Builder selector(TrafficSelector selector) { return (Builder) super.selector(selector); } @Override public Builder treatment(TrafficTreatment treatment) { return (Builder) super.treatment(treatment); } @Override public Builder constraints(List<Constraint> constraints) { return (Builder) super.constraints(constraints); } @Override public Builder priority(int priority) { return (Builder) super.priority(priority); } @Override public Builder resourceGroup(ResourceGroup resourceGroup) { return (Builder) super.resourceGroup(resourceGroup); } /** * Sets the ingress point of the single point to multi point intent * that will be built. * * @param ingressPoint ingress connect point * @return this builder */ @Deprecated public Builder ingressPoint(ConnectPoint ingressPoint) { if (this.ingressPoint != null) { log.warn("Ingress point is already set, " + "this will override original ingress point."); } this.ingressPoint = new FilteredConnectPoint(ingressPoint); return this; } /** * Sets the egress points of the single point to multi point intent * that will be built. * * @param egressPoints egress connect points * @return this builder */ @Deprecated public Builder egressPoints(Set<ConnectPoint> egressPoints) { if (this.egressPoints != null) { log.warn("Egress points are already set, " + "this will override original egress points."); } Set<FilteredConnectPoint> filteredConnectPoints = egressPoints.stream() .map(FilteredConnectPoint::new) .collect(Collectors.toSet()); this.egressPoints = ImmutableSet.copyOf(filteredConnectPoints); return this; } /** * Sets the filtered ingress point of the single point to * multi point intent that will be built. * * @param ingressPoint ingress connect point * @return this builder */ public Builder filteredIngressPoint(FilteredConnectPoint ingressPoint) { this.ingressPoint = ingressPoint; return this; } /** * Sets the filtered egress points of the single point to * multi point intent that will be built. * * @param egressPoints egress connect points * @return this builder */ public Builder filteredEgressPoints(Set<FilteredConnectPoint> egressPoints) { this.egressPoints = ImmutableSet.copyOf(egressPoints); return this; } /** * Builds a single point to multi point intent from the * accumulated parameters. * * @return point to point intent */ public SinglePointToMultiPointIntent build() { return new SinglePointToMultiPointIntent( appId, key, selector, treatment, ingressPoint, egressPoints, constraints, priority, resourceGroup ); } } /** * Constructor for serializer. */ protected SinglePointToMultiPointIntent() { super(); this.ingressPoint = null; this.egressPoints = null; } /** * Returns the port on which the ingress traffic should be connected to the * egress. * * @return ingress port */ public ConnectPoint ingressPoint() { return ingressPoint.connectPoint(); } /** * Returns the set of ports on which the traffic should egress. * * @return set of egress ports */ public Set<ConnectPoint> egressPoints() { return egressPoints.stream() .map(FilteredConnectPoint::connectPoint) .collect(Collectors.toSet()); } /** * Returns the filtered port on which the ingress traffic should be connected to the * egress. * * @return ingress port */ public FilteredConnectPoint filteredIngressPoint() { return ingressPoint; } /** * Returns the set of filtered ports on which the traffic should egress. * * @return set of egress ports */ public Set<FilteredConnectPoint> filteredEgressPoints() { return egressPoints; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .add("id", id()) .add("key", key()) .add("appId", appId()) .add("priority", priority()) .add("resources", resources()) .add("selector", selector()) .add("treatment", treatment()) .add("ingress", ingressPoint) .add("egress", egressPoints) .add("filteredIngressCPs", filteredIngressPoint()) .add("filteredEgressCP", filteredEgressPoints()) .add("constraints", constraints()) .add("resourceGroup", resourceGroup()) .toString(); } }