use of org.onosproject.net.behaviour.upf.UpfGtpTunnelPeer 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.UpfGtpTunnelPeer in project up4 by omec-project.
the class Up4DeviceManager method deleteAll.
@Override
public void deleteAll(UpfEntityType entityType) throws UpfProgrammableException {
switch(entityType) {
case TERMINATION_DOWNLINK:
getLeaderUpfProgrammable().deleteAll(entityType);
up4Store.reset();
break;
case INTERFACE:
Collection<? extends UpfEntity> intfs = getLeaderUpfProgrammable().readAll(UpfEntityType.INTERFACE).stream().filter(t -> !((UpfInterface) t).isDbufReceiver()).collect(Collectors.toList());
for (UpfEntity i : intfs) {
getLeaderUpfProgrammable().delete(i);
}
break;
case TUNNEL_PEER:
Collection<? extends UpfEntity> tunnels = getLeaderUpfProgrammable().readAll(UpfEntityType.TUNNEL_PEER).stream().filter(t -> ((UpfGtpTunnelPeer) t).tunPeerId() != DBUF_TUNNEL_ID).collect(Collectors.toList());
for (UpfEntity tun : tunnels) {
getLeaderUpfProgrammable().delete(tun);
}
break;
default:
getLeaderUpfProgrammable().deleteAll(entityType);
}
}
use of org.onosproject.net.behaviour.upf.UpfGtpTunnelPeer in project up4 by omec-project.
the class Up4DeviceManager method delete.
@Override
public void delete(UpfEntity entity) throws UpfProgrammableException {
switch(entity.type()) {
case SESSION_DOWNLINK:
UpfSessionDownlink sess = (UpfSessionDownlink) entity;
if (sess.needsBuffering()) {
entity = convertToBuffering(sess);
}
break;
case INTERFACE:
UpfInterface intf = (UpfInterface) entity;
if (intf.isDbufReceiver()) {
throw new UpfProgrammableException("Cannot delete the DBUF interface rule!");
}
break;
case TUNNEL_PEER:
UpfGtpTunnelPeer tunnel = (UpfGtpTunnelPeer) entity;
if (tunnel.tunPeerId() == DBUF_TUNNEL_ID) {
throw new UpfProgrammableException("Cannot delete the DBUF GTP tunnel peer");
}
break;
default:
break;
}
getLeaderUpfProgrammable().delete(entity);
forgetBufferingUeIfRequired(entity);
}
use of org.onosproject.net.behaviour.upf.UpfGtpTunnelPeer 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();
}
use of org.onosproject.net.behaviour.upf.UpfGtpTunnelPeer in project up4 by omec-project.
the class Up4DeviceManager method getDownlinkFlows.
@Override
public Collection<DownlinkUpfFlow> getDownlinkFlows() throws UpfProgrammableException {
Collection<DownlinkUpfFlow> downlinkFlows = Lists.newArrayList();
Map<Ip4Address, UpfSessionDownlink> ueToSess = Maps.newHashMap();
Map<Byte, UpfGtpTunnelPeer> idToTunn = Maps.newHashMap();
Map<Integer, UpfMeter> sessMeters = Maps.newHashMap();
Map<Integer, UpfMeter> appMeters = Maps.newHashMap();
Collection<? extends UpfEntity> downlinkTerm = this.adminReadAll(TERMINATION_DOWNLINK);
this.adminReadAll(SESSION_DOWNLINK).forEach(s -> ueToSess.put(((UpfSessionDownlink) s).ueAddress(), (UpfSessionDownlink) s));
this.adminReadAll(TUNNEL_PEER).forEach(t -> idToTunn.put(((UpfGtpTunnelPeer) t).tunPeerId(), (UpfGtpTunnelPeer) t));
this.adminReadAll(SESSION_METER).forEach(sm -> sessMeters.put(((UpfMeter) sm).cellId(), (UpfMeter) sm));
this.adminReadAll(APPLICATION_METER).forEach(am -> appMeters.put(((UpfMeter) am).cellId(), (UpfMeter) am));
for (UpfEntity t : downlinkTerm) {
UpfTerminationDownlink term = (UpfTerminationDownlink) t;
UpfSessionDownlink sess = ueToSess.getOrDefault(term.ueSessionId(), null);
UpfGtpTunnelPeer tunn = null;
UpfMeter sMeter = null;
UpfMeter aMeter = null;
if (sess != null) {
tunn = idToTunn.getOrDefault(sess.tunPeerId(), null);
sMeter = sessMeters.getOrDefault(sess.sessionMeterIdx(), null);
}
aMeter = appMeters.getOrDefault(term.appMeterIdx(), null);
downlinkFlows.add(DownlinkUpfFlow.builder().withTerminationDownlink(term).withSessionDownlink(sess).withTunnelPeer(tunn).withCounter(this.readCounter(term.counterId())).withAppMeter(aMeter).withSessionMeter(sMeter).build());
}
return downlinkFlows;
}
Aggregations