@Override public void filter(FilteringObjective filter) { Instructions.OutputInstruction output; if (filter.meta() != null && !filter.meta().immediate().isEmpty()) { output = (Instructions.OutputInstruction) filter .meta() .immediate() .stream() .filter(t -> t.type().equals(Instruction.Type.OUTPUT)) .limit(1) .findFirst() .get(); if (output == null || !output.port().equals(PortNumber.CONTROLLER)) { log.error("OLT can only filter packet to controller"); fail(filter, ObjectiveError.UNSUPPORTED); return; } } else { fail(filter, ObjectiveError.BADPARAMS); return; } if (filter.key().type() != Criterion.Type.IN_PORT) { fail(filter, ObjectiveError.BADPARAMS); return; } EthTypeCriterion ethType = (EthTypeCriterion) filterForCriterion(filter.conditions(), Criterion.Type.ETH_TYPE); if (ethType == null) { fail(filter, ObjectiveError.BADPARAMS); return; } if (ethType.ethType().equals(EthType.EtherType.EAPOL.ethType())) { provisionEapol(filter, ethType, output); } else if (ethType.ethType().equals(EthType.EtherType.IPV4.ethType())) { IPProtocolCriterion ipProto = (IPProtocolCriterion) filterForCriterion(filter.conditions(), Criterion.Type.IP_PROTO); if (ipProto.protocol() == IPv4.PROTOCOL_IGMP) { provisionIgmp(filter, ethType, ipProto, output); } else { log.error("OLT can only filter igmp"); fail(filter, ObjectiveError.UNSUPPORTED); } } else { log.error("OLT can only filter eapol and igmp"); fail(filter, ObjectiveError.UNSUPPORTED); } }
@Override // Dell switches need ETH_DST based match condition in all IP table entries. // So this method overrides the default spring-open behavior and adds // ETH_DST match condition while pushing IP table flow rules protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { log.debug("Processing specific"); TrafficSelector selector = fwd.selector(); EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); if ((ethType == null) || ((((short) ethType.ethType()) != Ethernet.TYPE_IPV4) && (((short) ethType.ethType()) != Ethernet.MPLS_UNICAST))) { log.debug("processSpecific: Unsupported " + "forwarding objective criteraia"); fail(fwd, ObjectiveError.UNSUPPORTED); return Collections.emptySet(); } TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder(); int forTableId = -1; if (((short) ethType.ethType()) == Ethernet.TYPE_IPV4) { if (deviceTMac == null) { log.debug( "processSpecific: ETH_DST filtering " + "objective is not set which is required " + "before sending a IPv4 forwarding objective"); // TODO: Map the error to more appropriate error code. fail(fwd, ObjectiveError.DEVICEMISSING); return Collections.emptySet(); } filteredSelectorBuilder = filteredSelectorBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchEthDst(deviceTMac) .matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); forTableId = ipv4UnicastTableId; log.debug("processing IPv4 specific forwarding objective"); } else { filteredSelectorBuilder = filteredSelectorBuilder .matchEthType(Ethernet.MPLS_UNICAST) .matchMplsLabel( ((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); // TODO: Add Match for BoS // if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) { // } forTableId = mplsTableId; log.debug("processing MPLS specific forwarding objective"); } TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); if (fwd.treatment() != null) { for (Instruction i : fwd.treatment().allInstructions()) { treatmentBuilder.add(i); } } if (fwd.nextId() != null) { NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); if (next != null) { GroupKey key = appKryo.deserialize(next.data()); Group group = groupService.getGroup(deviceId, key); if (group == null) { log.warn("The group left!"); fail(fwd, ObjectiveError.GROUPMISSING); return Collections.emptySet(); } treatmentBuilder.group(group.id()); log.debug("Adding OUTGROUP action"); } else { log.warn("processSpecific: No associated next objective object"); fail(fwd, ObjectiveError.GROUPMISSING); return Collections.emptySet(); } } TrafficSelector filteredSelector = filteredSelectorBuilder.build(); TrafficTreatment treatment = treatmentBuilder.transition(aclTableId).build(); FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() .fromApp(fwd.appId()) .withPriority(fwd.priority()) .forDevice(deviceId) .withSelector(filteredSelector) .withTreatment(treatment); if (fwd.permanent()) { ruleBuilder.makePermanent(); } else { ruleBuilder.makeTemporary(fwd.timeout()); } ruleBuilder.forTable(forTableId); return Collections.singletonList(ruleBuilder.build()); }