blob: cbb601b30950d2d760d7107b0087e55ddf2c37c3 [file] [log] [blame]
/*
* Copyright 2021-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.net.behaviour.upf;
import com.google.common.annotations.Beta;
import org.onlab.packet.Ip4Address;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A structure representing the UE Termination in the downlink direction on the
* UPF-programmable device.
* Provide means to configure the traffic behavior (e.g. set Traffic Class, GTP TEID, or QFI).
*/
@Beta
public final class UpfTerminationDownlink implements UpfEntity {
// Match Keys
private final Ip4Address ueSessionId; // UE Session ID, use UE IP address to uniquely identify a session.
private final byte applicationId; // Application ID, defaults to DEFAULT_APP_ID
// Action parameters
private final Integer ctrId; // Counter ID unique to this UPF Termination Rule
private final Byte trafficClass;
private final Integer teid; // Tunnel Endpoint Identifier
private final Byte qfi; // QoS Flow Identifier
private final boolean dropping;
private UpfTerminationDownlink(Ip4Address ueSessionId, byte applicationId, Integer ctrId, Byte trafficClass,
Integer teid, Byte qfi, boolean dropping) {
this.ueSessionId = ueSessionId;
this.applicationId = applicationId;
this.ctrId = ctrId;
this.trafficClass = trafficClass;
this.teid = teid;
this.qfi = qfi;
this.dropping = dropping;
}
public static Builder builder() {
return new Builder();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
UpfTerminationDownlink that = (UpfTerminationDownlink) obj;
// Safe comparisons between potentially null objects
return this.dropping == that.dropping &&
Objects.equals(this.ueSessionId, that.ueSessionId) &&
Objects.equals(this.applicationId, that.applicationId) &&
Objects.equals(this.ctrId, that.ctrId) &&
Objects.equals(this.trafficClass, that.trafficClass) &&
Objects.equals(this.teid, that.teid) &&
Objects.equals(this.qfi, that.qfi);
}
@Override
public int hashCode() {
return Objects.hash(ueSessionId, applicationId, ctrId, trafficClass, teid, qfi, dropping);
}
/**
* Get UE Session ID associated with UPF Termination rule.
*
* @return UE Session ID
*/
public Ip4Address ueSessionId() {
return ueSessionId;
}
/**
* Get the application ID associated with UPF Termination rule.
*
* @return the application ID
*/
public byte applicationId() {
return applicationId;
}
/**
* Get PDR Counter ID associated with UPF Termination rule.
*
* @return PDR counter cell ID
*/
public Integer counterId() {
return ctrId;
}
/**
* Get Traffic Class set by this UPF Termination rule.
*
* @return Traffic Class
*/
public Byte trafficClass() {
return trafficClass;
}
/**
* Get GTP TEID set by this UPF Termination rule.
*
* @return GTP tunnel ID
*/
public Integer teid() {
return teid;
}
/**
* Get QoS Flow Identifier set by this UPF Termination rule.
*
* @return QoS Flow Identifier
*/
public Byte qfi() {
return qfi;
}
/**
* True if this UPF Termination needs to drop traffic.
*
* @return true if the UPF Termination needs dropping.
*/
public boolean needsDropping() {
return dropping;
}
@Override
public UpfEntityType type() {
return UpfEntityType.TERMINATION_DOWNLINK;
}
@Override
public String toString() {
return "TerminationDL{" + matchString() + " -> " + actionString() + "}";
}
private String matchString() {
return "Match(ue_addr=" + this.ueSessionId() + ", app_id=" + this.applicationId + ")";
}
private String actionString() {
String fwd = "FWD";
if (this.needsDropping()) {
fwd = "DROP";
}
return "(" + fwd +
", TEID=" + this.teid() +
", CTR_ID=" + this.counterId() +
", QFI=" + this.qfi() +
", TC=" + this.trafficClass() +
")";
}
public static class Builder {
private Ip4Address ueSessionId = null;
private Byte applicationId = null;
private Integer ctrId = null;
private Byte trafficClass = null;
private Integer teid = null;
private Byte qfi = null;
private boolean drop = false;
public Builder() {
}
/**
* Set the ID of the UE session.
*
* @param ueSessionId UE session ID
* @return This builder object
*/
public Builder withUeSessionId(Ip4Address ueSessionId) {
this.ueSessionId = ueSessionId;
return this;
}
/**
* Set the ID of the application.
*
* @param applicationId Application ID
* @return This builder object
*/
public Builder withApplicationId(byte applicationId) {
this.applicationId = applicationId;
return this;
}
/**
* Set the dataplane counter cell ID.
*
* @param ctrId PDR counter cell ID
* @return This builder object
*/
public Builder withCounterId(int ctrId) {
this.ctrId = ctrId;
return this;
}
/**
* Set the Traffic Class.
*
* @param trafficClass Traffic Class
* @return This builder object
*/
public Builder withTrafficClass(byte trafficClass) {
this.trafficClass = trafficClass;
return this;
}
/**
* Set the identifier of the unidirectional GTP tunnel that should be used for the UE Session.
*
* @param teid tunnel ID
* @return This builder object
*/
public Builder withTeid(Integer teid) {
this.teid = teid;
return this;
}
/**
* Set the QoS Flow Identifier.
*
* @param qfi GTP Tunnel QFI
* @return This builder object
*/
public Builder withQfi(byte qfi) {
this.qfi = qfi;
return this;
}
/**
* Sets whether to drop downlink UPF termination traffic or not.
*
* @param drop True if request to drop, false otherwise
* @return This builder object
*/
public Builder needsDropping(boolean drop) {
this.drop = drop;
return this;
}
public UpfTerminationDownlink build() {
// Match fields must be provided
checkNotNull(ueSessionId, "UE session ID must be provided");
if (applicationId == null) {
applicationId = DEFAULT_APP_ID;
}
checkNotNull(ctrId, "Counter ID must be provided");
// TODO: should we verify that when dropping no other fields are provided
return new UpfTerminationDownlink(
this.ueSessionId, this.applicationId, this.ctrId, this.trafficClass,
this.teid, this.qfi, this.drop
);
}
}
}