use of org.onosproject.net.behaviour.upf.UpfTerminationUplink in project up4 by omec-project.
the class Up4DeviceManager method getUplinkFlows.
@Override
public Collection<UplinkUpfFlow> getUplinkFlows() throws UpfProgrammableException {
Collection<UplinkUpfFlow> uplinkFlows = Lists.newArrayList();
Collection<? extends UpfEntity> uplinkTerm = this.adminReadAll(TERMINATION_UPLINK);
Map<Integer, UpfMeter> appMeters = Maps.newHashMap();
this.adminReadAll(APPLICATION_METER).forEach(am -> appMeters.put(((UpfMeter) am).cellId(), (UpfMeter) am));
for (UpfEntity t : uplinkTerm) {
UpfTerminationUplink term = (UpfTerminationUplink) t;
uplinkFlows.add(UplinkUpfFlow.builder().withTerminationUplink(term).withCounter(this.readCounter(term.counterId())).withAppMeter(appMeters.getOrDefault(term.appMeterIdx(), null)).build());
}
return uplinkFlows;
}
use of org.onosproject.net.behaviour.upf.UpfTerminationUplink in project up4 by omec-project.
the class Up4DeviceManager method apply.
@Override
public void apply(UpfEntity entity) throws UpfProgrammableException {
switch(entity.type()) {
case SESSION_DOWNLINK:
UpfSessionDownlink sessDl = (UpfSessionDownlink) entity;
if (sessDl.needsBuffering()) {
// Override tunnel peer id with the DBUF
entity = convertToBuffering(sessDl);
up4Store.learnBufferingUe(sessDl.ueAddress());
}
break;
case TERMINATION_UPLINK:
UpfTerminationUplink termUl = (UpfTerminationUplink) entity;
if (isMaxUeSet() && termUl.counterId() >= getMaxUe() * 2) {
throw new UpfProgrammableException("Counter cell index referenced by uplink UPF termination " + "rule above max supported UE value.", UpfProgrammableException.Type.ENTITY_OUT_OF_RANGE, UpfEntityType.TERMINATION_UPLINK);
}
break;
case TERMINATION_DOWNLINK:
UpfTerminationDownlink termDl = (UpfTerminationDownlink) entity;
if (isMaxUeSet() && termDl.counterId() >= getMaxUe() * 2) {
throw new UpfProgrammableException("Counter cell index referenced by downlink UPF termination " + "rule above max supported UE value.", UpfProgrammableException.Type.ENTITY_OUT_OF_RANGE, UpfEntityType.TERMINATION_DOWNLINK);
}
break;
case INTERFACE:
UpfInterface intf = (UpfInterface) entity;
if (intf.isDbufReceiver()) {
throw new UpfProgrammableException("Cannot apply the DBUF interface entry!");
}
break;
case TUNNEL_PEER:
UpfGtpTunnelPeer tunnelPeer = (UpfGtpTunnelPeer) entity;
if (tunnelPeer.tunPeerId() == DBUF_TUNNEL_ID) {
throw new UpfProgrammableException("Cannot apply the DBUF GTP Tunnel Peer");
}
break;
default:
break;
}
getLeaderUpfProgrammable().apply(entity);
// Drain from DBUF if necessary
if (entity.type().equals(SESSION_DOWNLINK)) {
UpfSessionDownlink sess = (UpfSessionDownlink) entity;
if (!sess.needsBuffering() && up4Store.forgetBufferingUe(sess.ueAddress())) {
// TODO: Should we wait for rules to be installed on all devices before
// triggering drain?
// When a fwd FAR is changed to buff FAR,
// both session_downlink & downlink_termination rules are updated.
// If the drain action starts immediately right after applying session_downlink,
// the downlink_termination rule may not be updated,
// thus, the TEID may wrong in such case.
// Run the outbound rpc in a forked context so it doesn't cancel if it was called
// by an inbound rpc that completes faster than the drain call
Ip4Address ueAddr = sess.ueAddress();
Context ctx = Context.current().fork();
ctx.run(() -> {
if (dbufClient == null) {
log.error("Cannot start dbuf drain for {}, dbufClient is null", ueAddr);
return;
}
if (config == null || config.dbufDrainAddr() == null) {
log.error("Cannot start dbuf drain for {}, dbufDrainAddr is null", ueAddr);
return;
}
log.info("Started dbuf drain for {}", ueAddr);
dbufClient.drain(ueAddr, config.dbufDrainAddr(), GTP_PORT).whenComplete((result, ex) -> {
if (ex != null) {
log.error("Exception while draining dbuf for {}: {}", ueAddr, ex);
} else if (result) {
log.info("Dbuf drain completed for {}", ueAddr);
} else {
log.warn("Unknown error while draining dbuf for {}", ueAddr);
}
});
});
}
}
}
use of org.onosproject.net.behaviour.upf.UpfTerminationUplink in project up4 by omec-project.
the class ReadUpfEntitiesCommand method doExecute.
@Override
protected void doExecute() {
Up4AdminService up4Admin = get(Up4AdminService.class);
Up4Service up4Service = get(Up4Service.class);
boolean filterCounters = false;
try {
List<UpfEntityType> printedTypes = new ArrayList<>();
if (all) {
printedTypes.add(UpfEntityType.APPLICATION);
printedTypes.add(UpfEntityType.SESSION_UPLINK);
printedTypes.add(UpfEntityType.SESSION_DOWNLINK);
printedTypes.add(UpfEntityType.TERMINATION_UPLINK);
printedTypes.add(UpfEntityType.TERMINATION_DOWNLINK);
printedTypes.add(UpfEntityType.TUNNEL_PEER);
printedTypes.add(UpfEntityType.INTERFACE);
printedTypes.add(UpfEntityType.SESSION_METER);
printedTypes.add(UpfEntityType.APPLICATION_METER);
filterCounters = true;
} else if (ue) {
printedTypes.add(UpfEntityType.APPLICATION);
printedTypes.add(UpfEntityType.SESSION_UPLINK);
printedTypes.add(UpfEntityType.SESSION_DOWNLINK);
printedTypes.add(UpfEntityType.TERMINATION_UPLINK);
printedTypes.add(UpfEntityType.TERMINATION_DOWNLINK);
printedTypes.add(UpfEntityType.TUNNEL_PEER);
printedTypes.add(UpfEntityType.SESSION_METER);
printedTypes.add(UpfEntityType.APPLICATION_METER);
filterCounters = true;
} else {
if (application) {
printedTypes.add(UpfEntityType.APPLICATION);
}
if (sessions) {
printedTypes.add(UpfEntityType.SESSION_UPLINK);
printedTypes.add(UpfEntityType.SESSION_DOWNLINK);
}
if (termination) {
printedTypes.add(UpfEntityType.TERMINATION_UPLINK);
printedTypes.add(UpfEntityType.TERMINATION_DOWNLINK);
}
if (tunnels) {
printedTypes.add(UpfEntityType.TUNNEL_PEER);
}
if (counters) {
printedTypes.add(UpfEntityType.COUNTER);
filterCounters = false;
}
if (interfaces) {
printedTypes.add(UpfEntityType.INTERFACE);
}
if (appMeters) {
printedTypes.add(UpfEntityType.APPLICATION_METER);
}
if (sessMeters) {
printedTypes.add(UpfEntityType.SESSION_METER);
}
}
for (var type : printedTypes) {
if (type.equals(UpfEntityType.TERMINATION_UPLINK)) {
Collection<? extends UpfEntity> terminations = up4Admin.adminReadAll(type);
for (var t : terminations) {
UpfTerminationUplink term = (UpfTerminationUplink) t;
print(term.toString());
if (filterCounters) {
print(up4Service.readCounter(term.counterId()).toString());
}
}
} else if (type.equals(UpfEntityType.TERMINATION_DOWNLINK)) {
Collection<? extends UpfEntity> terminations = up4Admin.adminReadAll(type);
for (var t : terminations) {
UpfTerminationDownlink term = (UpfTerminationDownlink) t;
print(term.toString());
if (filterCounters) {
print(up4Service.readCounter(term.counterId()).toString());
}
}
} else {
up4Admin.adminReadAll(type).forEach(upfEntity -> print(upfEntity.toString()));
}
}
} catch (UpfProgrammableException e) {
print("Error while reading UPF entity: " + e.getMessage());
}
}
use of org.onosproject.net.behaviour.upf.UpfTerminationUplink in project up4 by omec-project.
the class Up4TranslatorImpl method upfEntityToUp4TableEntry.
@Override
public PiTableEntry upfEntityToUp4TableEntry(UpfEntity entity) throws Up4TranslationException {
PiTableEntry.Builder tableEntryBuilder = PiTableEntry.builder();
PiAction.Builder actionBuilder = PiAction.builder();
PiMatchKey.Builder matchBuilder = PiMatchKey.builder();
switch(entity.type()) {
case INTERFACE:
tableEntryBuilder.forTable(PRE_QOS_PIPE_INTERFACES);
UpfInterface upfIntf = (UpfInterface) entity;
byte direction;
byte srcIface;
actionBuilder.withId(PRE_QOS_PIPE_SET_SOURCE_IFACE);
if (upfIntf.isAccess()) {
srcIface = IFACE_ACCESS;
direction = DIRECTION_UPLINK;
} else if (upfIntf.isCore()) {
srcIface = IFACE_CORE;
direction = DIRECTION_DOWNLINK;
} else {
throw new Up4TranslationException("UPF Interface is not Access nor CORE: " + upfIntf);
}
actionBuilder.withParameter(new PiActionParam(SRC_IFACE, srcIface)).withParameter(new PiActionParam(DIRECTION, direction)).withParameter(new PiActionParam(SLICE_ID, (byte) upfIntf.sliceId()));
matchBuilder.addFieldMatch(new PiLpmFieldMatch(HDR_IPV4_DST_PREFIX, ImmutableByteSequence.copyFrom(upfIntf.prefix().address().toOctets()), upfIntf.prefix().prefixLength()));
break;
case SESSION_UPLINK:
tableEntryBuilder.forTable(PRE_QOS_PIPE_SESSIONS_UPLINK);
UpfSessionUplink sessionUplink = (UpfSessionUplink) entity;
matchBuilder.addFieldMatch(new PiExactFieldMatch(HDR_N3_ADDRESS, ImmutableByteSequence.copyFrom(sessionUplink.tunDstAddr().toOctets()))).addFieldMatch(new PiExactFieldMatch(HDR_TEID, ImmutableByteSequence.copyFrom(sessionUplink.teid())));
if (sessionUplink.needsDropping()) {
actionBuilder.withId(PRE_QOS_PIPE_SET_SESSION_UPLINK_DROP);
} else {
actionBuilder.withId(PRE_QOS_PIPE_SET_SESSION_UPLINK);
actionBuilder.withParameter(new PiActionParam(SESSION_METER_IDX, sessionUplink.sessionMeterIdx()));
}
break;
case SESSION_DOWNLINK:
tableEntryBuilder.forTable(PRE_QOS_PIPE_SESSIONS_DOWNLINK);
UpfSessionDownlink sessionDownlink = (UpfSessionDownlink) entity;
matchBuilder.addFieldMatch(new PiExactFieldMatch(HDR_UE_ADDRESS, ImmutableByteSequence.copyFrom(sessionDownlink.ueAddress().toOctets())));
if (sessionDownlink.needsDropping() && sessionDownlink.needsBuffering()) {
log.error("We don't support DROP + BUFF on the UP4 northbound! Defaulting to only BUFF");
actionBuilder.withId(PRE_QOS_PIPE_SET_SESSION_DOWNLINK_BUFF);
actionBuilder.withParameter(new PiActionParam(SESSION_METER_IDX, sessionDownlink.sessionMeterIdx()));
} else if (sessionDownlink.needsDropping()) {
actionBuilder.withId(PRE_QOS_PIPE_SET_SESSION_DOWNLINK_DROP);
} else {
actionBuilder.withParameter(new PiActionParam(SESSION_METER_IDX, sessionDownlink.sessionMeterIdx()));
if (sessionDownlink.needsBuffering()) {
actionBuilder.withId(PRE_QOS_PIPE_SET_SESSION_DOWNLINK_BUFF);
} else {
actionBuilder.withParameter(new PiActionParam(TUNNEL_PEER_ID, ImmutableByteSequence.copyFrom(sessionDownlink.tunPeerId())));
actionBuilder.withId(PRE_QOS_PIPE_SET_SESSION_DOWNLINK);
}
}
break;
case TERMINATION_UPLINK:
tableEntryBuilder.forTable(PRE_QOS_PIPE_TERMINATIONS_UPLINK);
UpfTerminationUplink upfTerminationUl = (UpfTerminationUplink) entity;
matchBuilder.addFieldMatch(new PiExactFieldMatch(HDR_UE_ADDRESS, ImmutableByteSequence.copyFrom(upfTerminationUl.ueSessionId().toOctets()))).addFieldMatch(new PiExactFieldMatch(HDR_APP_ID, ImmutableByteSequence.copyFrom(upfTerminationUl.applicationId())));
actionBuilder.withParameter(new PiActionParam(CTR_IDX, upfTerminationUl.counterId()));
if (upfTerminationUl.needsDropping()) {
actionBuilder.withId(PRE_QOS_PIPE_UPLINK_TERM_DROP);
} else {
if (upfTerminationUl.trafficClass() != null) {
actionBuilder.withId(PRE_QOS_PIPE_UPLINK_TERM_FWD);
actionBuilder.withParameter(new PiActionParam(TC, upfTerminationUl.trafficClass()));
} else {
actionBuilder.withId(PRE_QOS_PIPE_UPLINK_TERM_FWD_NO_TC);
}
actionBuilder.withParameter(new PiActionParam(APP_METER_IDX, upfTerminationUl.appMeterIdx()));
}
break;
case TERMINATION_DOWNLINK:
tableEntryBuilder.forTable(PRE_QOS_PIPE_TERMINATIONS_DOWNLINK);
UpfTerminationDownlink upfTerminationDl = (UpfTerminationDownlink) entity;
matchBuilder.addFieldMatch(new PiExactFieldMatch(HDR_UE_ADDRESS, ImmutableByteSequence.copyFrom(upfTerminationDl.ueSessionId().toOctets()))).addFieldMatch(new PiExactFieldMatch(HDR_APP_ID, ImmutableByteSequence.copyFrom(upfTerminationDl.applicationId())));
actionBuilder.withParameter(new PiActionParam(CTR_IDX, upfTerminationDl.counterId()));
if (upfTerminationDl.needsDropping()) {
actionBuilder.withId(PRE_QOS_PIPE_DOWNLINK_TERM_DROP);
} else {
actionBuilder.withParameter(new PiActionParam(TEID, upfTerminationDl.teid())).withParameter(new PiActionParam(QFI, upfTerminationDl.qfi()));
if (upfTerminationDl.trafficClass() != null) {
actionBuilder.withId(PRE_QOS_PIPE_DOWNLINK_TERM_FWD);
actionBuilder.withParameter(new PiActionParam(TC, upfTerminationDl.trafficClass()));
} else {
actionBuilder.withId(PRE_QOS_PIPE_DOWNLINK_TERM_FWD_NO_TC);
}
actionBuilder.withParameter(new PiActionParam(APP_METER_IDX, upfTerminationDl.appMeterIdx()));
}
break;
case TUNNEL_PEER:
tableEntryBuilder.forTable(PRE_QOS_PIPE_TUNNEL_PEERS);
UpfGtpTunnelPeer gtpTunnelPeer = (UpfGtpTunnelPeer) entity;
matchBuilder.addFieldMatch(new PiExactFieldMatch(HDR_TUNNEL_PEER_ID, ImmutableByteSequence.copyFrom(gtpTunnelPeer.tunPeerId())));
actionBuilder.withId(PRE_QOS_PIPE_LOAD_TUNNEL_PARAM).withParameter(new PiActionParam(SRC_ADDR, gtpTunnelPeer.src().toOctets())).withParameter(new PiActionParam(DST_ADDR, gtpTunnelPeer.dst().toOctets())).withParameter(new PiActionParam(SPORT, gtpTunnelPeer.srcPort()));
break;
case APPLICATION:
tableEntryBuilder.forTable(PRE_QOS_PIPE_APPLICATIONS);
UpfApplication application = (UpfApplication) entity;
tableEntryBuilder.withPriority(application.priority());
actionBuilder.withId(PRE_QOS_PIPE_SET_APP_ID).withParameter(new PiActionParam(APP_ID, application.appId()));
matchBuilder.addFieldMatch(new PiExactFieldMatch(HDR_SLICE_ID, ImmutableByteSequence.copyFrom((byte) application.sliceId())));
if (application.ip4Prefix().isPresent()) {
Ip4Prefix ipPrefix = application.ip4Prefix().get();
matchBuilder.addFieldMatch(new PiLpmFieldMatch(HDR_APP_IP_ADDR, ImmutableByteSequence.copyFrom(ipPrefix.address().toOctets()), ipPrefix.prefixLength()));
}
if (application.l4PortRange().isPresent()) {
Range<Short> portRange = application.l4PortRange().get();
matchBuilder.addFieldMatch(new PiRangeFieldMatch(HDR_APP_L4_PORT, ImmutableByteSequence.copyFrom(portRange.lowerEndpoint()), ImmutableByteSequence.copyFrom(portRange.upperEndpoint())));
}
if (application.ipProto().isPresent()) {
byte ipProto = application.ipProto().get();
matchBuilder.addFieldMatch(new PiTernaryFieldMatch(HDR_APP_IP_PROTO, ImmutableByteSequence.copyFrom(ipProto), ImmutableByteSequence.ofOnes(1)));
}
break;
case SESSION_METER:
case APPLICATION_METER:
case COUNTER:
default:
throw new Up4TranslationException("Attempting to translate an unsupported UPF entity to a table entry! " + entity);
}
return tableEntryBuilder.withMatchKey(matchBuilder.build()).withAction(actionBuilder.build()).build();
}
Aggregations