use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class OfdpaPipelineTraceable method handleOutputFlows.
// Handles output flows
private List<FlowEntry> handleOutputFlows(TrafficSelector currentPacket, List<FlowEntry> outputFlows, TrafficSelector.Builder egressPacket, List<PortNumber> outputPorts, PipelineTraceableHitChain currentHitChain, PipelineTraceableOutput.Builder outputBuilder, TrafficSelector initialPacket) {
// TODO optimization
// outputFlows contains also last rule of device, so we need filtering for OUTPUT instructions.
List<FlowEntry> outputFlowEntries = outputFlows.stream().filter(flow -> flow.treatment().allInstructions().stream().filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT)).count() > 0).collect(Collectors.toList());
if (outputFlowEntries.size() > 1) {
outputBuilder.appendToLog("More than one flow rule with OUTPUT instruction");
log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", currentPacket);
}
if (outputFlowEntries.size() == 1) {
OutputInstruction outputInstruction = (OutputInstruction) outputFlowEntries.get(0).treatment().allInstructions().stream().filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT)).findFirst().get();
buildOutputFromDevice(egressPacket, outputPorts, outputInstruction, currentHitChain, outputBuilder, initialPacket, false);
}
return outputFlowEntries;
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class OfdpaPipelineTraceable method isDropped.
private boolean isDropped(GroupId groupId, GroupBucket bucket, ConnectPoint ingressPort) {
log.debug("Verify if the packet has to be dropped by the input port {}", ingressPort);
// if It is not a l2 flood group and l2/l3 mcast skip
int maskedId = groupId.id() & 0xF0000000;
if (maskedId != L2_FLOOD_TYPE && maskedId != L2_MULTICAST_TYPE && maskedId != L3_MULTICAST_TYPE) {
return false;
}
// Verify if the bucket points to the ingress port
Instructions.GroupInstruction groupInstruction;
for (Instruction instr : bucket.treatment().allInstructions()) {
if (instr.type().equals(Instruction.Type.GROUP)) {
groupInstruction = (Instructions.GroupInstruction) instr;
// FIXME According to the OFDPA spec for L3 MCAST if the VLAN is changed packet is not dropped
if ((groupInstruction.groupId().id() & 0xF0000000) == L2_INTERFACE_TYPE) {
return (groupInstruction.groupId().id() & 0x0000FFFF) == ingressPort.port().toLong();
}
}
}
return false;
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class OfdpaPipelineTraceable method handleOfdpa27FixedTable.
// Handles table 27 in Ofpda which is a fixed table not visible to any controller that handles Mpls Labels.
private TrafficSelector handleOfdpa27FixedTable(TrafficSelector initialPacket, TrafficSelector packet) {
log.debug("Handling table 27 on OFDPA, removing mpls ETH Type and change mpls label");
Criterion mplsCriterion = packet.getCriterion(Criterion.Type.ETH_TYPE);
// T3 was using the initial packet of the trace - using the metadata in the packet to carry this info
Criterion metadataCriterion = initialPacket.getCriterion(Criterion.Type.METADATA);
ImmutableList.Builder<Instruction> builder = ImmutableList.builder();
// If the packet comes in with the expected elements we update it as per OFDPA spec.
if (mplsCriterion != null && ((EthTypeCriterion) mplsCriterion).ethType().equals(EthType.EtherType.MPLS_UNICAST.ethType()) && metadataCriterion != null) {
// Get the metadata to restore the original ethertype
long ethType = ((MetadataCriterion) metadataCriterion).metadata();
// TODO update with parsing with eth MPLS pop Instruction for treating label an bos
Instruction ethInstruction = Instructions.popMpls(EthType.EtherType.lookup((short) ethType).ethType());
// FIXME what do we use as L3_Unicast mpls Label ?
// translateInstruction(builder, ethInstruction);
builder.add(ethInstruction);
// Filtering out metadata
TrafficSelector.Builder currentPacketBuilder = DefaultTrafficSelector.builder();
packet.criteria().stream().filter(criterion -> criterion.type() != Criterion.Type.METADATA).forEach(currentPacketBuilder::add);
packet = currentPacketBuilder.build();
}
packet = updatePacket(packet, builder.build()).build();
return packet;
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class OfdpaPipelineTraceable method getGroupsFromInstructions.
// Gets group information from instructions.
private void getGroupsFromInstructions(Map<GroupId, Group> groups, List<Instruction> instructions, TrafficSelector.Builder egressPacket, List<PortNumber> outputPorts, PipelineTraceableHitChain currentHitChain, PipelineTraceableOutput.Builder outputBuilder, PipelineTraceableInput input, boolean dropped) {
List<Instruction> groupInstructionlist = new ArrayList<>();
// sort instructions according to priority (larger Instruction.Type ENUM constant first)
// which enables to treat other actions before the OUTPUT action
// TODO improve the priority scheme according to the OpenFlow ActionSet spec
List<Instruction> instructionsSorted = new ArrayList<>();
instructionsSorted.addAll(instructions);
instructionsSorted.sort((instr1, instr2) -> Integer.compare(instr2.type().ordinal(), instr1.type().ordinal()));
// Handles first all non-group instructions
for (Instruction instruction : instructionsSorted) {
log.debug("Considering Instruction {}", instruction);
// to the possible outputs for this packet
if (!instruction.type().equals(Instruction.Type.GROUP)) {
// or add the output to the possible outputs for this packet
if (instruction.type().equals(Instruction.Type.OUTPUT)) {
buildOutputFromDevice(egressPacket, outputPorts, (OutputInstruction) instruction, currentHitChain, outputBuilder, input.ingressPacket().packet(), dropped);
} else {
egressPacket = translateInstruction(egressPacket, instruction);
}
} else {
// Store for later if the instruction is pointing to a group
groupInstructionlist.add(instruction);
}
}
// handle all the internal instructions pointing to a group.
for (Instruction instr : groupInstructionlist) {
Instructions.GroupInstruction groupInstruction = (Instructions.GroupInstruction) instr;
Group group = groups.get(groupInstruction.groupId());
// group does not exist in the dataplane
if (group == null) {
currentHitChain.setEgressPacket(new PipelineTraceablePacket(egressPacket.build()));
currentHitChain.dropped();
outputBuilder.appendToLog("Null group for Instruction " + instr).noGroups().addHitChain(currentHitChain);
break;
}
log.debug("Analyzing group {}", group.id());
// group is there but there are no members/buckets
if (group.buckets().buckets().size() == 0) {
// add the group to the traversed groups
currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));
currentHitChain.setEgressPacket(new PipelineTraceablePacket(egressPacket.build()));
currentHitChain.dropped();
outputBuilder.appendToLog("Group " + group.id() + " has no buckets").noMembers().addHitChain(currentHitChain);
break;
}
PipelineTraceableHitChain newHitChain;
TrafficSelector.Builder newEgressPacket;
// Cycle in each of the group's buckets and add them to the groups for this Device.
for (GroupBucket bucket : group.buckets().buckets()) {
// add the group to the traversed groups
currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));
// Go to the next step - using a copy of the egress packet and of the hit chain
newHitChain = PipelineTraceableHitChain.emptyHitChain();
currentHitChain.hitChain().forEach(newHitChain::addDataPlaneEntity);
newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
getGroupsFromInstructions(groups, bucket.treatment().allInstructions(), newEgressPacket, outputPorts, newHitChain, outputBuilder, input, dropped | isDropped(group.id(), bucket, input.ingressPort()));
}
}
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method createL2L3ChainInternal.
/**
* Internal implementation of createL2L3Chain.
* <p>
* The is_present bit in set_vlan_vid action is required to be 0 in OFDPA i12.
* Since it is non-OF spec, we need an extension treatment for that.
* The useSetVlanExtension must be set to false for OFDPA i12.
* </p>
*
* @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 mpls determines if L3Unicast or MPLSInterface group is created
* @param meta metadata passed in by the application as part of the nextObjective
* @param useSetVlanExtension use the setVlanVid extension that has is_present bit set to 0.
* @return GroupInfo containing the GroupDescription of the
* L2Interface group(inner) and the GroupDescription of the (outer)
* L3Unicast/MPLSInterface group. May return null if there is an
* error in processing the chain
*/
protected GroupInfo createL2L3ChainInternal(TrafficTreatment treatment, int nextId, ApplicationId appId, boolean mpls, TrafficSelector meta, boolean useSetVlanExtension) {
// for the l2interface group, get vlan and port info
// for the outer group, get the src/dst mac, and vlan info
TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
VlanId vlanid = null;
long portNum = 0;
boolean setVlan = false, popVlan = false;
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);
}
setVlan = true;
break;
case VLAN_POP:
innerTtb.popVlan();
popVlan = true;
break;
case DEC_MPLS_TTL:
case MPLS_LABEL:
case MPLS_POP:
case MPLS_PUSH:
case VLAN_PCP:
case VLAN_PUSH:
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);
}
}
if (vlanid == null && meta != null) {
// use metadata if available
Criterion vidCriterion = meta.getCriterion(VLAN_VID);
if (vidCriterion != null) {
vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
}
// if vlan is not set, use the vlan in metadata for outerTtb
if (vlanid != null && !setVlan) {
if (useSetVlanExtension) {
OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(vlanid);
outerTtb.extension(ofdpaSetVlanVid, deviceId);
} else {
outerTtb.setVlanId(vlanid);
}
}
}
if (vlanid == null) {
log.error("Driver cannot process an L2/L3 group chain without " + "egress vlan information for dev: {} port:{}", deviceId, portNum);
return null;
}
if (!setVlan && !popVlan) {
// untagged outgoing port
TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder();
temp.popVlan();
innerTtb.build().allInstructions().forEach(temp::add);
innerTtb = temp;
}
// assemble information for ofdpa l2interface group
int l2groupId = l2GroupId(vlanid, 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 = l2InterfaceGroupKey(deviceId, vlanid, portNum);
final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
// assemble information for outer group
GroupDescription outerGrpDesc;
if (mpls) {
// outer group is MPLS Interface
int mplsInterfaceIndex = getNextAvailableIndex();
int mplsGroupId = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & mplsInterfaceIndex);
final GroupKey mplsGroupKey = new DefaultGroupKey(appKryo.serialize(mplsInterfaceIndex));
outerTtb.group(new GroupId(l2groupId));
// create the mpls-interface group description to wait for the
// l2 interface group to be processed
GroupBucket mplsinterfaceGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
outerGrpDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(mplsinterfaceGroupBucket)), mplsGroupKey, mplsGroupId, appId);
log.debug("Trying MPLS-Interface: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(mplsGroupId), mplsGroupKey, nextId);
} else {
// outer group is L3Unicast
int l3unicastIndex = getNextAvailableIndex();
int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3unicastIndex));
outerTtb.group(new GroupId(l2groupId));
// create the l3unicast group description to wait for the
// l2 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 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 L2Interface: device:{} gid:{} gkey:{} nextId:{}", deviceId, Integer.toHexString(l2groupId), l2groupkey, nextId);
return new GroupInfo(l2groupDescription, outerGrpDesc);
}
Aggregations