Segment Routing refactor with flow objectives
Change-Id: I0b87f89bb8b18522b9d38bdf5e96f55485b6f1e3
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index c4db26c..2d2102b 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -21,23 +21,25 @@
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.group.DefaultGroupKey;
-import org.onosproject.net.group.Group;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flowobjective.DefaultFilteringObjective;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
@@ -46,7 +48,8 @@
public class RoutingRulePopulator {
- private static final Logger log = LoggerFactory.getLogger(RoutingRulePopulator.class);
+ private static final Logger log = LoggerFactory
+ .getLogger(RoutingRulePopulator.class);
private AtomicLong rulePopulationCounter;
private SegmentRoutingManager srManager;
@@ -77,7 +80,8 @@
}
/**
- * Populates IP flow rules for specific hosts directly connected to the switch.
+ * Populates IP flow rules for specific hosts directly connected to the
+ * switch.
*
* @param deviceId switch ID to set the rules
* @param hostIp host IP address
@@ -99,12 +103,15 @@
TrafficTreatment treatment = tbuilder.build();
TrafficSelector selector = sbuilder.build();
- FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
- srManager.appId, 600, false, FlowRule.Type.IP);
+ ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
+ .builder().fromApp(srManager.appId).makePermanent()
+ .withSelector(selector).withTreatment(treatment)
+ .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC);
- srManager.flowRuleService.applyFlowRules(f);
+ log.debug("Installing IPv4 forwarding objective "
+ + "for host {} in switch {}", hostIp, deviceId);
+ srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add());
rulePopulationCounter.incrementAndGet();
- log.debug("Flow rule {} is set to switch {}", f, deviceId);
}
/**
@@ -116,11 +123,12 @@
* @param nextHops next hop switch ID list
* @return true if all rules are set successfully, false otherwise
*/
- public boolean populateIpRuleForSubnet(DeviceId deviceId, List<Ip4Prefix> subnets,
- DeviceId destSw, Set<DeviceId> nextHops) {
+ public boolean populateIpRuleForSubnet(DeviceId deviceId,
+ List<Ip4Prefix> subnets,
+ DeviceId destSw,
+ Set<DeviceId> nextHops) {
- //List<IpPrefix> subnets = extractSubnet(subnetInfo);
- for (IpPrefix subnet: subnets) {
+ for (IpPrefix subnet : subnets) {
if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) {
return false;
}
@@ -138,8 +146,9 @@
* @param nextHops next hop switch ID list
* @return true if all rules are set successfully, false otherwise
*/
- public boolean populateIpRuleForRouter(DeviceId deviceId, IpPrefix ipPrefix,
- DeviceId destSw, Set<DeviceId> nextHops) {
+ public boolean populateIpRuleForRouter(DeviceId deviceId,
+ IpPrefix ipPrefix, DeviceId destSw,
+ Set<DeviceId> nextHops) {
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
@@ -149,7 +158,8 @@
NeighborSet ns = null;
- //If the next hop is the same as the final destination, then MPLS label is not set.
+ // If the next hop is the same as the final destination, then MPLS label
+ // is not set.
if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) {
tbuilder.decNwTtl();
ns = new NeighborSet(nextHops);
@@ -158,34 +168,28 @@
ns = new NeighborSet(nextHops, config.getSegmentId(destSw));
}
- DefaultGroupKey groupKey = (DefaultGroupKey) srManager.getGroupKey(ns);
- if (groupKey == null) {
- log.warn("Group key is not found for ns {}", ns);
- return false;
- }
- Group group = srManager.groupService.getGroup(deviceId, groupKey);
- if (group != null) {
- tbuilder.group(group.id());
- } else {
- log.warn("No group found for NeighborSet {} from {} to {}",
- ns, deviceId, destSw);
- return false;
- }
-
TrafficTreatment treatment = tbuilder.build();
TrafficSelector selector = sbuilder.build();
- FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
- srManager.appId, 600, false, FlowRule.Type.IP);
-
- srManager.flowRuleService.applyFlowRules(f);
+ ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
+ .builder()
+ .fromApp(srManager.appId)
+ .makePermanent()
+ .nextStep(srManager.getNextObjectiveId(deviceId, ns))
+ .withTreatment(treatment)
+ .withSelector(selector)
+ .withPriority(100)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC);
+ log.debug("Installing IPv4 forwarding objective "
+ + "for router IP/subnet {} in switch {}",
+ ipPrefix,
+ deviceId);
+ srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add());
rulePopulationCounter.incrementAndGet();
- log.debug("IP flow rule {} is set to switch {}", f, deviceId);
return true;
}
-
/**
* Populates MPLS flow rules to all transit routers.
*
@@ -194,35 +198,53 @@
* @param nextHops next hops switch ID list
* @return true if all rules are set successfully, false otherwise
*/
- public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId, Set<DeviceId> nextHops) {
+ public boolean populateMplsRule(DeviceId deviceId, DeviceId destSwId,
+ Set<DeviceId> nextHops) {
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- Collection<TrafficTreatment> treatments = new ArrayList<>();
+ List<ForwardingObjective.Builder> fwdObjBuilders = new ArrayList<ForwardingObjective.Builder>();
// TODO Handle the case of Bos == false
sbuilder.matchMplsLabel(MplsLabel.mplsLabel(config.getSegmentId(destSwId)));
sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
- //If the next hop is the destination router, do PHP
+ // If the next hop is the destination router, do PHP
if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
- TrafficTreatment treatmentBos =
- getMplsTreatment(deviceId, destSwId, nextHops, true, true);
- TrafficTreatment treatment =
- getMplsTreatment(deviceId, destSwId, nextHops, true, false);
- if (treatmentBos != null) {
- treatments.add(treatmentBos);
+ ForwardingObjective.Builder fwdObjBosBuilder =
+ getMplsForwardingObjective(deviceId,
+ destSwId,
+ nextHops,
+ true,
+ true);
+ // TODO: Check with Sangho on why we need this
+ ForwardingObjective.Builder fwdObjNoBosBuilder =
+ getMplsForwardingObjective(deviceId,
+ destSwId,
+ nextHops,
+ true,
+ false);
+ if (fwdObjBosBuilder != null) {
+ fwdObjBuilders.add(fwdObjBosBuilder);
} else {
log.warn("Failed to set MPLS rules.");
return false;
}
} else {
- TrafficTreatment treatmentBos =
- getMplsTreatment(deviceId, destSwId, nextHops, false, true);
- TrafficTreatment treatment =
- getMplsTreatment(deviceId, destSwId, nextHops, false, false);
-
- if (treatmentBos != null) {
- treatments.add(treatmentBos);
+ ForwardingObjective.Builder fwdObjBosBuilder =
+ getMplsForwardingObjective(deviceId,
+ destSwId,
+ nextHops,
+ false,
+ true);
+ // TODO: Check with Sangho on why we need this
+ ForwardingObjective.Builder fwdObjNoBosBuilder =
+ getMplsForwardingObjective(deviceId,
+ destSwId,
+ nextHops,
+ false,
+ false);
+ if (fwdObjBosBuilder != null) {
+ fwdObjBuilders.add(fwdObjBosBuilder);
} else {
log.warn("Failed to set MPLS rules.");
return false;
@@ -230,34 +252,42 @@
}
TrafficSelector selector = sbuilder.build();
- for (TrafficTreatment treatment: treatments) {
- FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
- srManager.appId, 600, false, FlowRule.Type.MPLS);
- srManager.flowRuleService.applyFlowRules(f);
+ for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
+ ((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId)
+ .makePermanent()).withSelector(selector)
+ .withPriority(100))
+ .withFlag(ForwardingObjective.Flag.SPECIFIC);
+ log.debug("Installing MPLS forwarding objective in switch {}",
+ deviceId);
+ srManager.flowObjectiveService.forward(deviceId,
+ fwdObjBuilder.add());
rulePopulationCounter.incrementAndGet();
- log.debug("MPLS rule {} is set to {}", f, deviceId);
}
return true;
}
+ private ForwardingObjective.Builder getMplsForwardingObjective(DeviceId deviceId,
+ DeviceId destSw,
+ Set<DeviceId> nextHops,
+ boolean phpRequired,
+ boolean isBos) {
- private TrafficTreatment getMplsTreatment(DeviceId deviceId, DeviceId destSw,
- Set<DeviceId> nextHops,
- boolean phpRequired, boolean isBos) {
+ ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
+ .builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
if (phpRequired) {
+ log.debug("getMplsForwardingObjective: php required");
tbuilder.copyTtlIn();
if (isBos) {
- tbuilder.popMpls(Ethernet.TYPE_IPV4)
- .decNwTtl();
+ tbuilder.popMpls(Ethernet.TYPE_IPV4).decNwTtl();
} else {
- tbuilder.popMpls(Ethernet.MPLS_UNICAST)
- .decMplsTtl();
+ tbuilder.popMpls(Ethernet.MPLS_UNICAST).decMplsTtl();
}
} else {
+ log.debug("getMplsForwardingObjective: php not required");
tbuilder.decMplsTtl();
}
@@ -271,24 +301,14 @@
tbuilder.setEthSrc(config.getDeviceMac(deviceId))
.setEthDst(config.getDeviceMac(nextHop))
.setOutput(link.src().port());
+ fwdBuilder.withTreatment(tbuilder.build());
} else {
NeighborSet ns = new NeighborSet(nextHops);
- DefaultGroupKey groupKey = (DefaultGroupKey) srManager.getGroupKey(ns);
- if (groupKey == null) {
- log.warn("Group key is not found for ns {}", ns);
- return null;
- }
- Group group = srManager.groupService.getGroup(deviceId, groupKey);
- if (group != null) {
- tbuilder.group(group.id());
- } else {
- log.warn("No group found for ns {} key {} in {}", ns,
- srManager.getGroupKey(ns), deviceId);
- return null;
- }
+ fwdBuilder.nextStep(srManager
+ .getNextObjectiveId(deviceId, ns));
}
- return tbuilder.build();
+ return fwdBuilder;
}
private boolean isECMPSupportedInTransitRouter() {
@@ -298,109 +318,41 @@
}
/**
- * Populates VLAN flows rules.
- * All packets are forwarded to TMAC table.
+ * Populates VLAN flows rules. All packets are forwarded to TMAC table.
*
* @param deviceId switch ID to set the rules
*/
public void populateTableVlan(DeviceId deviceId) {
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-
- tbuilder.transition(FlowRule.Type.ETHER);
-
- TrafficTreatment treatment = tbuilder.build();
- TrafficSelector selector = sbuilder.build();
-
- FlowRule f = new DefaultFlowRule(deviceId, selector, treatment, 100,
- srManager.appId, 600, false, FlowRule.Type.VLAN);
-
- srManager.flowRuleService.applyFlowRules(f);
-
- log.debug("Vlan flow rule {} is set to switch {}", f, deviceId);
+ FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
+ fob.withKey(Criteria.matchInPort(PortNumber.ALL))
+ .addCondition(Criteria.matchVlanId(VlanId.NONE));
+ fob.permit().fromApp(srManager.appId);
+ log.debug("populateTableVlan: Installing filtering objective for untagged packets");
+ srManager.flowObjectiveService.filter(deviceId, fob.add());
}
/**
- * Populates TMAC table rules.
- * IP packets are forwarded to IP table.
- * MPLS packets are forwarded to MPLS table.
+ * Populates TMAC table rules. IP packets are forwarded to IP table. MPLS
+ * packets are forwarded to MPLS table.
*
* @param deviceId switch ID to set the rules
*/
public void populateTableTMac(DeviceId deviceId) {
- // flow rule for IP packets
- TrafficSelector selectorIp = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchEthDst(config.getDeviceMac(deviceId))
- .build();
- TrafficTreatment treatmentIp = DefaultTrafficTreatment.builder()
- .transition(FlowRule.Type.IP)
- .build();
-
- FlowRule flowIp = new DefaultFlowRule(deviceId, selectorIp, treatmentIp, 100,
- srManager.appId, 600, false, FlowRule.Type.ETHER);
-
- srManager.flowRuleService.applyFlowRules(flowIp);
-
- // flow rule for MPLS packets
- TrafficSelector selectorMpls = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.MPLS_UNICAST)
- .matchEthDst(config.getDeviceMac(deviceId))
- .build();
- TrafficTreatment treatmentMpls = DefaultTrafficTreatment.builder()
- .transition(FlowRule.Type.MPLS)
- .build();
-
- FlowRule flowMpls = new DefaultFlowRule(deviceId, selectorMpls, treatmentMpls, 100,
- srManager.appId, 600, false, FlowRule.Type.ETHER);
-
- srManager.flowRuleService.applyFlowRules(flowMpls);
-
- }
-
- /**
- * Populates a table miss entry.
- *
- * @param deviceId switch ID to set rules
- * @param tableToAdd table to set the rules
- * @param toControllerNow flag to send packets to controller immediately
- * @param toControllerWrite flag to send packets to controller at the end of pipeline
- * @param toTable flag to send packets to a specific table
- * @param tableToSend table type to send packets when the toTable flag is set
- */
- public void populateTableMissEntry(DeviceId deviceId, FlowRule.Type tableToAdd, boolean toControllerNow,
- boolean toControllerWrite,
- boolean toTable, FlowRule.Type tableToSend) {
- // TODO: Change arguments to EnumSet
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .build();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- if (toControllerNow) {
- tBuilder.setOutput(PortNumber.CONTROLLER);
- }
-
- if (toControllerWrite) {
- tBuilder.deferred().setOutput(PortNumber.CONTROLLER);
- }
-
- if (toTable) {
- tBuilder.transition(tableToSend);
- }
-
- FlowRule flow = new DefaultFlowRule(deviceId, selector, tBuilder.build(), 0,
- srManager.appId, 600, false, tableToAdd);
-
- srManager.flowRuleService.applyFlowRules(flow);
-
+ FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
+ fob.withKey(Criteria.matchInPort(PortNumber.ALL))
+ .addCondition(Criteria.matchEthDst(config
+ .getDeviceMac(deviceId)));
+ fob.permit().fromApp(srManager.appId);
+ log.debug("populateTableVlan: Installing filtering objective for router mac");
+ srManager.flowObjectiveService.filter(deviceId, fob.add());
}
private Link selectOneLink(DeviceId srcId, Set<DeviceId> destIds) {
Set<Link> links = srManager.linkService.getDeviceEgressLinks(srcId);
DeviceId destId = (DeviceId) destIds.toArray()[0];
- for (Link link: links) {
+ for (Link link : links) {
if (link.dst().deviceId().equals(destId)) {
return link;
}