[CORD-634]Add dynamic config update support for interfaces
Change-Id: I065ef5df908864f10f60c5491db3ff9e502c4101
(cherry picked from commit 42fe10524af1b9c84f4dc16a2361ee6f4b1a82a2)
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 3fb38ba..85d6e1e 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -767,6 +767,23 @@
return true;
}
+ /**
+ * Updates 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
+ * @param pushVlan true to push vlan, false otherwise
+ * @param vlanId vlan identifier
+ * @param install true to install the filtering objective, false to remove
+ */
+ void updateSinglePortFilters(DeviceId deviceId, PortNumber portNum,
+ boolean pushVlan, VlanId vlanId, boolean install) {
+ if (!processSinglePortFiltersInternal(deviceId, portNum, pushVlan, vlanId, install)) {
+ log.warn("Failed to update FilteringObjective for {}/{} with vlan {}",
+ deviceId, portNum, vlanId);
+ }
+ }
+
private boolean processSinglePortFiltersInternal(DeviceId deviceId, PortNumber portnum,
boolean pushVlan, VlanId vlanId, boolean install) {
FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum, pushVlan, vlanId);
@@ -774,7 +791,7 @@
// error encountered during build
return false;
}
- log.debug("{} filtering objectives for dev/port:{}/{}",
+ log.debug("{} filtering objectives for dev/port: {}/{}",
install ? "Installing" : "Removing", deviceId, portnum);
ObjectiveContext context = new DefaultObjectiveContext(
(objective) -> log.debug("Filter for {}/{} {}", deviceId, portnum,
@@ -856,11 +873,44 @@
allIps.add(pairRouterIpv6);
}
for (IpAddress ipaddr : allIps) {
- TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipaddr);
- Optional<DeviceId> optDeviceId = Optional.of(deviceId);
+ populateSingleIpPunts(deviceId, ipaddr);
+ }
+ }
- srManager.packetService.requestPackets(sbuilder.build(),
- PacketPriority.CONTROL, srManager.appId, optDeviceId);
+ /**
+ * Creates a forwarding objective to punt all IP packets, destined to the
+ * specified IP address, which should be router's port IP address.
+ *
+ * @param deviceId the switch dpid for the router
+ * @param ipAddress the IP address of the router's port
+ */
+ void populateSingleIpPunts(DeviceId deviceId, IpAddress ipAddress) {
+ TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipAddress);
+ Optional<DeviceId> optDeviceId = Optional.of(deviceId);
+
+ srManager.packetService.requestPackets(sbuilder.build(),
+ PacketPriority.CONTROL, srManager.appId, optDeviceId);
+ }
+
+ /**
+ * Removes a forwarding objective to punt all IP packets, destined to the
+ * specified IP address, which should be router's port IP address.
+ *
+ * @param deviceId the switch dpid for the router
+ * @param ipAddress the IP address of the router's port
+ */
+ void revokeSingleIpPunts(DeviceId deviceId, IpAddress ipAddress) {
+ TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipAddress);
+ Optional<DeviceId> optDeviceId = Optional.of(deviceId);
+
+ try {
+ if (!ipAddress.equals(config.getRouterIpv4(deviceId)) &&
+ !ipAddress.equals(config.getRouterIpv6(deviceId))) {
+ srManager.packetService.cancelPackets(sbuilder.build(),
+ PacketPriority.CONTROL, srManager.appId, optDeviceId);
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn(e.getMessage() + " Aborting revokeSingleIpPunts");
}
}
@@ -1033,38 +1083,122 @@
*/
void populateSubnetBroadcastRule(DeviceId deviceId) {
srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
- int nextId = srManager.getVlanNextObjectiveId(deviceId, vlanId);
-
- if (nextId < 0) {
- log.error("Cannot install vlan {} broadcast rule in dev:{} due"
- + "to vlanId:{} or nextId:{}", vlanId, deviceId, vlanId, nextId);
- return;
- }
-
- // Driver should treat objective with MacAddress.NONE as the
- // subnet broadcast rule
- 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(SegmentRoutingService.FLOOD_PRIORITY)
- .fromApp(srManager.appId)
- .makePermanent();
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Vlan broadcast rule for {} populated", vlanId),
- (objective, error) ->
- log.warn("Failed to populate vlan broadcast rule for {}: {}", vlanId, error));
- srManager.flowObjectiveService.forward(deviceId, fob.add(context));
+ updateSubnetBroadcastRule(deviceId, vlanId, true);
});
}
+ /**
+ * Creates or removes a forwarding objective to broadcast packets to its subnet.
+ * @param deviceId switch ID to set the rule
+ * @param vlanId vlan ID to specify the subnet
+ * @param install true to install the rule, false to revoke the rule
+ */
+ void updateSubnetBroadcastRule(DeviceId deviceId, VlanId vlanId, boolean install) {
+ int nextId = srManager.getVlanNextObjectiveId(deviceId, vlanId);
+
+ if (nextId < 0) {
+ log.error("Cannot install vlan {} broadcast rule in dev:{} due"
+ + " to vlanId:{} or nextId:{}", vlanId, deviceId, vlanId, nextId);
+ return;
+ }
+
+ // Driver should treat objective with MacAddress.NONE as the
+ // subnet broadcast rule
+ 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(SegmentRoutingService.FLOOD_PRIORITY)
+ .fromApp(srManager.appId)
+ .makePermanent();
+ ObjectiveContext context = new DefaultObjectiveContext(
+ (objective) -> log.debug("Vlan broadcast rule for {} populated", vlanId),
+ (objective, error) ->
+ log.warn("Failed to populate vlan broadcast rule for {}: {}", vlanId, error));
+
+ if (install) {
+ srManager.flowObjectiveService.forward(deviceId, fob.add(context));
+ } else {
+ srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
+ }
+ }
+
private int getPriorityFromPrefix(IpPrefix prefix) {
return (prefix.isIp4()) ?
2000 * prefix.prefixLength() + SegmentRoutingService.MIN_IP_PRIORITY :
500 * prefix.prefixLength() + SegmentRoutingService.MIN_IP_PRIORITY;
}
+
+ /**
+ * Update Forwarding objective for each host and IP address connected to given port.
+ * And create corresponding Simple Next objective if it does not exist.
+ * Applied only when populating Forwarding objective
+ * @param deviceId switch ID to set the rule
+ * @param portNumber port number
+ * @param prefix IP prefix of the route
+ * @param hostMac MAC address of the next hop
+ * @param vlanId Vlan ID of the port
+ * @param popVlan true to pop vlan tag in TrafficTreatment
+ * @param install true to populate the forwarding objective, false to revoke
+ */
+ void updateFwdObj(DeviceId deviceId, PortNumber portNumber, IpPrefix prefix, MacAddress hostMac,
+ VlanId vlanId, boolean popVlan, boolean install) {
+ ForwardingObjective.Builder fob;
+ TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(prefix);
+ MacAddress deviceMac;
+ try {
+ deviceMac = config.getDeviceMac(deviceId);
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn(e.getMessage() + " Aborting updateFwdObj.");
+ return;
+ }
+
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+ tbuilder.deferred()
+ .setEthDst(hostMac)
+ .setEthSrc(deviceMac)
+ .setOutput(portNumber);
+
+ TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
+
+ if (!popVlan) {
+ tbuilder.setVlanId(vlanId);
+ } else {
+ mbuilder.matchVlanId(vlanId);
+ }
+
+ // if the objective is to revoke an existing rule, and for some reason
+ // the next-objective does not exist, then a new one should not be created
+ int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNumber,
+ tbuilder.build(), mbuilder.build(), install);
+ if (portNextObjId == -1) {
+ // Warning log will come from getPortNextObjective method
+ return;
+ }
+
+ fob = DefaultForwardingObjective.builder().withSelector(sbuilder.build())
+ .nextStep(portNextObjId).fromApp(srManager.appId).makePermanent()
+ .withPriority(getPriorityFromPrefix(prefix)).withFlag(ForwardingObjective.Flag.SPECIFIC);
+
+ ObjectiveContext context = new DefaultObjectiveContext(
+ (objective) -> log.debug("IP rule for route {} {}", prefix, install ? "installed" : "revoked"),
+ (objective, error) ->
+ log.warn("Failed to {} IP rule for route {}: {}",
+ install ? "install" : "revoke", prefix, error));
+ srManager.flowObjectiveService.forward(deviceId, install ? fob.add(context) : fob.remove(context));
+
+ if (!install) {
+ DefaultGroupHandler grpHandler = srManager.getGroupHandler(deviceId);
+ if (grpHandler == null) {
+ log.warn("updateFwdObj: groupHandler for device {} not found", deviceId);
+ } else {
+ // Remove L3UG for the given port and host
+ grpHandler.removeGroupFromPort(portNumber, tbuilder.build(), mbuilder.build());
+ }
+ }
+ }
}