public List<NextObjective> updateNext(NextObjective nextObjective) { List<NextObjective> updates = new ArrayList<>(); switch (nextObjective.op()) { case ADD: this.nextMap.put(nextObjective.id(), nextObjective); updates.add(nextObjective); break; case REMOVE: this.nextMap.remove(nextObjective.id()); updates.add(nextObjective); break; default: break; } return updates; }
@Override public void run() { Set<GroupKey> keys = pendingGroups.asMap().keySet().stream() .filter(key -> groupService.getGroup(deviceId, key) != null) .collect(Collectors.toSet()); keys.stream().forEach(key -> { NextObjective obj = pendingGroups.getIfPresent(key); if (obj == null) { return; } pass(obj); pendingGroups.invalidate(key); log.info("Heard back from group service for group {}. " + "Applying pending forwarding objectives", obj.id()); flowObjectiveStore.putNextGroup(obj.id(), new CentecV350Group(key)); }); } }
boolean queueNextObjective(DeviceId deviceId, NextObjective next) { // we need to hold off on other operations till we get notified that the // initial group creation has succeeded boolean queued = false; synchronized (pendingNexts) { // double check the flow objective store, because this block could run // after a notification arrives if (flowObjectiveStore.getNextGroup(next.id()) == null) { pendingNexts.compute(next.id(), (id, pending) -> { PendingFlowObjective pendfo = new PendingFlowObjective(deviceId, next); if (pending == null) { return Lists.newArrayList(pendfo); } else { pending.add(pendfo); return pending; } }); queued = true; } } if (queued) { log.debug("Queued next objective {} with operation {} meant for device {}", next.id(), next.op(), deviceId); } return queued; }
@Override public void next(NextObjective nextObjective) { pendingNext.put(nextObjective.id(), nextObjective); flowObjectiveStore.putNextGroup(nextObjective.id(), new SingleGroup(new DefaultGroupKey(appKryo.serialize(nextObjective.id())))); nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective)); }
/** * Next Objectives are stored as dummy groups for retrieval later * when Forwarding Objectives reference the next objective id. At that point * the dummy group is fetched from the distributed store and the enclosed * treatment is applied as a flow rule action. * * @param nextObj the next objective of type simple */ private void processSimpleNextObjective(NextObjective nextObj) { // Simple next objective has a single treatment (not a collection) log.debug("Received nextObj {}", nextObj.id()); // delay processing to emulate group creation delay(50); TrafficTreatment treatment = nextObj.next().iterator().next(); flowObjectiveStore.putNextGroup(nextObj.id(), new DummyGroup(treatment)); }
@Override public void run() { Set<GroupKey> keys = pendingGroups .asMap() .keySet() .stream() .filter(key -> groupService.getGroup(deviceId, key) != null) .collect(Collectors.toSet()); keys.stream() .forEach(key -> { NextObjective obj = pendingGroups .getIfPresent(key); if (obj == null) { return; } log.debug("Group verified: dev:{} gid:{} <<->> nextId:{}", deviceId, groupService.getGroup(deviceId, key).id(), obj.id()); pass(obj); pendingGroups.invalidate(key); flowObjectiveStore.putNextGroup( obj.id(), new SpringOpenGroup(key, null)); }); } }
/** * Removes all groups in multiple possible group-chains that represent the next * objective. * * @param nextObjective the next objective to remove * @param next the NextGroup that represents the existing group-chain for * this next objective */ protected void removeGroup(NextObjective nextObjective, NextGroup next) { List<Deque<GroupKey>> allgkeys = Ofdpa2Pipeline.appKryo.deserialize(next.data()); List<GroupKey> groupKeys = allgkeys.stream() .map(Deque::getFirst).collect(Collectors.toList()); pendingRemoveNextObjectives.put(nextObjective, groupKeys); allgkeys.forEach(groupChain -> groupChain.forEach(groupKey -> groupService.removeGroup(deviceId, groupKey, nextObjective.appId()))); flowObjectiveStore.removeNextGroup(nextObjective.id()); }
@Override public void event(GroupEvent event) { if (event.type() == GroupEvent.Type.GROUP_ADDED) { GroupKey key = event.subject().appCookie(); NextObjective obj = pendingGroups.getIfPresent(key); if (obj != null) { flowObjectiveStore.putNextGroup(obj.id(), new OLTPipelineGroup(key)); pass(obj); pendingGroups.invalidate(key); } } } }
@Override public void event(GroupEvent event) { if (event.type() == GroupEvent.Type.GROUP_ADDED) { GroupKey key = event.subject().appCookie(); NextObjective obj = pendingGroups.getIfPresent(key); if (obj != null) { flowObjectiveStore.putNextGroup(obj.id(), new CentecV350Group(key)); pass(obj); pendingGroups.invalidate(key); } } } }
@Override public void event(GroupEvent event) { if (event.type() == GroupEvent.Type.GROUP_ADDED) { log.trace("InnerGroupListener: Group ADDED " + "event received in device {}", deviceId); GroupKey key = event.subject().appCookie(); NextObjective obj = pendingGroups.getIfPresent(key); if (obj != null) { log.debug("Group verified: dev:{} gid:{} <<->> nextId:{}", deviceId, event.subject().id(), obj.id()); flowObjectiveStore .putNextGroup(obj.id(), new SpringOpenGroup(key, null)); pass(obj); pendingGroups.invalidate(key); } } else if (event.type() == GroupEvent.Type.GROUP_ADD_FAILED) { log.warn("InnerGroupListener: Group ADD " + "failed event received in device {}", deviceId); } } }
+ "Done implementing next objective: {} <<-->> gid:0x{}", (added) ? "ADDED" : "processed", key, deviceId, nextGrp.nextObjective().id(), Integer.toHexString(groupService.getGroup(deviceId, key) .givenGroupId())); Ofdpa2Pipeline.pass(nextGrp.nextObjective()); flowObjectiveStore.putNextGroup(nextGrp.nextObjective().id(), nextGrp); .remove(nextGrp.nextObjective().id()); if (pendBkt != null) { addBucketToGroup(pendBkt, nextGrp);
private void removeBucketFromGroup(NextObjective nextObjective) { log.debug("removeBucketFromGroup in {}: for next objective id {}", deviceId, nextObjective.id()); NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id()); if (nextGroup != null) { Collection<TrafficTreatment> treatments = nextObjective.next(); final GroupKey key = new DefaultGroupKey( appKryo.serialize(nextObjective .id())); Group group = groupService.getGroup(deviceId, key); if (group == null) { group.id(), nextObjective.id(), deviceId); groupService.removeBucketsFromGroup(deviceId, key, removeBuckets, key, appId);
private void addBucketToGroup(NextObjective nextObjective) { log.debug("addBucketToGroup in {}: for next objective id {}", deviceId, nextObjective.id()); Collection<TrafficTreatment> treatments = nextObjective.next(); TrafficTreatment treatment = treatments.iterator().next(); final GroupKey key = new DefaultGroupKey( appKryo.serialize(nextObjective .id())); Group group = groupService.getGroup(deviceId, key); if (group == null) { log.warn("Group is not found in {} for {}", deviceId, key); return; } GroupBucket bucket; if (group.type() == GroupDescription.Type.INDIRECT) { bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment); } else if (group.type() == GroupDescription.Type.SELECT) { bucket = DefaultGroupBucket.createSelectGroupBucket(treatment); } else if (group.type() == GroupDescription.Type.ALL) { bucket = DefaultGroupBucket.createAllGroupBucket(treatment); } else { log.warn("Unsupported Group type {}", group.type()); return; } GroupBuckets bucketsToAdd = new GroupBuckets(Collections.singletonList(bucket)); log.debug("Adding buckets to group id {} of next objective id {} in device {}", group.id(), nextObjective.id(), deviceId); groupService.addBucketsToGroup(deviceId, key, bucketsToAdd, key, appId); }
@Override public void next(DeviceId deviceId, NextObjective nextObjective) { checkPermission(FLOWRULE_WRITE); if (nextObjective.op() == Operation.ADD || nextObjective.op() == Operation.VERIFY || flowObjectiveStore.getNextGroup(nextObjective.id()) != null || !queueNextObjective(deviceId, nextObjective)) { // either group exists or we are trying to create it - let it through executorService.execute(new ObjectiveInstaller(deviceId, nextObjective)); } }
@Override public void next(NextObjective nextObjective) { switch (nextObjective.type()) { case SIMPLE: Collection<TrafficTreatment> treatments = nextObjective.next(); if (treatments.size() != 1) { log.error("Next Objectives of type Simple should only have a " + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id()); fail(nextObjective, ObjectiveError.BADPARAMS); return; } processSimpleNextObjective(nextObjective); break; case HASHED: case BROADCAST: case FAILOVER: fail(nextObjective, ObjectiveError.UNSUPPORTED); log.warn("Unsupported next objective type {}", nextObjective.type()); break; default: fail(nextObjective, ObjectiveError.UNKNOWN); log.warn("Unknown next objective type {}", nextObjective.type()); } }
@Override public ObjectNode encode(NextObjective nextObjective, CodecContext context) { checkNotNull(nextObjective, NOT_NULL_MESSAGE); final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); // encode common properties ObjectiveCodecHelper och = new ObjectiveCodecHelper(); ObjectNode result = och.encode(nextObjective, context); // encode id result.put(ID, nextObjective.id()); // encode type result.put(TYPE, nextObjective.type().toString()); // encode operation result.put(OPERATION, nextObjective.op().toString()); // encode treatments ArrayNode treatments = context.mapper().createArrayNode(); nextObjective.next().forEach(t -> { ObjectNode treatmentJson = trafficTreatmentCodec.encode(t, context); treatments.add(treatmentJson); }); result.set(TREATMENTS, treatments); // encode meta if (nextObjective.meta() != null) { ObjectNode trafficSelectorNode = trafficSelectorCodec.encode(nextObjective.meta(), context); result.set(META, trafficSelectorNode); } return result; }
protected void addGroup(NextObjective nextObjective) { switch (nextObjective.type()) { case SIMPLE: Collection<TrafficTreatment> treatments = nextObjective.next(); if (treatments.size() != 1) { log.error("Next Objectives of type Simple should only have a " + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id()); Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.BADPARAMS); return; } processSimpleNextObjective(nextObjective); break; case BROADCAST: processBroadcastNextObjective(nextObjective); break; case HASHED: processHashedNextObjective(nextObjective); break; case FAILOVER: Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.UNSUPPORTED); log.warn("Unsupported next objective type {}", nextObjective.type()); break; default: Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.UNKNOWN); log.warn("Unknown next objective type {}", nextObjective.type()); } }
GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
.nextStep(nextObjective.id()) .withPriority(priority) .fromApp(appId)