CORD-349 Support VLAN cross-connect traffic
Change related to this topic:
- Support VLAN cross-connect traffic
Utilize ports subjectClass to achieve. For non-xConnect port, set interface VLAN to -1
- Remove VLAN checking since we have multiple VLANs per port
- Hash the L2 interface group key generation to include VLAN as well
- Update the network-cfg.json sample
Other refactoring changes:
- Read next objective stores from srManager directly
- Use constant for flow priority
- CORD-267 Javadoc fix
Change-Id: I4ca8c2d9c8b3633a4a0101c5070d19343f7e5b90
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 03b29a5..6017e8b 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -23,6 +23,7 @@
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
@@ -49,11 +50,15 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import static com.google.common.base.Preconditions.checkNotNull;
+/**
+ * Populator of segment routing flow rules.
+ */
public class RoutingRulePopulator {
private static final Logger log = LoggerFactory
.getLogger(RoutingRulePopulator.class);
@@ -63,6 +68,10 @@
private DeviceConfiguration config;
private static final int HIGHEST_PRIORITY = 0xffff;
+ //
+ private static final int XCONNECT_PRIORITY = 1000;
+ private static final int DEFAULT_PRIORITY = 100;
+ private static final int FLOOD_PRIORITY = 5;
private static final long OFPP_MAX = 0xffffff00L;
@@ -120,6 +129,14 @@
rulePopulationCounter.incrementAndGet();
}
+ /**
+ * Removes IP rules for host when the host is gone.
+ *
+ * @param deviceId device ID of the device that host attaches to
+ * @param hostIp IP address of the host
+ * @param hostMac MAC address of the host
+ * @param outPort port that host attaches to
+ */
public void revokeIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
MacAddress hostMac, PortNumber outPort) {
log.debug("Revoke IP table entry for host {} at {}:{}",
@@ -175,7 +192,7 @@
.withSelector(selector)
.nextStep(portNextObjId)
.fromApp(srManager.appId).makePermanent()
- .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC);
+ .withPriority(DEFAULT_PRIORITY).withFlag(ForwardingObjective.Flag.SPECIFIC);
}
/**
@@ -369,7 +386,7 @@
for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId)
.makePermanent()).withSelector(selector)
- .withPriority(100))
+ .withPriority(DEFAULT_PRIORITY))
.withFlag(ForwardingObjective.Flag.SPECIFIC);
srManager.flowObjectiveService.
forward(deviceId,
@@ -464,7 +481,8 @@
FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
fob.withKey(Criteria.matchInPort(port.number()))
.addCondition(Criteria.matchEthDst(deviceMac))
- .addCondition(Criteria.matchVlanId(VlanId.NONE));
+ .addCondition(Criteria.matchVlanId(VlanId.NONE))
+ .withPriority(DEFAULT_PRIORITY);
// vlan assignment is valid only if this instance is master
if (srManager.mastershipService.isLocalMaster(deviceId)) {
TrafficTreatment tt = DefaultTrafficTreatment.builder()
@@ -558,7 +576,7 @@
fob.withFlag(Flag.SPECIFIC)
.withSelector(sbuilder.build())
.nextStep(nextId)
- .withPriority(5)
+ .withPriority(FLOOD_PRIORITY)
.fromApp(srManager.appId)
.makePermanent();
@@ -572,6 +590,86 @@
});
}
+ /**
+ * Creates a filtering objective to permit VLAN cross-connect traffic.
+ *
+ * @param deviceId the DPID of the switch
+ */
+ public void populateXConnectVlanFilters(DeviceId deviceId) {
+ Map<VlanId, List<ConnectPoint>> xConnectsForDevice =
+ config.getXConnects();
+ xConnectsForDevice.forEach((vlanId, connectPoints) -> {
+ // Only proceed the xConnect for given device
+ for (ConnectPoint connectPoint : connectPoints) {
+ if (!connectPoint.deviceId().equals(deviceId)) {
+ return;
+ }
+ }
+
+ connectPoints.forEach(connectPoint -> {
+ FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
+ fob.withKey(Criteria.matchInPort(connectPoint.port()))
+ .addCondition(Criteria.matchVlanId(vlanId))
+ .addCondition(Criteria.matchEthDst(MacAddress.NONE))
+ .withPriority(XCONNECT_PRIORITY);
+
+ fob.permit().fromApp(srManager.appId);
+ srManager.flowObjectiveService
+ .filter(deviceId, fob.add(new SRObjectiveContext(deviceId,
+ SRObjectiveContext.ObjectiveType.FILTER)));
+ });
+ });
+ }
+
+ /**
+ * Populates a forwarding objective that points the VLAN cross-connect
+ * packets to a broadcast group.
+ *
+ * @param deviceId switch ID to set the rules
+ */
+ public void populateXConnectBroadcastRule(DeviceId deviceId) {
+ Map<VlanId, List<ConnectPoint>> xConnects =
+ config.getXConnects();
+ xConnects.forEach((vlanId, connectPoints) -> {
+ // Only proceed the xConnect for given device
+ for (ConnectPoint connectPoint : connectPoints) {
+ if (!connectPoint.deviceId().equals(deviceId)) {
+ return;
+ }
+ }
+
+ int nextId = srManager.getXConnectNextObjectiveId(deviceId, vlanId);
+ if (nextId < 0) {
+ log.error("Cannot install cross-connect broadcast rule in dev:{} " +
+ "due to missing nextId:{}", deviceId, nextId);
+ return;
+ }
+
+ /*
+ * Driver should treat objectives with MacAddress.NONE and !VlanId.NONE
+ * as the VLAN cross-connect broadcast rules
+ */
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ sbuilder.matchVlanId(vlanId);
+ sbuilder.matchEthDst(MacAddress.NONE);
+
+ ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
+ fob.withFlag(Flag.SPECIFIC)
+ .withSelector(sbuilder.build())
+ .nextStep(nextId)
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(srManager.appId)
+ .makePermanent();
+
+ srManager.flowObjectiveService.forward(
+ deviceId,
+ fob.add(new SRObjectiveContext(
+ deviceId,
+ SRObjectiveContext.ObjectiveType.FORWARDING)
+ )
+ );
+ });
+ }
private static class SRObjectiveContext implements ObjectiveContext {
enum ObjectiveType {