Cleanup FPC agent rules on create session
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/protocols/DpnP4Communicator.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/protocols/DpnP4Communicator.java
index 11c2c06..71c993e 100644
--- a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/protocols/DpnP4Communicator.java
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/protocols/DpnP4Communicator.java
@@ -90,11 +90,11 @@
.withId(PiActionId.of("NoAction"))
.build();
- private static final ConcurrentMap<Long, Ip4Address> SESS_ID_TO_UE_ADDR =
+ private static final ConcurrentMap<Long, Ip4Address> UE_ADDRESSES =
Maps.newConcurrentMap();
- private static final ConcurrentMap<Long, Set<FlowRule>> SESS_ID_TO_FLOWS =
+ private static final ConcurrentMap<Long, Set<FlowRule>> FLOWS =
Maps.newConcurrentMap();
- private static final ConcurrentMap<Long, Set<Route>> SESS_ID_TO_ROUTES =
+ private static final ConcurrentMap<Long, Set<Route>> ROUTES =
Maps.newConcurrentMap();
// FIXME: should use a cache with timeout
@@ -169,20 +169,18 @@
SESS_LOCKS.putIfAbsent(sessionId, new ReentrantLock());
SESS_LOCKS.get(sessionId).lock();
try {
- if (SESS_ID_TO_FLOWS.containsKey(sessionId)
- && !SESS_ID_TO_FLOWS.get(sessionId).isEmpty()) {
- log.error("Creating session {}, but {} rules already exists for such session.",
- sessionId, SESS_ID_TO_FLOWS.get(sessionId).size());
- SESS_ID_TO_FLOWS.get(sessionId).forEach(f -> log.debug("{}", f));
+ if (sessionHasState(sessionId)) {
+ log.warn("Creating session {}, but state for this session is already present. Forcing cleanup of old state...");
+ logSessionState(sessionId);
+ cleanUpSession(sessionId);
}
- // If old session is there, we keep the old rules.
- SESS_ID_TO_FLOWS.putIfAbsent(sessionId, Sets.newHashSet());
- SESS_ID_TO_UE_ADDR.put(sessionId, ueIpv4);
+ FLOWS.putIfAbsent(sessionId, Sets.newHashSet());
+ UE_ADDRESSES.put(sessionId, ueIpv4);
- SESS_ID_TO_FLOWS.get(sessionId).add(ueFilterRule(ueIpv4));
+ FLOWS.get(sessionId).add(ueFilterRule(ueIpv4));
- applySessionRules(sessionId);
+ applySession(sessionId);
sendNotification(
clientId.toString(),
@@ -211,28 +209,21 @@
SESS_LOCKS.putIfAbsent(sessionId, new ReentrantLock());
SESS_LOCKS.get(sessionId).lock();
try {
- if (!SESS_ID_TO_UE_ADDR.containsKey(sessionId)) {
+ if (!UE_ADDRESSES.containsKey(sessionId)) {
log.error("Missing sess ID in SESS_ID_TO_UE_ADDR map: {}",
sessionId);
return;
}
- final Ip4Address ueAddr = SESS_ID_TO_UE_ADDR.get(sessionId);
+ final Ip4Address ueAddr = UE_ADDRESSES.get(sessionId);
- if (SESS_ID_TO_ROUTES.containsKey(sessionId)
- && !SESS_ID_TO_ROUTES.get(sessionId).isEmpty()) {
- log.error("Modifying session {}, but {} DL routes already exists for such session.",
- sessionId, SESS_ID_TO_ROUTES.get(sessionId).size());
- SESS_ID_TO_ROUTES.get(sessionId).forEach(r -> log.debug("{}", r));
- }
- SESS_ID_TO_ROUTES.putIfAbsent(sessionId, Sets.newHashSet());
-
- SESS_ID_TO_FLOWS.get(sessionId).add(s1uFilterRule(s1USgwIpv4));
- SESS_ID_TO_FLOWS.get(sessionId)
+ FLOWS.get(sessionId).add(s1uFilterRule(s1USgwIpv4));
+ FLOWS.get(sessionId)
.add(dlSessLookupRule(ueAddr, s1UEnodebTeid,
s1UEnodebIpv4, s1USgwIpv4));
// Segment routing configuration
- SESS_ID_TO_ROUTES.get(sessionId).add(
+ ROUTES.putIfAbsent(sessionId, Sets.newHashSet());
+ ROUTES.get(sessionId).add(
new Route(Route.Source.STATIC, ueAddr.toIpPrefix(), s1UEnodebIpv4));
// List<InterfaceIpAddress> ifaceIpAddrList = Lists.newArrayList();
@@ -244,7 +235,7 @@
// Collections.emptySet(), VlanId.NONE);
// interfaceService.add(intf);
- applySessionRules(sessionId);
+ applySession(sessionId);
sendNotification(
clientId.toString(),
@@ -270,11 +261,7 @@
SESS_LOCKS.putIfAbsent(sessionId, new ReentrantLock());
SESS_LOCKS.get(sessionId).lock();
try {
- removeSessionRules(sessionId);
-
- SESS_ID_TO_UE_ADDR.remove(sessionId);
- SESS_ID_TO_FLOWS.remove(sessionId);
- SESS_ID_TO_ROUTES.remove(sessionId);
+ cleanUpSession(sessionId);
sendNotification(
clientId.toString(),
@@ -378,31 +365,48 @@
.fromApp(appId);
}
- private void applySessionRules(long sessionId) {
- if (SESS_ID_TO_FLOWS.containsKey(sessionId)) {
- batchApply(SESS_ID_TO_FLOWS.get(sessionId));
+ private void applySession(long sessionId) {
+ if (FLOWS.containsKey(sessionId)) {
+ batchApplyFlowRules(FLOWS.get(sessionId));
}
- if (SESS_ID_TO_ROUTES.containsKey(sessionId)) {
- SESS_ID_TO_ROUTES.get(sessionId).forEach(routeStore::updateRoute);
+ if (ROUTES.containsKey(sessionId)) {
+ ROUTES.get(sessionId).forEach(routeStore::updateRoute);
}
}
- private void removeSessionRules(long sessionId) {
- if (SESS_ID_TO_FLOWS.containsKey(sessionId)) {
- batchRemove(SESS_ID_TO_FLOWS.get(sessionId));
+ private void cleanUpSession(long sessionId) {
+ if (FLOWS.containsKey(sessionId)) {
+ batchRemoveFlowRules(FLOWS.get(sessionId));
+ FLOWS.get(sessionId).clear();
}
- if (SESS_ID_TO_ROUTES.containsKey(sessionId)) {
- SESS_ID_TO_ROUTES.get(sessionId).forEach(routeStore::removeRoute);
+ if (ROUTES.containsKey(sessionId)) {
+ ROUTES.get(sessionId).forEach(routeStore::removeRoute);
+ ROUTES.get(sessionId).clear();
+ }
+ UE_ADDRESSES.remove(sessionId);
+ }
+
+ private void logSessionState(long sessionId) {
+ if (FLOWS.containsKey(sessionId)) {
+ FLOWS.get(sessionId).forEach(f -> log.debug(f.toString()));
+ }
+ if (ROUTES.containsKey(sessionId)) {
+ ROUTES.get(sessionId).forEach(r -> log.debug(r.toString()));
}
}
- private void batchApply(Collection<FlowRule> rules) {
+ private boolean sessionHasState(long sessionId) {
+ return (FLOWS.containsKey(sessionId) && !FLOWS.get(sessionId).isEmpty())
+ || (ROUTES.containsKey(sessionId) && !ROUTES.get(sessionId).isEmpty());
+ }
+
+ private void batchApplyFlowRules(Collection<FlowRule> rules) {
final FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder();
rules.forEach(opsBuilder::add);
flowRuleService.apply(opsBuilder.build());
}
- private void batchRemove(Collection<FlowRule> rules) {
+ private void batchRemoveFlowRules(Collection<FlowRule> rules) {
final FlowRuleOperations.Builder opsBuilder = FlowRuleOperations.builder();
rules.forEach(opsBuilder::remove);
flowRuleService.apply(opsBuilder.build());