use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method prepareL2UnfilteredGroup.
private List<GroupInfo> prepareL2UnfilteredGroup(NextObjective nextObj) {
ImmutableList.Builder<GroupInfo> groupInfoBuilder = ImmutableList.builder();
// break up broadcast next objective to multiple groups
Collection<TrafficTreatment> treatments = nextObj.nextTreatments().stream().filter(nt -> nt.type() == NextTreatment.Type.TREATMENT).map(nt -> ((DefaultNextTreatment) nt).treatment()).collect(Collectors.toSet());
Collection<Integer> nextIds = nextObj.nextTreatments().stream().filter(nt -> nt.type() == NextTreatment.Type.ID).map(nt -> ((IdNextTreatment) nt).nextId()).collect(Collectors.toSet());
// Each treatment is converted to an L2 unfiltered group
treatments.forEach(treatment -> {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
// Extract port information
PortNumber port = treatment.allInstructions().stream().map(instr -> (Instructions.OutputInstruction) instr).map(instr -> instr.port()).findFirst().orElse(null);
if (port == null) {
log.debug("Skip bucket without output instruction");
return;
}
tBuilder.setOutput(port);
if (requireAllowVlanTransition()) {
tBuilder.extension(new OfdpaSetAllowVlanTranslation(Ofdpa3AllowVlanTranslationType.ALLOW), deviceId);
}
// Build L2UG
int l2ugk = l2UnfilteredGroupKey(deviceId, port.toLong());
final GroupKey l2UnfilterGroupKey = new DefaultGroupKey(appKryo.serialize(l2ugk));
int l2UnfilteredGroupId = L2_UNFILTERED_TYPE | ((int) port.toLong() & FOUR_NIBBLE_MASK);
GroupBucket l2UnfilteredGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(tBuilder.build());
GroupDescription l2UnfilteredGroupDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l2UnfilteredGroupBucket)), l2UnfilterGroupKey, l2UnfilteredGroupId, nextObj.appId());
log.debug("Trying L2-Unfiltered: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(l2UnfilteredGroupId), l2UnfilterGroupKey, nextObj.id());
groupInfoBuilder.add(new GroupInfo(l2UnfilteredGroupDesc, l2UnfilteredGroupDesc));
});
// Save the current count
int counts = groupInfoBuilder.build().size();
// Lookup each nextId in the store and obtain the group information
nextIds.forEach(nextId -> {
NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextId);
if (nextGroup != null) {
List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(nextGroup.data());
GroupKey topGroupKey = allActiveKeys.get(0).getFirst();
GroupDescription groupDesc = groupService.getGroup(deviceId, topGroupKey);
if (groupDesc != null) {
log.debug("Trying L2-Hash device:{} gid:{}, gkey:{}, nextid:{}", deviceId, Integer.toHexString(((Group) groupDesc).id().id()), topGroupKey, nextId);
groupInfoBuilder.add(new GroupInfo(groupDesc, groupDesc));
} else {
log.error("Not found L2-Hash device:{}, gkey:{}, nextid:{}", deviceId, topGroupKey, nextId);
}
} else {
log.error("Not found NextGroup device:{}, nextid:{}", deviceId, nextId);
}
});
// Compare the size before and after to detect problems during the creation
ImmutableList<GroupInfo> groupInfos = groupInfoBuilder.build();
return (counts + nextIds.size()) == groupInfos.size() ? groupInfos : ImmutableList.of();
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method modifySimpleNextObjective.
/**
* As per the OFDPA 2.0 TTP, packets are sent out of ports by using
* a chain of groups. The simple Next Objective passed in by the application
* is broken up into a group chain. The following chains can be modified
* depending on the parameters in the Next Objective.
* 1. L2 Interface group (no chaining)
* 2. L3 Unicast group -> L2 Interface group
*
* @param nextObj the nextObjective of type SIMPLE
*/
private void modifySimpleNextObjective(NextObjective nextObj, NextGroup nextGroup) {
TrafficTreatment treatment = nextObj.next().iterator().next();
// determine if plain L2 or L3->L2 chain
boolean plainL2 = true;
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
if (l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_DST || l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_SRC || l2ins.subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
plainL2 = false;
}
}
}
if (plainL2) {
modifyBucketInL2Group(nextObj, nextGroup);
} else {
modifyBucketInL3Group(nextObj, nextGroup);
}
return;
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class Ofdpa2Pipeline method getNextMappings.
@Override
public List<String> getNextMappings(NextGroup nextGroup) {
List<String> mappings = new ArrayList<>();
List<Deque<GroupKey>> gkeys = appKryo.deserialize(nextGroup.data());
for (Deque<GroupKey> gkd : gkeys) {
Group lastGroup = null;
StringBuilder gchain = new StringBuilder();
for (GroupKey gk : gkd) {
Group g = groupService.getGroup(deviceId, gk);
if (g == null) {
gchain.append(" NoGrp").append(" -->");
continue;
}
gchain.append(" 0x").append(Integer.toHexString(g.id().id())).append(" -->");
lastGroup = g;
}
// add port information for last group in group-chain
List<Instruction> lastGroupIns = new ArrayList<>();
if (lastGroup != null && !lastGroup.buckets().buckets().isEmpty()) {
lastGroupIns = lastGroup.buckets().buckets().get(0).treatment().allInstructions();
}
for (Instruction i : lastGroupIns) {
if (i instanceof OutputInstruction) {
gchain.append(" port:").append(((OutputInstruction) i).port());
}
}
mappings.add(gchain.toString());
}
return mappings;
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class Ofdpa2Pipeline method processEgress.
/**
* In the OF-DPA 2.0 pipeline, egress forwarding objectives go to the
* egress tables.
* @param fwd the forwarding objective of type 'egress'
* @return a collection of flow rules to be sent to the switch. An empty
* collection may be returned if there is a problem in processing
* the flow rule
*/
protected Collection<FlowRule> processEgress(ForwardingObjective fwd) {
log.debug("Processing egress forwarding objective:{} in dev:{}", fwd, deviceId);
List<FlowRule> rules = new ArrayList<>();
// Build selector
TrafficSelector.Builder sb = DefaultTrafficSelector.builder();
VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) fwd.selector().getCriterion(Criterion.Type.VLAN_VID);
if (vlanIdCriterion == null) {
log.error("Egress forwarding objective:{} must include vlanId", fwd.id());
fail(fwd, ObjectiveError.BADPARAMS);
return rules;
}
Optional<Instruction> outInstr = fwd.treatment().allInstructions().stream().filter(instruction -> instruction instanceof OutputInstruction).findFirst();
if (!outInstr.isPresent()) {
log.error("Egress forwarding objective:{} must include output port", fwd.id());
fail(fwd, ObjectiveError.BADPARAMS);
return rules;
}
PortNumber portNumber = ((OutputInstruction) outInstr.get()).port();
sb.matchVlanId(vlanIdCriterion.vlanId());
OfdpaMatchActsetOutput actsetOutput = new OfdpaMatchActsetOutput(portNumber);
sb.extension(actsetOutput, deviceId);
sb.extension(new OfdpaMatchAllowVlanTranslation(ALLOW_VLAN_TRANSLATION), deviceId);
// Build a flow rule for Egress VLAN Flow table
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
tb.transition(EGRESS_DSCP_PCP_REMARK_FLOW_TABLE);
if (fwd.treatment() != null) {
for (Instruction instr : fwd.treatment().allInstructions()) {
if (instr instanceof L2ModificationInstruction && ((L2ModificationInstruction) instr).subtype() == L2SubType.VLAN_ID) {
tb.immediate().add(instr);
}
if (instr instanceof L2ModificationInstruction && ((L2ModificationInstruction) instr).subtype() == L2SubType.VLAN_PUSH) {
tb.immediate().pushVlan();
EthType ethType = ((L2ModificationInstruction.ModVlanHeaderInstruction) instr).ethernetType();
if (ethType.equals(EtherType.QINQ.ethType())) {
// Build a flow rule for Egress TPID Flow table
TrafficSelector tpidSelector = DefaultTrafficSelector.builder().extension(actsetOutput, deviceId).matchVlanId(VlanId.ANY).build();
TrafficTreatment tpidTreatment = DefaultTrafficTreatment.builder().extension(new Ofdpa3CopyField(COPY_FIELD_NBITS, COPY_FIELD_OFFSET, COPY_FIELD_OFFSET, OXM_ID_VLAN_VID, OXM_ID_PACKET_REG_1), deviceId).popVlan().pushVlan(EtherType.QINQ.ethType()).extension(new Ofdpa3CopyField(COPY_FIELD_NBITS, COPY_FIELD_OFFSET, COPY_FIELD_OFFSET, OXM_ID_PACKET_REG_1, OXM_ID_VLAN_VID), deviceId).build();
FlowRule.Builder tpidRuleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(tpidSelector).withTreatment(tpidTreatment).makePermanent().forTable(EGRESS_TPID_FLOW_TABLE);
rules.add(tpidRuleBuilder.build());
}
}
}
}
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(sb.build()).withTreatment(tb.build()).makePermanent().forTable(EGRESS_VLAN_FLOW_TABLE);
rules.add(ruleBuilder.build());
return rules;
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class Ofdpa3GroupHandler method createUnfilteredL2L3Chain.
// TODO Introduce in the future an inner class to return two treatments
/**
* Internal implementation of createL2L3Chain for L2 unfiltered interface group.
*
* @param treatment that needs to be broken up to create the group chain
* @param nextId of the next objective that needs this group chain
* @param appId of the application that sent this next objective
* @param useSetVlanExtension use the setVlanVid extension that has is_present bit set to 0.
* @return GroupInfo containing the GroupDescription of the
* L2 Unfiltered Interface group(inner) and the GroupDescription of the (outer)
* L3Unicast group. May return null if there is an error in processing the chain.
*/
private GroupInfo createUnfilteredL2L3Chain(TrafficTreatment treatment, int nextId, ApplicationId appId, boolean useSetVlanExtension) {
// for the l2 unfiltered interface group, get port info
// for the l3 unicast group, get the src/dst mac, and vlan info
TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
VlanId vlanId;
long portNum = 0;
MacAddress srcMac;
MacAddress dstMac;
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
switch(l2ins.subtype()) {
case ETH_DST:
dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
outerTtb.setEthDst(dstMac);
break;
case ETH_SRC:
srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
outerTtb.setEthSrc(srcMac);
break;
case VLAN_ID:
vlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
if (useSetVlanExtension) {
OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(vlanId);
outerTtb.extension(ofdpaSetVlanVid, deviceId);
} else {
outerTtb.setVlanId(vlanId);
}
break;
default:
break;
}
} else if (ins.type() == Instruction.Type.OUTPUT) {
portNum = ((Instructions.OutputInstruction) ins).port().toLong();
innerTtb.add(ins);
} else {
log.debug("Driver does not handle this type of TrafficTreatment" + " instruction in l2l3chain: {} - {}", ins.type(), ins);
}
}
innerTtb.extension(new OfdpaSetAllowVlanTranslation(Ofdpa3AllowVlanTranslationType.ALLOW), deviceId);
// assemble information for ofdpa l2 unfiltered interface group
int l2groupId = l2UnfilteredGroupId(portNum);
// a globally unique groupkey that is different for ports in the same device,
// but different for the same portnumber on different devices. Also different
// for the various group-types created out of the same next objective.
int l2gk = l2UnfilteredGroupKey(deviceId, portNum);
final GroupKey l2groupkey = new DefaultGroupKey(Ofdpa3Pipeline.appKryo.serialize(l2gk));
// assemble information for outer group (L3Unicast)
GroupDescription outerGrpDesc;
int l3unicastIndex = getNextAvailableIndex();
int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
final GroupKey l3groupkey = new DefaultGroupKey(Ofdpa3Pipeline.appKryo.serialize(l3unicastIndex));
outerTtb.group(new GroupId(l2groupId));
// create the l3unicast group description to wait for the
// l2 unfiltered interface group to be processed
GroupBucket l3unicastGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
outerGrpDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l3unicastGroupBucket)), l3groupkey, l3groupId, appId);
log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(l3groupId), l3groupkey, nextId);
// store l2groupkey with the groupChainElem for the outer-group that depends on it
GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1, false, deviceId);
updatePendingGroups(l2groupkey, gce);
// create group description for the inner l2 unfiltered interface group
GroupBucket l2InterfaceGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
GroupDescription l2groupDescription = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l2InterfaceGroupBucket)), l2groupkey, l2groupId, appId);
log.debug("Trying L2Unfiltered: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(l2groupId), l2groupkey, nextId);
return new GroupInfo(l2groupDescription, outerGrpDesc);
}
Aggregations