In this commit: CORD-799
Bug fix for host-update to not remove and add the same IP addr
NPE fix in ofdpa3pipeline
Removing unused code in ofdpa2pipeline
Ability to add or revoke port filters for port-updates
Retry filters retry for a longer time
Bug fix for suppress ports to not suppress filters
Filters now sent only by master instance
Removing the MPLS BOS=0 rules for now until inconsitent hardware behavior is fixed
Change-Id: I8b4ee4af6de263531e0696af86e65f1c502f5f85
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 758e4cc..050bb97 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -509,11 +509,11 @@
fwdObjs.addAll(fwdObjsMpls);
// Generates the transit rules used by the MPLS Pwaas. For now it is
// the only case !BoS supported.
- fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId, routerIp, false);
+ /*fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId, routerIp, false);
if (fwdObjsMpls.isEmpty()) {
return false;
}
- fwdObjs.addAll(fwdObjsMpls);
+ fwdObjs.addAll(fwdObjsMpls);*/
for (ForwardingObjective fwdObj : fwdObjs) {
log.debug("Sending MPLS fwd obj {} for SID {}-> next {} in sw: {}",
@@ -595,9 +595,11 @@
* that need to internally assign vlans to untagged packets, this method
* provides per-subnet vlan-ids as metadata.
* <p>
- * Note that the vlan assignment is only done by the master-instance for a switch.
- * However we send the filtering objective from slave-instances as well, so
- * that drivers can obtain other information (like Router MAC and IP).
+ * Note that the vlan assignment and filter programming should only be done by
+ * the master for a switch. This method is typically called at deviceAdd and
+ * programs filters only for the enabled ports of the device. For port-updates,
+ * that enable/disable ports after device add, singlePortFilter methods should
+ * be called.
*
* @param deviceId the switch dpid for the router
* @return PortFilterInfo information about the processed ports
@@ -606,73 +608,117 @@
log.debug("Installing per-port filtering objective for untagged "
+ "packets in device {}", deviceId);
- MacAddress deviceMac;
- try {
- deviceMac = config.getDeviceMac(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting populateRouterMacVlanFilters.");
- return null;
- }
-
List<Port> devPorts = srManager.deviceService.getPorts(deviceId);
if (devPorts == null || devPorts.isEmpty()) {
log.warn("Device {} ports not available. Unable to add MacVlan filters",
deviceId);
return null;
}
- int disabledPorts = 0, suppressedPorts = 0, filteredPorts = 0;
+ int disabledPorts = 0, errorPorts = 0, filteredPorts = 0;
for (Port port : devPorts) {
- ConnectPoint connectPoint = new ConnectPoint(deviceId, port.number());
- // TODO: Handles dynamic port events when we are ready for dynamic config
if (!port.isEnabled()) {
disabledPorts++;
continue;
}
-
- boolean isSuppressed = false;
- SegmentRoutingAppConfig appConfig = srManager.cfgService
- .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
- if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
- isSuppressed = true;
- suppressedPorts++;
- continue;
+ if (populateSinglePortFilters(deviceId, port.number())) {
+ filteredPorts++;
+ } else {
+ errorPorts++;
}
-
- Ip4Prefix portSubnet = config.getPortIPv4Subnet(deviceId, port.number());
- VlanId assignedVlan = (portSubnet == null || isSuppressed)
- ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
- : srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
-
- if (assignedVlan == null) {
- log.warn("Assigned vlan is null for {} in {} - Aborting populateRouterMacVlanFilters.",
- port.number(), deviceId);
- return null;
- }
-
- FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
- fob.withKey(Criteria.matchInPort(port.number()))
- .addCondition(Criteria.matchEthDst(deviceMac))
- .addCondition(Criteria.matchVlanId(VlanId.NONE))
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
- // vlan assignment is valid only if this instance is master
- if (srManager.mastershipService.isLocalMaster(deviceId)) {
- TrafficTreatment tt = DefaultTrafficTreatment.builder()
- .pushVlan().setVlanId(assignedVlan).build();
- fob.withMeta(tt);
- }
- fob.permit().fromApp(srManager.appId);
- log.debug("Sending filtering objective for dev/port:{}/{}", deviceId, port);
- filteredPorts++;
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Filter for {} populated", connectPoint),
- (objective, error) ->
- log.warn("Failed to populate filter for {}: {}", connectPoint, error));
- srManager.flowObjectiveService.filter(deviceId, fob.add(context));
}
- log.info("Filtering on dev:{}, disabledPorts:{}, suppressedPorts:{}, filteredPorts:{}",
- deviceId, disabledPorts, suppressedPorts, filteredPorts);
+ log.info("Filtering on dev:{}, disabledPorts:{}, errorPorts:{}, filteredPorts:{}",
+ deviceId, disabledPorts, errorPorts, filteredPorts);
return srManager.defaultRoutingHandler.new PortFilterInfo(disabledPorts,
- suppressedPorts, filteredPorts);
+ errorPorts, filteredPorts);
+ }
+
+ /**
+ * Creates filtering objectives for a single port. Should only be called
+ * by the master for a switch.
+ *
+ * @param deviceId device identifier
+ * @param portnum port identifier for port to be filtered
+ * @return true if no errors occurred during the build of the filtering objective
+ */
+ public boolean populateSinglePortFilters(DeviceId deviceId, PortNumber portnum) {
+ FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum);
+ if (fob == null) {
+ // error encountered during build
+ return false;
+ }
+ log.info("Sending filtering objectives for dev/port:{}/{}", deviceId, portnum);
+ ObjectiveContext context = new DefaultObjectiveContext(
+ (objective) -> log.debug("Filter for {}/{} populated", deviceId, portnum),
+ (objective, error) ->
+ log.warn("Failed to populate filter for {}/{}: {}",
+ deviceId, portnum, error));
+ srManager.flowObjectiveService.filter(deviceId, fob.add(context));
+ return true;
+ }
+
+ /**
+ * Removes filtering objectives for a single port. Should only be called
+ * by the master for a switch.
+ *
+ * @param deviceId device identifier
+ * @param portnum port identifier
+ */
+ public void revokeSinglePortFilters(DeviceId deviceId, PortNumber portnum) {
+ FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum);
+ if (fob == null) {
+ // error encountered during build
+ return;
+ }
+ log.info("Removing filtering objectives for dev/port:{}/{}", deviceId, portnum);
+ ObjectiveContext context = new DefaultObjectiveContext(
+ (objective) -> log.debug("Filter for {}/{} removed", deviceId, portnum),
+ (objective, error) ->
+ log.warn("Failed to remove filter for {}/{}: {}",
+ deviceId, portnum, error));
+ srManager.flowObjectiveService.filter(deviceId, fob.remove(context));
+ return;
+ }
+
+
+ private FilteringObjective.Builder buildFilteringObjective(DeviceId deviceId,
+ PortNumber portnum) {
+ MacAddress deviceMac;
+ try {
+ deviceMac = config.getDeviceMac(deviceId);
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn(e.getMessage() + " Processing SinglePortFilters aborted");
+ return null;
+ }
+ // suppressed ports still have filtering rules pushed by SR using default vlan
+ ConnectPoint connectPoint = new ConnectPoint(deviceId, portnum);
+ boolean isSuppressed = false;
+ SegmentRoutingAppConfig appConfig = srManager.cfgService
+ .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
+ if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
+ isSuppressed = true;
+ }
+
+ Ip4Prefix portSubnet = config.getPortIPv4Subnet(deviceId, portnum);
+ VlanId assignedVlan = (portSubnet == null || isSuppressed)
+ ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
+ : srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
+
+ if (assignedVlan == null) {
+ log.warn("Assigned vlan is null for {} in {} - Processing "
+ + "SinglePortFilters aborted", portnum, deviceId);
+ return null;
+ }
+
+ FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
+ fob.withKey(Criteria.matchInPort(portnum))
+ .addCondition(Criteria.matchEthDst(deviceMac))
+ .addCondition(Criteria.matchVlanId(VlanId.NONE))
+ .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
+ TrafficTreatment tt = DefaultTrafficTreatment.builder()
+ .pushVlan().setVlanId(assignedVlan).build();
+ fob.withMeta(tt);
+ fob.permit().fromApp(srManager.appId);
+ return fob;
}
/**