@Override public void next(NextObjective nextObjective) { if (nextObjective.type() != NextObjective.Type.BROADCAST) { log.error("OLT only supports broadcast groups."); fail(nextObjective, ObjectiveError.BADPARAMS); if (nextObjective.next().size() != 1) { log.error("OLT only supports singleton broadcast groups."); fail(nextObjective, ObjectiveError.BADPARAMS); TrafficTreatment treatment = nextObjective.next().stream().findFirst().get(); GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id())); switch (nextObjective.op()) { case ADD: GroupDescription groupDesc = key, null, nextObjective.appId()); groupService.addGroup(groupDesc); break; case REMOVE: groupService.removeGroup(deviceId, key, nextObjective.appId()); break; case ADD_TO_EXISTING: groupService.addBucketsToGroup(deviceId, key, new GroupBuckets(Collections.singletonList(bucket)), key, nextObjective.appId());
@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; }
@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)); }
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; }
/** * 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 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()); } }
/** * 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()); }
.append(", Treatments: ") .append(((NextObjective) pn.flowObjective()) .next());
public List<NextObjective> updateNext(NextObjective nextObjective) { switch (this.operator) { case Parallel: case Sequential: case Override: return updateNextComposition(nextObjective); case Application: if (nextObjective.appId().id() == this.applicationId) { return this.nextTable.updateNext(nextObjective); } else { return new ArrayList<>(); } default: return new ArrayList<>(); } }
/** * Creates a simple L2 Interface Group. * * @param nextObj the next Objective */ private void createL2InterfaceGroup(NextObjective nextObj) { VlanId assignedVlan = Ofdpa2Pipeline.readVlanFromSelector(nextObj.meta()); if (assignedVlan == null) { log.warn("VLAN ID required by simple next obj is missing. Abort."); Ofdpa2Pipeline.fail(nextObj, ObjectiveError.BADPARAMS); return; } List<GroupInfo> groupInfos = prepareL2InterfaceGroup(nextObj, assignedVlan); // There is only one L2 interface group in this case GroupDescription l2InterfaceGroupDesc = groupInfos.get(0).innerMostGroupDesc; // Put all dependency information into allGroupKeys List<Deque<GroupKey>> allGroupKeys = Lists.newArrayList(); Deque<GroupKey> gkeyChain = new ArrayDeque<>(); gkeyChain.addFirst(l2InterfaceGroupDesc.appCookie()); allGroupKeys.add(gkeyChain); // Point the next objective to this group OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj); updatePendingNextObjective(l2InterfaceGroupDesc.appCookie(), ofdpaGrp); // Start installing the inner-most group groupService.addGroup(l2InterfaceGroupDesc); }
@Override public void init(DeviceId deviceId, PipelinerContext context) { this.serviceDirectory = context.directory(); this.deviceId = deviceId; flowRuleService = serviceDirectory.get(FlowRuleService.class); flowObjectiveStore = serviceDirectory.get(FlowObjectiveStore.class); pendingNext = CacheBuilder.newBuilder() .expireAfterWrite(20, TimeUnit.SECONDS) .removalListener((RemovalNotification<Integer, NextObjective> notification) -> { if (notification.getCause() == RemovalCause.EXPIRED) { notification.getValue().context() .ifPresent(c -> c.onError(notification.getValue(), ObjectiveError.FLOWINSTALLATIONFAILED)); } }).build(); }
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()); } }
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; }
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(); TrafficTreatment treatment = treatments.iterator().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);
@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)); }); } }
if (nextObjective != null) { pendingNext.invalidate(fwd.nextId()); nextObjective.next().forEach(treat -> { FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() .forDevice(deviceId)
l3MulticastGroupKey, l3MulticastGroupId, nextObj.appId());