use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class OvsOfdpaGroupHandler method createL2L3Chain.
@Override
protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId, ApplicationId appId, boolean mpls, TrafficSelector meta) {
if (createUnfiltered(treatment, meta)) {
return createUnfilteredL2L3Chain(treatment, nextId, appId);
}
// 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.ZERO;
MacAddress dstMac = MacAddress.ZERO;
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();
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(Criterion.Type.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) {
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(i -> temp.add(i));
innerTtb = temp;
}
// assemble information for ofdpa l2interface group
int l2groupId = L2_INTERFACE_TYPE | (vlanid.toShort() << 16) | (int) 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(Ofdpa2Pipeline.appKryo.serialize(l2gk));
// assemble information for outer group
GroupDescription outerGrpDesc = null;
if (mpls) {
// outer group is MPLSInteface
int mplsInterfaceIndex = getNextAvailableIndex();
int mplsgroupId = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & mplsInterfaceIndex);
final GroupKey mplsgroupkey = new DefaultGroupKey(Ofdpa2Pipeline.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(Ofdpa2Pipeline.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 l2interfacegroup
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);
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class OvsOfdpaGroupHandler method createUnfilteredL2L3Chain.
/**
* Internal implementation of createL2L3Chain to handle double-tagged vlan.
* L3UG Group carries dummyVlanId and output port information in its groupId,
* and does not set vlan.
* L2UG Group only has OUTPUT instruction.
*
* @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
* @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) {
// 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 = VlanId.NONE;
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();
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);
}
}
// 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(Ofdpa2Pipeline.appKryo.serialize(l2gk));
// assemble information for outer group (L3Unicast)
GroupDescription outerGrpDesc;
int l3groupId = doubleVlanL3UnicastGroupId(vlanId, portNum);
final GroupKey l3groupkey = new DefaultGroupKey(Ofdpa3Pipeline.appKryo.serialize(doubleVlanL3UnicastGroupKey(deviceId, vlanId, portNum)));
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
OfdpaGroupHandlerUtility.GroupChainElem gce = new OfdpaGroupHandlerUtility.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 OfdpaGroupHandlerUtility.GroupInfo(l2groupDescription, outerGrpDesc);
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class SpringOpenTTP method processEthDstSpecificObjective.
protected Collection<FlowRule> processEthDstSpecificObjective(ForwardingObjective fwd) {
List<FlowRule> rules = new ArrayList<>();
// Build filtered selector
TrafficSelector selector = fwd.selector();
EthCriterion ethCriterion = (EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST);
VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID);
TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder();
// Do not match MacAddress for subnet broadcast entry
if (!ethCriterion.mac().equals(MacAddress.NONE)) {
filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
log.debug("processing L2 forwarding objective:{} in dev:{}", fwd.id(), deviceId);
} else {
log.debug("processing L2 Broadcast forwarding objective:{} " + "in dev:{} for vlan:{}", fwd.id(), deviceId, vlanIdCriterion.vlanId());
}
filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
TrafficSelector filteredSelector = filteredSelectorBuilder.build();
// Build filtered treatment
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (fwd.treatment() != null) {
treatmentBuilder.deferred();
fwd.treatment().allInstructions().forEach(treatmentBuilder::add);
}
if (fwd.nextId() != null) {
NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
if (next != null) {
SpringOpenGroup soGrp = appKryo.deserialize(next.data());
if (soGrp.dummy) {
log.debug("Adding {} flow-actions for fwd. obj. {} " + "in dev: {}", soGrp.treatment.allInstructions().size(), fwd.id(), deviceId);
for (Instruction ins : soGrp.treatment.allInstructions()) {
treatmentBuilder.deferred().add(ins);
}
} else {
GroupKey key = soGrp.key;
Group group = groupService.getGroup(deviceId, key);
if (group == null) {
log.warn("The group left!");
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
treatmentBuilder.deferred().group(group.id());
log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} " + "in dev: {}", group.id(), fwd.id(), deviceId);
}
}
}
treatmentBuilder.immediate().transition(aclTableId);
TrafficTreatment filteredTreatment = treatmentBuilder.build();
// Build bridging table entries
FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
flowRuleBuilder.fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector).withTreatment(filteredTreatment).forTable(dstMacTableId);
if (fwd.permanent()) {
flowRuleBuilder.makePermanent();
} else {
flowRuleBuilder.makeTemporary(fwd.timeout());
}
rules.add(flowRuleBuilder.build());
return rules;
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class SpringOpenTTP method processFilter.
private void processFilter(FilteringObjective filt, boolean install, ApplicationId applicationId) {
// ports as the key
if (filt.key().equals(Criteria.dummy()) || filt.key().type() != Criterion.Type.IN_PORT) {
log.warn("No key defined in filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filt, ObjectiveError.UNKNOWN);
return;
}
EthCriterion ethCriterion = null;
VlanIdCriterion vlanIdCriterion = null;
// convert filtering conditions for switch-intfs into flowrules
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
for (Criterion criterion : filt.conditions()) {
if (criterion.type() == Criterion.Type.ETH_DST) {
ethCriterion = (EthCriterion) criterion;
} else if (criterion.type() == Criterion.Type.VLAN_VID) {
vlanIdCriterion = (VlanIdCriterion) criterion;
} else if (criterion.type() == Criterion.Type.IPV4_DST) {
log.debug("driver does not process IP filtering rules as it " + "sends all misses in the IP table to the controller");
} else {
log.warn("Driver does not currently process filtering condition" + " of type: {}", criterion.type());
fail(filt, ObjectiveError.UNSUPPORTED);
}
}
VlanId assignedVlan = null;
VlanId modifiedVlan = null;
VlanId pushedVlan = null;
boolean pushVlan = false;
boolean popVlan = false;
if (vlanIdCriterion != null) {
if (filt.meta() != null) {
for (Instruction i : filt.meta().allInstructions()) {
if (i instanceof L2ModificationInstruction) {
if (((L2ModificationInstruction) i).subtype().equals(L2ModificationInstruction.L2SubType.VLAN_PUSH)) {
pushVlan = true;
} else if (((L2ModificationInstruction) i).subtype().equals(L2ModificationInstruction.L2SubType.VLAN_POP)) {
if (modifiedVlan != null) {
log.error("Pop tag is not allowed after modify VLAN operation " + "in filtering objective", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
popVlan = true;
}
}
if (i instanceof ModVlanIdInstruction) {
if (pushVlan && vlanIdCriterion.vlanId() != VlanId.NONE) {
// Modify VLAN should not appear after pushing a new tag
if (pushedVlan != null) {
log.error("Modify VLAN not allowed after push tag operation " + "in filtering objective", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
pushedVlan = ((ModVlanIdInstruction) i).vlanId();
} else if (vlanIdCriterion.vlanId() == VlanId.NONE) {
// For untagged packets the pushed VLAN ID will be saved in assignedVlan
// just to ensure the driver works as designed for the fabric use case
assignedVlan = ((ModVlanIdInstruction) i).vlanId();
} else {
// For tagged packets modifiedVlan will contain the modified value of existing tag
if (modifiedVlan != null) {
log.error("Driver does not allow multiple modify VLAN operations " + "in the same filtering objective", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
modifiedVlan = ((ModVlanIdInstruction) i).vlanId();
}
}
}
}
// For VLAN cross-connect packets, use the configured VLAN unless there is an explicitly provided VLAN ID
if (vlanIdCriterion.vlanId() != VlanId.NONE) {
if (assignedVlan == null) {
assignedVlan = vlanIdCriterion.vlanId();
}
// For untagged packets, assign a VLAN ID
} else {
if (filt.meta() == null) {
log.error("Missing metadata in filtering objective required " + "for vlan assignment in dev {}", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
if (assignedVlan == null) {
log.error("Driver requires an assigned vlan-id to tag incoming " + "untagged packets. Not processing vlan filters on " + "device {}", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
}
if (pushVlan && popVlan) {
log.error("Cannot push and pop vlan in the same filtering objective");
fail(filt, ObjectiveError.BADPARAMS);
return;
}
if (popVlan && vlanIdCriterion.vlanId() == VlanId.NONE) {
log.error("Cannot pop vlan for untagged packets");
fail(filt, ObjectiveError.BADPARAMS);
return;
}
if ((pushVlan && pushedVlan == null) && vlanIdCriterion.vlanId() != VlanId.NONE) {
log.error("No VLAN ID provided for push tag operation");
fail(filt, ObjectiveError.BADPARAMS);
return;
}
}
if (ethCriterion == null) {
log.debug("filtering objective missing dstMac, cannot program TMAC table");
} else {
for (FlowRule tmacRule : processEthDstFilter(ethCriterion, vlanIdCriterion, filt, assignedVlan, applicationId)) {
log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}", tmacRule, deviceId);
ops = install ? ops.add(tmacRule) : ops.remove(tmacRule);
}
}
if (vlanIdCriterion == null) {
log.debug("filtering objective missing VLAN ID criterion, " + "cannot program VLAN Table");
} else {
for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion, filt, assignedVlan, modifiedVlan, pushedVlan, pushVlan, popVlan, applicationId)) {
log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", vlanRule, deviceId);
ops = install ? ops.add(vlanRule) : ops.remove(vlanRule);
}
}
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
pass(filt);
log.debug("Provisioned tables in {} with fitering " + "rules", deviceId);
}
@Override
public void onError(FlowRuleOperations ops) {
fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
log.warn("Failed to provision tables in {} with " + "fitering rules", deviceId);
}
}));
}
use of org.onosproject.net.flow.instructions.Instruction in project onos by opennetworkinglab.
the class DefaultVirtualFlowRuleProviderTest method devirtualizeFlowRuleWithoutInPort.
@Test
public void devirtualizeFlowRuleWithoutInPort() {
TrafficSelector ts = DefaultTrafficSelector.builder().build();
TrafficTreatment tr = DefaultTrafficTreatment.builder().setOutput(PORT_NUM2).build();
FlowRule r1 = DefaultFlowRule.builder().forDevice(VDID).withSelector(ts).withTreatment(tr).withPriority(10).fromApp(vAppId).makeTemporary(TIMEOUT).build();
virtualProvider.applyFlowRule(VNET_ID, r1);
assertEquals("3 rules should exist", 3, virtualProvider.flowRuleService.getFlowRuleCount());
FlowRule inFromDID1 = null;
FlowRule inFromDID2 = null;
FlowRule out = null;
Set<FlowEntry> phyRules = new HashSet<>();
for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
phyRules.add(i);
}
for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
phyRules.add(i);
}
for (FlowRule rule : phyRules) {
for (Instruction inst : rule.treatment().allInstructions()) {
if (inst.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction i = (L2ModificationInstruction) inst;
if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
inFromDID1 = rule;
break;
} else {
out = rule;
break;
}
} else {
inFromDID2 = rule;
break;
}
}
}
assertEquals(DID1, inFromDID1.deviceId());
assertEquals(DID2, inFromDID2.deviceId());
assertEquals(DID2, out.deviceId());
}
Aggregations