Adding route blackhole
Change-Id: I70212b0ab91e628e8528bca896c3aecc499e31b1
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
index f54ee9e..034ddfe 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
@@ -16,6 +16,8 @@
package org.onosproject.segmentrouting;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
@@ -62,6 +64,9 @@
SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
deviceService.getAvailableDevices().forEach(device -> {
populateVRouter(device.id(), getMacAddresses(config));
+ config.blackholeIPs().forEach(ipPrefix -> {
+ srManager.routingRulePopulator.populateDefaultRouteBlackhole(device.id(), ipPrefix);
+ });
});
}
@@ -86,6 +91,14 @@
revokeVRouter(device.id(), prevMacAddresses);
populateVRouter(device.id(), macAddresses);
+ Set<IpPrefix> toRemove = Sets.difference(prevConfig.blackholeIPs(), config.blackholeIPs());
+ toRemove.forEach(ipPrefix -> {
+ srManager.routingRulePopulator.removeDefaultRouteBlackhole(device.id(), ipPrefix);
+ });
+ Set<IpPrefix> toAdd = Sets.difference(config.blackholeIPs(), prevConfig.blackholeIPs());
+ toAdd.forEach(ipPrefix -> {
+ srManager.routingRulePopulator.populateDefaultRouteBlackhole(device.id(), ipPrefix);
+ });
});
}
@@ -100,11 +113,14 @@
SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
deviceService.getAvailableDevices().forEach(device -> {
revokeVRouter(device.id(), getMacAddresses(prevConfig));
+ prevConfig.blackholeIPs().forEach(ipPrefix -> {
+ srManager.routingRulePopulator.removeDefaultRouteBlackhole(device.id(), ipPrefix);
+ });
});
}
/**
- * Populates initial vRouter rules.
+ * Populates initial vRouter and blackhole rules.
*
* @param deviceId device ID
*/
@@ -112,6 +128,9 @@
SegmentRoutingAppConfig config =
srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
populateVRouter(deviceId, getMacAddresses(config));
+ config.blackholeIPs().forEach(ipPrefix -> {
+ srManager.routingRulePopulator.populateDefaultRouteBlackhole(deviceId, ipPrefix);
+ });
}
private void populateVRouter(DeviceId deviceId, Set<MacAddress> pendingAdd) {
@@ -166,7 +185,9 @@
if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {
return true;
}
- } catch (DeviceConfigNotFoundException e) { }
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn("Device configuration for {} is not present.", deviceId);
+ }
return false;
}
}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 094d287..64fe2fc 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -1378,6 +1378,75 @@
* priority Bridging Table entries to a group that contains all ports of
* its subnet.
*
+ * @param address the address to block
+ * @param deviceId switch ID to set the rules
+ */
+ void populateDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address) {
+ updateDefaultRouteBlackhole(deviceId, address, true);
+ }
+
+ /**
+ * Populates a forwarding objective to send packets that miss other high
+ * priority Bridging Table entries to a group that contains all ports of
+ * its subnet.
+ *
+ * @param address the address to block
+ * @param deviceId switch ID to set the rules
+ */
+ void removeDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address) {
+ updateDefaultRouteBlackhole(deviceId, address, false);
+ }
+
+ private void updateDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address, boolean install) {
+ try {
+ if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {
+
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ if (address.isIp4()) {
+ sbuilder.matchIPDst(address);
+ sbuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort());
+ } else {
+ sbuilder.matchIPv6Dst(address);
+ sbuilder.matchEthType(EthType.EtherType.IPV6.ethType().toShort());
+ }
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ tBuilder.transition(60);
+ tBuilder.wipeDeferred();
+
+ ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
+ fob.withFlag(Flag.SPECIFIC)
+ .withSelector(sbuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(getPriorityFromPrefix(address))
+ .fromApp(srManager.appId)
+ .makePermanent();
+
+ log.debug("{} blackhole forwarding objectives for dev: {}",
+ install ? "Installing" : "Removing", deviceId);
+ ObjectiveContext context = new DefaultObjectiveContext(
+ (objective) -> log.debug("Forward for {} {}", deviceId,
+ install ? "installed" : "removed"),
+ (objective, error) -> log.warn("Failed to {} forward for {}: {}",
+ install ? "install" : "remove", deviceId, error));
+ if (install) {
+ srManager.flowObjectiveService.forward(deviceId, fob.add(context));
+ } else {
+ srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
+ }
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ log.info("Not populating blackhole for un-configured device {}", deviceId);
+ }
+
+ }
+
+ /**
+ * Populates a forwarding objective to send packets that miss other high
+ * priority Bridging Table entries to a group that contains all ports of
+ * its subnet.
+ *
* @param deviceId switch ID to set the rules
*/
void populateSubnetBroadcastRule(DeviceId deviceId) {
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
index 3e4d17c..9741f78 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
@@ -19,6 +19,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
@@ -38,14 +39,68 @@
// TODO We might want to move SUPPRESS_HOST_BY_PROVIDER to Component Config
private static final String SUPPRESS_HOST_BY_PROVIDER = "suppressHostByProvider";
private static final String MPLS_ECMP = "MPLS-ECMP";
+ private static final String BLACKHOLE_IPS = "blackholeIps";
@Override
public boolean isValid() {
return hasOnlyFields(VROUTER_MACS, SUPPRESS_SUBNET,
- SUPPRESS_HOST_BY_PORT, SUPPRESS_HOST_BY_PROVIDER, MPLS_ECMP) &&
+ SUPPRESS_HOST_BY_PORT, SUPPRESS_HOST_BY_PROVIDER, MPLS_ECMP, BLACKHOLE_IPS) &&
vRouterMacs() != null &&
suppressSubnet() != null && suppressHostByPort() != null &&
- suppressHostByProvider() != null;
+ suppressHostByProvider() != null &&
+ blackholeIPs() != null;
+ }
+
+ /**
+ * Gets ips to blackhole from the config.
+ *
+ * @return Set of ips to blackhole, empty is not specified,
+ * or null if not valid
+ */
+ public Set<IpPrefix> blackholeIPs() {
+ if (!object.has(BLACKHOLE_IPS)) {
+ return ImmutableSet.of();
+ }
+
+ ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
+ ArrayNode arrayNode = (ArrayNode) object.path(BLACKHOLE_IPS);
+ for (JsonNode jsonNode : arrayNode) {
+ IpPrefix address;
+
+ String addrStr = jsonNode.asText(null);
+ if (addrStr == null) {
+ return null;
+ }
+ try {
+ address = IpPrefix.valueOf(addrStr);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+
+ builder.add(address);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Sets ips to blackhole to the config.
+ *
+ * @param blackholeIps a set of ips to blackhole
+ * @return this {@link SegmentRoutingAppConfig}
+ */
+ public SegmentRoutingAppConfig setBalckholeIps(Set<IpPrefix> blackholeIps) {
+ if (blackholeIps == null) {
+ object.remove(BLACKHOLE_IPS);
+ } else {
+ ArrayNode arrayNode = mapper.createArrayNode();
+
+ blackholeIps.forEach(ip -> {
+ arrayNode.add(ip.toString());
+ });
+
+ object.set(BLACKHOLE_IPS, arrayNode);
+ }
+ return this;
}
/**
@@ -262,6 +317,7 @@
.add("suppressHostByPort", suppressHostByPort())
.add("suppressHostByProvider", suppressHostByProvider())
.add("mplsEcmp", mplsEcmp())
+ .add("blackholeIps", blackholeIPs())
.toString();
}
}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java
index 72b1ef5..2a10f56 100644
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java
+++ b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java
@@ -21,6 +21,7 @@
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.TestApplicationId;
@@ -55,6 +56,8 @@
private static final String PROVIDER_1 = "org.onosproject.provider.host";
private static final String PROVIDER_2 = "org.onosproject.netcfghost";
private static final String PROVIDER_3 = "org.onosproject.anotherprovider";
+ private static final IpPrefix BLACKHOLE_IP = IpPrefix.valueOf("10.0.0.0/8");
+ private static final IpPrefix BLACKHOLE_IP_2 = IpPrefix.valueOf("20.0.0.0/8");
/**
* Initialize test related variables.
@@ -263,6 +266,34 @@
assertTrue(supprsuppressHostByProvider.contains(PROVIDER_3));
}
+ /**
+ * Tests BlackHoleIps getter.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testBlackHoleIps() throws Exception {
+ Set<IpPrefix> blackHoleIps = config.blackholeIPs();
+ assertNotNull("BlackHoleIps should not be null", blackHoleIps);
+ assertThat(blackHoleIps.size(), is(1));
+ assertTrue(blackHoleIps.contains(BLACKHOLE_IP));
+ }
+
+ /**
+ * Tests BlackHoleIps setter.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testSetBlackHoleIps() throws Exception {
+
+ config.setBalckholeIps(ImmutableSet.of(BLACKHOLE_IP_2));
+
+ Set<IpPrefix> blackHoleIps = config.blackholeIPs();
+ assertThat(blackHoleIps.size(), is(1));
+ assertTrue(blackHoleIps.contains(BLACKHOLE_IP_2));
+ }
+
private class MockDelegate implements ConfigApplyDelegate {
@Override
public void onApply(Config config) {
diff --git a/apps/segmentrouting/app/src/test/resources/app.json b/apps/segmentrouting/app/src/test/resources/app.json
index dab6384..2e59b0d 100644
--- a/apps/segmentrouting/app/src/test/resources/app.json
+++ b/apps/segmentrouting/app/src/test/resources/app.json
@@ -14,5 +14,8 @@
"suppressHostByProvider" : [
"org.onosproject.provider.host",
"org.onosproject.netcfghost"
+ ],
+ "blackholeIps": [
+ "10.0.0.0/8"
]
}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
index 04d581a..d834b48 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
@@ -284,6 +284,15 @@
return false;
}
+ /**
+ * Determines whether this driver supports installing a clearDeferred action on table 30.
+ *
+ * @return true if required
+ */
+ protected boolean supportsUnicastBlackHole() {
+ return true;
+ }
+
//////////////////////////////////////
// Flow Objectives
//////////////////////////////////////
@@ -1462,6 +1471,15 @@
tb.transition(ACL_TABLE);
}
+ if (fwd.treatment() != null && fwd.treatment().clearedDeferred()) {
+ if (supportsUnicastBlackHole()) {
+ tb.wipeDeferred();
+ } else {
+ log.warn("Clear Deferred is not supported Unicast Routing Table on device {}", deviceId);
+ return Collections.emptySet();
+ }
+ }
+
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
.fromApp(fwd.appId())
.withPriority(fwd.priority())
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java
index 7377a20..13fe2b1 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java
@@ -65,7 +65,10 @@
import static org.onlab.packet.MacAddress.NONE;
import static org.onosproject.driver.extensions.Ofdpa3MplsType.VPWS;
-import static org.onosproject.net.flow.criteria.Criterion.Type.*;
+import static org.onosproject.net.flow.criteria.Criterion.Type.INNER_VLAN_VID;
+import static org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT;
+import static org.onosproject.net.flow.criteria.Criterion.Type.TUNNEL_ID;
+import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;
import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
import static org.slf4j.LoggerFactory.getLogger;
@@ -100,6 +103,11 @@
}
@Override
+ protected boolean supportsUnicastBlackHole() {
+ return true;
+ }
+
+ @Override
protected void processFilter(FilteringObjective filteringObjective,
boolean install,
ApplicationId applicationId) {
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpa2Pipeline.java
index 013b98e..3aa8865 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpa2Pipeline.java
@@ -50,4 +50,9 @@
protected boolean supportPuntGroup() {
return true;
}
+
+ @Override
+ protected boolean supportsUnicastBlackHole() {
+ return true;
+ }
}