Independence of Trellis
`segmentrouting` and `t3` apps are now hosted in individual repos `trellis-control` and `trellis-t3` respectively
Change-Id: Idaf37dc7b25bd2bcc9f347dbc28ce00faafb6590
diff --git a/apps/segmentrouting/BUILD b/apps/segmentrouting/BUILD
deleted file mode 100644
index 1304a5e..0000000
--- a/apps/segmentrouting/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-BUNDLES = [
- "//apps/segmentrouting/app:onos-apps-segmentrouting-app",
- "//apps/segmentrouting/web:onos-apps-segmentrouting-web",
-]
-
-onos_app(
- category = "Traffic Steering",
- description = "Segment routing application.",
- included_bundles = BUNDLES,
- required_apps = [
- "org.onosproject.route-service",
- "org.onosproject.mcast",
- "org.onosproject.portloadbalancer",
- ],
- title = "Segment Routing",
- url = "http://onosproject.org",
-)
diff --git a/apps/segmentrouting/app/BUILD b/apps/segmentrouting/app/BUILD
deleted file mode 100644
index c6844a6..0000000
--- a/apps/segmentrouting/app/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + CLI + [
- "//core/common:onos-core-common",
- "//core/store/serializers:onos-core-serializers",
- "//apps/route-service/api:onos-apps-route-service-api",
- "//apps/mcast/api:onos-apps-mcast-api",
- "//apps/mcast/cli:onos-apps-mcast-cli",
- "//apps/portloadbalancer:onos-apps-portloadbalancer",
-]
-
-TEST_DEPS = TEST_ADAPTERS + [
- "//core/net:onos-core-net",
- "//apps/route-service/api:onos-apps-route-service-api-tests",
-]
-
-osgi_jar_with_tests(
- karaf_command_packages = ["org.onosproject.segmentrouting.cli"],
- test_deps = TEST_DEPS,
- deps = COMPILE_DEPS,
-)
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
deleted file mode 100644
index 38d8aac..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-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;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Handles Segment Routing app config events.
- */
-public class AppConfigHandler {
- private static final Logger log = LoggerFactory.getLogger(AppConfigHandler.class);
- private final SegmentRoutingManager srManager;
- private final DeviceService deviceService;
-
- /**
- * Constructs Segment Routing App Config Handler.
- *
- * @param srManager instance of {@link SegmentRoutingManager}
- */
- public AppConfigHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- this.deviceService = srManager.deviceService;
- }
-
- /**
- * Processes Segment Routing App Config added event.
- *
- * @param event network config added event
- */
- protected void processAppConfigAdded(NetworkConfigEvent event) {
- log.info("Processing AppConfig CONFIG_ADDED");
- 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);
- });
- });
- }
-
- /**
- * Processes Segment Routing App Config updated event.
- *
- * @param event network config updated event
- */
- protected void processAppConfigUpdated(NetworkConfigEvent event) {
- log.info("Processing AppConfig CONFIG_UPDATED");
- SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
- SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
- deviceService.getAvailableDevices().forEach(device -> {
- Set<MacAddress> macAddresses = new HashSet<>(getMacAddresses(config));
- Set<MacAddress> prevMacAddresses = new HashSet<>(getMacAddresses(prevConfig));
- // Avoid removing and re-adding unchanged MAC addresses since
- // FlowObjective does not guarantee the execution order.
- Set<MacAddress> sameMacAddresses = new HashSet<>(macAddresses);
- sameMacAddresses.retainAll(prevMacAddresses);
- macAddresses.removeAll(sameMacAddresses);
- prevMacAddresses.removeAll(sameMacAddresses);
-
- 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);
- });
- });
-
- }
-
- /**
- * Processes Segment Routing App Config removed event.
- *
- * @param event network config removed event
- */
- protected void processAppConfigRemoved(NetworkConfigEvent event) {
- log.info("Processing AppConfig CONFIG_REMOVED");
- 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 and blackhole rules.
- *
- * @param deviceId device ID
- */
- public void init(DeviceId deviceId) {
- SegmentRoutingAppConfig config =
- srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
- populateVRouter(deviceId, getMacAddresses(config));
- if (config != null) {
- config.blackholeIPs().forEach(ipPrefix -> {
- srManager.routingRulePopulator.populateDefaultRouteBlackhole(deviceId, ipPrefix);
- });
- }
- }
-
- private void populateVRouter(DeviceId deviceId, Set<MacAddress> pendingAdd) {
- if (!isEdge(deviceId)) {
- return;
- }
- getVRouterFlowObjBuilders(pendingAdd).forEach(foBuilder -> {
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("vRouterMac filter for {} populated", pendingAdd),
- (objective, error) ->
- log.warn("Failed to populate vRouterMac filter for {}: {}", pendingAdd, error));
- srManager.flowObjectiveService.filter(deviceId, foBuilder.add(context));
- });
- }
-
- private void revokeVRouter(DeviceId deviceId, Set<MacAddress> pendingRemove) {
- if (!isEdge(deviceId)) {
- return;
- }
- getVRouterFlowObjBuilders(pendingRemove).forEach(foBuilder -> {
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("vRouterMac filter for {} revoked", pendingRemove),
- (objective, error) ->
- log.warn("Failed to revoke vRouterMac filter for {}: {}", pendingRemove, error));
- srManager.flowObjectiveService.filter(deviceId, foBuilder.remove(context));
- });
- }
-
- private Set<FilteringObjective.Builder> getVRouterFlowObjBuilders(Set<MacAddress> macAddresses) {
- ImmutableSet.Builder<FilteringObjective.Builder> setBuilder = ImmutableSet.builder();
- macAddresses.forEach(macAddress -> {
- FilteringObjective.Builder fobuilder = DefaultFilteringObjective.builder();
- fobuilder.withKey(Criteria.matchInPort(PortNumber.ANY))
- .addCondition(Criteria.matchEthDst(macAddress))
- .permit()
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
- .fromApp(srManager.appId);
- setBuilder.add(fobuilder);
- });
- return setBuilder.build();
- }
-
- private Set<MacAddress> getMacAddresses(SegmentRoutingAppConfig config) {
- if (config == null) {
- return ImmutableSet.of();
- }
- return ImmutableSet.copyOf(config.vRouterMacs());
- }
-
- private boolean isEdge(DeviceId deviceId) {
- try {
- if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {
- return true;
- }
- } 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/ArpHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
deleted file mode 100644
index cfef0f1..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.ARP;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.host.HostService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.onosproject.net.neighbour.NeighbourMessageType.REQUEST;
-
-/**
- * Handler of ARP packets that responses or forwards ARP packets that
- * are sent to the controller.
- */
-public class ArpHandler extends SegmentRoutingNeighbourHandler {
-
- private static Logger log = LoggerFactory.getLogger(ArpHandler.class);
-
- /**
- * Creates an ArpHandler object.
- *
- * @param srManager SegmentRoutingManager object
- */
- public ArpHandler(SegmentRoutingManager srManager) {
- super(srManager);
- }
-
- /**
- * Processes incoming ARP packets.
- *
- * If it is an ARP request to router itself or known hosts,
- * then it sends ARP response.
- * If it is an ARP request to unknown hosts in its own subnet,
- * then it flood the ARP request to the ports.
- * If it is an ARP response, then set a flow rule for the host
- * and forward any IP packets to the host in the packet buffer to the host.
- * <p>
- * Note: We handles all ARP packet in, even for those ARP packets between
- * hosts in the same subnet.
- * For an ARP packet with broadcast destination MAC,
- * some switches pipelines will send it to the controller due to table miss,
- * other switches will flood the packets directly in the data plane without
- * packet in.
- * We can deal with both cases.
- *
- * @param pkt incoming ARP packet and context information
- * @param hostService the host service
- */
- public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {
-
- SegmentRoutingAppConfig appConfig = srManager.cfgService
- .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
- if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
- // Ignore ARP packets come from suppressed ports
- pkt.drop();
- return;
- }
-
- if (!validateArpSpa(pkt)) {
- log.debug("Ignore ARP packet discovered on {} with unexpected src protocol address {}.",
- pkt.inPort(), pkt.sender().getIp4Address());
- pkt.drop();
- return;
- }
-
- if (pkt.type() == REQUEST) {
- handleArpRequest(pkt, hostService);
- } else {
- handleArpReply(pkt, hostService);
- }
- }
-
- private void handleArpRequest(NeighbourMessageContext pkt, HostService hostService) {
- // ARP request for router. Send ARP reply.
- if (isArpForRouter(pkt)) {
- MacAddress targetMac = config.getRouterMacForAGatewayIp(pkt.target().getIp4Address());
- if (targetMac == null) {
- log.warn("Router MAC of {} is not configured. Cannot handle ARP request from {}",
- pkt.inPort().deviceId(), pkt.sender());
- return;
- }
- sendResponse(pkt, targetMac, hostService, true);
- } else {
- // NOTE: Ignore ARP packets except those target for the router
- // We will reconsider enabling this when we have host learning support
- /*
- Set<Host> hosts = hostService.getHostsByIp(pkt.target());
- if (hosts.size() > 1) {
- log.warn("More than one host with the same ip {}", pkt.target());
- }
- Host targetHost = hosts.stream().findFirst().orElse(null);
- // ARP request for known hosts. Send proxy ARP reply on behalf of the target.
- if (targetHost != null) {
- pkt.forward(targetHost.location());
- // ARP request for unknown host in the subnet. Flood in the subnet.
- } else {
- flood(pkt);
- }
- */
- }
- }
-
- private void handleArpReply(NeighbourMessageContext pkt, HostService hostService) {
- // ARP reply for router. Process all pending IP packets.
- if (isArpForRouter(pkt)) {
- Ip4Address hostIpAddress = pkt.sender().getIp4Address();
- srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
- } else {
- // NOTE: Ignore ARP packets except those target for the router
- // We will reconsider enabling this when we have host learning support
- /*
- HostId targetHostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
- Host targetHost = hostService.getHost(targetHostId);
- // ARP reply for known hosts. Forward to the host.
- if (targetHost != null) {
- pkt.forward(targetHost.location());
- // ARP reply for unknown host, Flood in the subnet.
- } else {
- // Don't flood to non-edge ports
- if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
- return;
- }
- flood(pkt);
- }
- */
- }
- }
-
- /**
- * Check if the source protocol address of an ARP packet belongs to the same
- * subnet configured on the port it is seen.
- *
- * @param pkt ARP packet and context information
- * @return true if the source protocol address belongs to the configured subnet
- */
- private boolean validateArpSpa(NeighbourMessageContext pkt) {
- Ip4Address spa = pkt.sender().getIp4Address();
- Set<IpPrefix> subnet = config.getPortSubnets(pkt.inPort().deviceId(), pkt.inPort().port())
- .stream()
- .filter(ipPrefix -> ipPrefix.isIp4() && ipPrefix.contains(spa))
- .collect(Collectors.toSet());
- return !subnet.isEmpty();
- }
-
-
- private boolean isArpForRouter(NeighbourMessageContext pkt) {
- Ip4Address targetProtocolAddress = pkt.target().getIp4Address();
- Set<IpAddress> gatewayIpAddresses = null;
- try {
- if (targetProtocolAddress.equals(config.getRouterIpv4(pkt.inPort().deviceId()))) {
- return true;
- }
- gatewayIpAddresses = config.getPortIPs(pkt.inPort().deviceId());
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting check for router IP in processing arp");
- }
- if (gatewayIpAddresses != null &&
- gatewayIpAddresses.contains(targetProtocolAddress)) {
- return true;
- }
- return false;
- }
-
- /**
- * Sends an APR request for the target IP address to all ports except in-port.
- *
- * @param deviceId Switch device ID
- * @param targetAddress target IP address for ARP
- * @param inPort in-port
- */
- public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
- byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
- byte[] senderIpAddress = new byte[Ip4Address.BYTE_LENGTH];
- /*
- * Retrieves device info.
- */
- if (!getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress)) {
- log.warn("Aborting sendArpRequest, we cannot get all the information needed");
- return;
- }
- /*
- * Creates the request.
- */
- Ethernet arpRequest = ARP.buildArpRequest(
- senderMacAddress,
- senderIpAddress,
- targetAddress.toOctets(),
- VlanId.NO_VID
- );
- flood(arpRequest, inPort, targetAddress);
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
deleted file mode 100644
index 8b4b31c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ /dev/null
@@ -1,2222 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-import org.onlab.packet.EthType;
-import com.google.common.collect.Streams;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.PredictableExecutor;
-import org.onlab.util.PredictableExecutor.PickyCallable;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipEvent;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMultimap;
-import org.onosproject.store.service.Serializer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Default routing handler that is responsible for route computing and
- * routing rule population.
- */
-public class DefaultRoutingHandler {
- private static final int MAX_CONSTANT_RETRY_ATTEMPTS = 5;
- private static final long RETRY_INTERVAL_MS = 250L;
- private static final int RETRY_INTERVAL_SCALE = 1;
- private static final long STABLITY_THRESHOLD = 10; //secs
- private static final long MASTER_CHANGE_DELAY = 1000; // ms
- private static final long PURGE_DELAY = 1000; // ms
- private static Logger log = LoggerFactory.getLogger(DefaultRoutingHandler.class);
-
- private SegmentRoutingManager srManager;
- private RoutingRulePopulator rulePopulator;
- private HashMap<DeviceId, EcmpShortestPathGraph> currentEcmpSpgMap;
- private HashMap<DeviceId, EcmpShortestPathGraph> updatedEcmpSpgMap;
- private DeviceConfiguration config;
- private final Lock statusLock = new ReentrantLock();
- private volatile Status populationStatus;
- private ScheduledExecutorService executorService
- = newScheduledThreadPool(1, groupedThreads("retryftr", "retry-%d", log));
- private ScheduledExecutorService executorServiceMstChg
- = newScheduledThreadPool(1, groupedThreads("masterChg", "mstch-%d", log));
- private ScheduledExecutorService executorServiceFRR
- = newScheduledThreadPool(1, groupedThreads("fullRR", "fullRR-%d", log));
- // Route populators - 0 will leverage available processors
- private static final int DEFAULT_THREADS = 0;
- private ExecutorService routePopulators;
-
- private Instant lastRoutingChange = Instant.EPOCH;
- private Instant lastFullReroute = Instant.EPOCH;
-
- // Distributed store to keep track of ONOS instance that should program the
- // device pair. There should be only one instance (the king) that programs the same pair.
- Map<Set<DeviceId>, NodeId> shouldProgram;
- Map<DeviceId, Boolean> shouldProgramCache;
-
- // Distributed routes store to keep track of the routes already seen
- // destination device is the key and target sw is the value
- ConsistentMultimap<DeviceId, DeviceId> seenBeforeRoutes;
-
- // Local store to keep track of all devices that this instance was responsible
- // for programming in the last run. Helps to determine if mastership changed
- // during a run - only relevant for programming as a result of topo change.
- Set<DeviceId> lastProgrammed;
-
- /**
- * Represents the default routing population status.
- */
- public enum Status {
- // population process is not started yet.
- IDLE,
- // population process started.
- STARTED,
- // population process was aborted due to errors, mostly for groups not found.
- ABORTED,
- // population process was finished successfully.
- SUCCEEDED
- }
-
- /**
- * Creates a DefaultRoutingHandler object.
- *
- * @param srManager SegmentRoutingManager object
- */
- DefaultRoutingHandler(SegmentRoutingManager srManager) {
- this.shouldProgram = srManager.storageService.<Set<DeviceId>, NodeId>consistentMapBuilder()
- .withName("sr-should-program")
- .withSerializer(Serializer.using(KryoNamespaces.API))
- .withRelaxedReadConsistency()
- .build().asJavaMap();
- this.seenBeforeRoutes = srManager.storageService.<DeviceId, DeviceId>consistentMultimapBuilder()
- .withName("programmed-routes")
- .withSerializer(Serializer.using(KryoNamespaces.API))
- .withRelaxedReadConsistency()
- .build();
- this.shouldProgramCache = Maps.newConcurrentMap();
- update(srManager);
- this.routePopulators = new PredictableExecutor(DEFAULT_THREADS,
- groupedThreads("onos/sr", "r-populator-%d", log));
- }
-
- /**
- * Updates a DefaultRoutingHandler object.
- *
- * @param srManager SegmentRoutingManager object
- */
- void update(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- this.rulePopulator = checkNotNull(srManager.routingRulePopulator);
- this.config = checkNotNull(srManager.deviceConfiguration);
- this.populationStatus = Status.IDLE;
- this.currentEcmpSpgMap = Maps.newHashMap();
- this.lastProgrammed = Sets.newConcurrentHashSet();
- }
-
- /**
- * Returns an immutable copy of the current ECMP shortest-path graph as
- * computed by this controller instance.
- *
- * @return immutable copy of the current ECMP graph
- */
- public ImmutableMap<DeviceId, EcmpShortestPathGraph> getCurrentEmcpSpgMap() {
- Builder<DeviceId, EcmpShortestPathGraph> builder = ImmutableMap.builder();
- currentEcmpSpgMap.entrySet().forEach(entry -> {
- if (entry.getValue() != null) {
- builder.put(entry.getKey(), entry.getValue());
- }
- });
- return builder.build();
- }
-
- /**
- * Acquires the lock used when making routing changes.
- */
- public void acquireRoutingLock() {
- statusLock.lock();
- }
-
- /**
- * Releases the lock used when making routing changes.
- */
- public void releaseRoutingLock() {
- statusLock.unlock();
- }
-
- /**
- * Determines if routing in the network has been stable in the last
- * STABILITY_THRESHOLD seconds, by comparing the current time to the last
- * routing change timestamp.
- *
- * @return true if stable
- */
- public boolean isRoutingStable() {
- long last = (long) (lastRoutingChange.toEpochMilli() / 1000.0);
- long now = (long) (Instant.now().toEpochMilli() / 1000.0);
- log.trace("Routing stable since {}s", now - last);
- return (now - last) > STABLITY_THRESHOLD;
- }
-
- /**
- * Gracefully shuts down the defaultRoutingHandler. Typically called when
- * the app is deactivated
- */
- public void shutdown() {
- executorService.shutdown();
- executorServiceMstChg.shutdown();
- executorServiceFRR.shutdown();
- routePopulators.shutdown();
- }
-
- //////////////////////////////////////
- // Route path handling
- //////////////////////////////////////
-
- /* The following three methods represent the three major ways in which
- * route-path handling is triggered in the network
- * a) due to configuration change
- * b) due to route-added event
- * c) due to change in the topology
- */
-
- /**
- * Populates all routing rules to all switches. Typically triggered at
- * startup or after a configuration event.
- */
- public void populateAllRoutingRules() {
- lastRoutingChange = Instant.now();
- statusLock.lock();
- try {
- if (populationStatus == Status.STARTED) {
- log.warn("Previous rule population is not finished. Cannot"
- + " proceed with populateAllRoutingRules");
- return;
- }
-
- populationStatus = Status.STARTED;
- rulePopulator.resetCounter();
- log.info("Starting to populate all routing rules");
- log.debug("populateAllRoutingRules: populationStatus is STARTED");
-
- // take a snapshot of the topology
- updatedEcmpSpgMap = new HashMap<>();
- Set<EdgePair> edgePairs = new HashSet<>();
- Set<ArrayList<DeviceId>> routeChanges = new HashSet<>();
- for (DeviceId dstSw : srManager.deviceConfiguration.getRouters()) {
- EcmpShortestPathGraph ecmpSpgUpdated =
- new EcmpShortestPathGraph(dstSw, srManager);
- updatedEcmpSpgMap.put(dstSw, ecmpSpgUpdated);
- Optional<DeviceId> pairDev = srManager.getPairDeviceId(dstSw);
- if (pairDev.isPresent()) {
- // pairDev may not be available yet, but we still need to add
- ecmpSpgUpdated = new EcmpShortestPathGraph(pairDev.get(), srManager);
- updatedEcmpSpgMap.put(pairDev.get(), ecmpSpgUpdated);
- edgePairs.add(new EdgePair(dstSw, pairDev.get()));
- }
-
- if (!shouldProgram(dstSw)) {
- lastProgrammed.remove(dstSw);
- continue;
- } else {
- lastProgrammed.add(dstSw);
- }
- // To do a full reroute, assume all route-paths have changed
- for (DeviceId dev : deviceAndItsPair(dstSw)) {
- for (DeviceId targetSw : srManager.deviceConfiguration.getRouters()) {
- if (targetSw.equals(dev)) {
- continue;
- }
- routeChanges.add(Lists.newArrayList(targetSw, dev));
- }
- }
- }
-
- log.debug("seenBeforeRoutes size {}", seenBeforeRoutes.size());
- if (!redoRouting(routeChanges, edgePairs, null)) {
- log.debug("populateAllRoutingRules: populationStatus is ABORTED");
- populationStatus = Status.ABORTED;
- log.warn("Failed to repopulate all routing rules.");
- return;
- }
-
- log.debug("populateAllRoutingRules: populationStatus is SUCCEEDED");
- populationStatus = Status.SUCCEEDED;
- log.info("Completed all routing rule population. Total # of rules pushed : {}",
- rulePopulator.getCounter());
- return;
- } catch (Exception e) {
- log.error("populateAllRoutingRules thrown an exception: {}",
- e.getMessage(), e);
- populationStatus = Status.ABORTED;
- } finally {
- statusLock.unlock();
- }
- }
-
- /**
- * Populate rules from all other edge devices to the connect-point(s)
- * specified for the given subnets.
- *
- * @param cpts connect point(s) of the subnets being added
- * @param subnets subnets being added
- */
- // XXX refactor
- protected void populateSubnet(Set<ConnectPoint> cpts, Set<IpPrefix> subnets) {
- if (cpts == null || cpts.size() < 1 || cpts.size() > 2) {
- log.warn("Skipping populateSubnet due to illegal size of connect points. {}", cpts);
- return;
- }
-
- lastRoutingChange = Instant.now();
- statusLock.lock();
- try {
- if (populationStatus == Status.STARTED) {
- log.warn("Previous rule population is not finished. Cannot"
- + " proceed with routing rules for added routes");
- return;
- }
- populationStatus = Status.STARTED;
- rulePopulator.resetCounter();
- log.info("Starting to populate routing rules for added routes, subnets={}, cpts={}",
- subnets, cpts);
- // In principle an update to a subnet/prefix should not require a
- // new ECMPspg calculation as it is not a topology event. As a
- // result, we use the current/existing ECMPspg in the updated map
- // used by the redoRouting method.
- if (updatedEcmpSpgMap == null) {
- updatedEcmpSpgMap = new HashMap<>();
- }
- currentEcmpSpgMap.entrySet().forEach(entry -> {
- updatedEcmpSpgMap.put(entry.getKey(), entry.getValue());
- if (log.isTraceEnabled()) {
- log.trace("Root switch: {}", entry.getKey());
- log.trace(" Current/Existing SPG: {}", entry.getValue());
- }
- });
- log.debug("seenBeforeRoutes size {}", seenBeforeRoutes.size());
- Set<EdgePair> edgePairs = new HashSet<>();
- Set<ArrayList<DeviceId>> routeChanges = new HashSet<>();
- boolean handleRouting = false;
-
- if (cpts.size() == 2) {
- // ensure connect points are edge-pairs
- Iterator<ConnectPoint> iter = cpts.iterator();
- DeviceId dev1 = iter.next().deviceId();
- Optional<DeviceId> pairDev = srManager.getPairDeviceId(dev1);
- if (pairDev.isPresent() && iter.next().deviceId().equals(pairDev.get())) {
- edgePairs.add(new EdgePair(dev1, pairDev.get()));
- } else {
- log.warn("Connectpoints {} for subnets {} not on "
- + "pair-devices.. aborting populateSubnet", cpts, subnets);
- populationStatus = Status.ABORTED;
- return;
- }
- for (ConnectPoint cp : cpts) {
- if (updatedEcmpSpgMap.get(cp.deviceId()) == null) {
- EcmpShortestPathGraph ecmpSpgUpdated =
- new EcmpShortestPathGraph(cp.deviceId(), srManager);
- updatedEcmpSpgMap.put(cp.deviceId(), ecmpSpgUpdated);
- log.warn("populateSubnet: no updated graph for dev:{}"
- + " ... creating", cp.deviceId());
- }
- if (!shouldProgram(cp.deviceId())) {
- continue;
- }
- handleRouting = true;
- }
- } else {
- // single connect point
- DeviceId dstSw = cpts.iterator().next().deviceId();
- if (updatedEcmpSpgMap.get(dstSw) == null) {
- EcmpShortestPathGraph ecmpSpgUpdated =
- new EcmpShortestPathGraph(dstSw, srManager);
- updatedEcmpSpgMap.put(dstSw, ecmpSpgUpdated);
- log.warn("populateSubnet: no updated graph for dev:{}"
- + " ... creating", dstSw);
- }
- handleRouting = shouldProgram(dstSw);
- }
-
- if (!handleRouting) {
- log.debug("This instance is not handling ecmp routing to the "
- + "connectPoint(s) {}", cpts);
- populationStatus = Status.ABORTED;
- return;
- }
-
- // if it gets here, this instance should handle routing for the
- // connectpoint(s). Assume all route-paths have to be updated to
- // the connectpoint(s) with the following exceptions
- // 1. if target is non-edge no need for routing rules
- // 2. if target is one of the connectpoints
- for (ConnectPoint cp : cpts) {
- DeviceId dstSw = cp.deviceId();
- for (Device targetSw : srManager.deviceService.getDevices()) {
- boolean isEdge = false;
- try {
- isEdge = config.isEdgeDevice(targetSw.id());
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + "aborting populateSubnet on targetSw {}", targetSw.id());
- continue;
- }
- Optional<DeviceId> pairDev = srManager.getPairDeviceId(dstSw);
- if (dstSw.equals(targetSw.id()) || !isEdge ||
- (cpts.size() == 2 && pairDev.isPresent() && targetSw.id().equals(pairDev.get()))) {
- continue;
- }
- routeChanges.add(Lists.newArrayList(targetSw.id(), dstSw));
- }
- }
-
- if (!redoRouting(routeChanges, edgePairs, subnets)) {
- log.debug("populateSubnet: populationStatus is ABORTED");
- populationStatus = Status.ABORTED;
- log.warn("Failed to repopulate the rules for subnet.");
- return;
- }
-
- log.debug("populateSubnet: populationStatus is SUCCEEDED");
- populationStatus = Status.SUCCEEDED;
- log.info("Completed subnet population. Total # of rules pushed : {}",
- rulePopulator.getCounter());
- return;
-
- } catch (Exception e) {
- log.error("populateSubnet thrown an exception: {}",
- e.getMessage(), e);
- populationStatus = Status.ABORTED;
- } finally {
- statusLock.unlock();
- }
- }
-
- /**
- * Populates the routing rules or makes hash group changes according to the
- * route-path changes due to link failure, switch failure or link up. This
- * method should only be called for one of these three possible event-types.
- * Note that when a switch goes away, all of its links fail as well, but
- * this is handled as a single switch removal event.
- *
- * @param linkDown the single failed link, or null for other conditions such
- * as link-up or a removed switch
- * @param linkUp the single link up, or null for other conditions such as
- * link-down or a removed switch
- * @param switchDown the removed switch, or null for other conditions such
- * as link-down or link-up
- * @param seenBefore true if this event is for a linkUp or linkDown for a
- * seen link
- */
- // TODO This method should be refactored into three separated methods
- public void populateRoutingRulesForLinkStatusChange(Link linkDown, Link linkUp,
- DeviceId switchDown, boolean seenBefore) {
- if (Stream.of(linkDown, linkUp, switchDown).filter(Objects::nonNull)
- .count() != 1) {
- log.warn("Only one event can be handled for link status change .. aborting");
- return;
- }
-
- lastRoutingChange = Instant.now();
- statusLock.lock();
- try {
-
- if (populationStatus == Status.STARTED) {
- log.warn("Previous rule population is not finished. Cannot"
- + " proceeed with routingRules for Topology change");
- return;
- }
-
- // Take snapshots of the topology
- updatedEcmpSpgMap = new HashMap<>();
- Set<EdgePair> edgePairs = new HashSet<>();
- for (Device sw : srManager.deviceService.getDevices()) {
- EcmpShortestPathGraph ecmpSpgUpdated =
- new EcmpShortestPathGraph(sw.id(), srManager);
- updatedEcmpSpgMap.put(sw.id(), ecmpSpgUpdated);
- Optional<DeviceId> pairDev = srManager.getPairDeviceId(sw.id());
- if (pairDev.isPresent()) {
- // pairDev may not be available yet, but we still need to add
- ecmpSpgUpdated = new EcmpShortestPathGraph(pairDev.get(), srManager);
- updatedEcmpSpgMap.put(pairDev.get(), ecmpSpgUpdated);
- edgePairs.add(new EdgePair(sw.id(), pairDev.get()));
- }
- }
-
- log.info("Starting to populate routing rules from Topology change");
-
- Set<ArrayList<DeviceId>> routeChanges;
- log.debug("populateRoutingRulesForLinkStatusChange: "
- + "populationStatus is STARTED");
- log.debug("seenBeforeRoutes size {}", seenBeforeRoutes.size());
- populationStatus = Status.STARTED;
- rulePopulator.resetCounter(); //XXX maybe useful to have a rehash ctr
- boolean hashGroupsChanged = false;
- // try optimized re-routing
- if (linkDown == null) {
- // either a linkUp or a switchDown - compute all route changes by
- // comparing all routes of existing ECMP SPG to new ECMP SPG
- routeChanges = computeRouteChange(switchDown);
-
- // deal with linkUp
- if (linkUp != null) {
- // deal with linkUp of a seen-before link
- if (seenBefore) {
- // link previously seen before
- // do hash-bucket changes instead of a re-route
- processHashGroupChangeForLinkUp(routeChanges);
- // clear out routesChanges so a re-route is not attempted
- routeChanges = ImmutableSet.of();
- hashGroupsChanged = true;
- } else {
- // do hash-bucket changes first, method will return changed routes;
- // for each route not changed it will perform a reroute
- Set<ArrayList<DeviceId>> changedRoutes = processHashGroupChangeForLinkUp(routeChanges);
- Set<ArrayList<DeviceId>> routeChangesTemp = getExpandedRoutes(routeChanges);
- changedRoutes.forEach(routeChangesTemp::remove);
- // if routesChanges is empty a re-route is not attempted
- routeChanges = routeChangesTemp;
- for (ArrayList<DeviceId> route : routeChanges) {
- log.debug("remaining routes Target -> Root");
- if (route.size() == 1) {
- log.debug(" : all -> {}", route.get(0));
- } else {
- log.debug(" : {} -> {}", route.get(0), route.get(1));
- }
- }
- // Mark hash groups as changed
- if (!changedRoutes.isEmpty()) {
- hashGroupsChanged = true;
- }
- }
-
- }
-
- //deal with switchDown
- if (switchDown != null) {
- processHashGroupChangeForFailure(routeChanges, switchDown);
- // clear out routesChanges so a re-route is not attempted
- routeChanges = ImmutableSet.of();
- hashGroupsChanged = true;
- }
- } else {
- // link has gone down
- // Compare existing ECMP SPG only with the link that went down
- routeChanges = computeDamagedRoutes(linkDown);
- processHashGroupChangeForFailure(routeChanges, null);
- // clear out routesChanges so a re-route is not attempted
- routeChanges = ImmutableSet.of();
- hashGroupsChanged = true;
- }
-
- if (routeChanges.isEmpty()) {
- if (hashGroupsChanged) {
- log.info("Hash-groups changed for link status change");
- } else {
- log.info("No re-route or re-hash attempted for the link"
- + " status change");
- updatedEcmpSpgMap.keySet().forEach(devId -> {
- currentEcmpSpgMap.put(devId, updatedEcmpSpgMap.get(devId));
- log.debug("Updating ECMPspg for remaining dev:{}", devId);
- });
- }
- log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED");
- populationStatus = Status.SUCCEEDED;
- return;
- }
-
- if (hashGroupsChanged) {
- log.debug("Hash-groups changed for link status change");
- }
-
- // reroute of routeChanges
- if (redoRouting(routeChanges, edgePairs, null)) {
- log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED");
- populationStatus = Status.SUCCEEDED;
- log.info("Completed repopulation of rules for link-status change."
- + " # of rules populated : {}", rulePopulator.getCounter());
- return;
- } else {
- log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is ABORTED");
- populationStatus = Status.ABORTED;
- log.warn("Failed to repopulate the rules for link status change.");
- return;
- }
- } catch (Exception e) {
- log.error("populateRoutingRulesForLinkStatusChange thrown an exception: {}",
- e.getMessage(), e);
- populationStatus = Status.ABORTED;
- } finally {
- statusLock.unlock();
- }
- }
-
- /**
- * Processes a set a route-path changes by reprogramming routing rules and
- * creating new hash-groups or editing them if necessary. This method also
- * determines the next-hops for the route-path from the src-switch (target)
- * of the path towards the dst-switch of the path.
- *
- * @param routeChanges a set of route-path changes, where each route-path is
- * a list with its first element the src-switch (target)
- * of the path, and the second element the dst-switch of
- * the path.
- * @param edgePairs a set of edge-switches that are paired by configuration
- * @param subnets a set of prefixes that need to be populated in the routing
- * table of the target switch in the route-path. Can be null,
- * in which case all the prefixes belonging to the dst-switch
- * will be populated in the target switch
- * @return true if successful in repopulating all routes
- */
- private boolean redoRouting(Set<ArrayList<DeviceId>> routeChanges,
- Set<EdgePair> edgePairs, Set<IpPrefix> subnets) {
- // first make every entry two-elements
- Set<ArrayList<DeviceId>> changedRoutes = getExpandedRoutes(routeChanges);
- // no valid routes - fail fast
- if (changedRoutes.isEmpty()) {
- return false;
- }
-
- // Temporary stores the changed routes
- Set<ArrayList<DeviceId>> tempRoutes = ImmutableSet.copyOf(changedRoutes);
- // now process changedRoutes according to edgePairs
- if (!redoRoutingEdgePairs(edgePairs, subnets, changedRoutes)) {
- return false; //abort routing and fail fast
- }
- // Calculate the programmed routes pointing to the pairs
- Set<ArrayList<DeviceId>> programmedPairRoutes = Sets.difference(tempRoutes, changedRoutes);
- log.debug("Evaluating programmed pair routes");
- storeSeenBeforeRoutes(programmedPairRoutes);
-
- // Temporary stores the left routes
- tempRoutes = ImmutableSet.copyOf(changedRoutes);
- // whatever is left in changedRoutes is now processed for individual dsts.
- Set<DeviceId> updatedDevices = Sets.newHashSet();
- if (!redoRoutingIndividualDests(subnets, changedRoutes,
- updatedDevices)) {
- return false; //abort routing and fail fast
- }
- // Calculate the individual programmed routes
- Set<ArrayList<DeviceId>> programmedIndividualRoutes = Sets.difference(tempRoutes, changedRoutes);
- log.debug("Evaluating individual programmed routes");
- storeSeenBeforeRoutes(programmedIndividualRoutes);
-
- // update ecmpSPG for all edge-pairs
- for (EdgePair ep : edgePairs) {
- currentEcmpSpgMap.put(ep.dev1, updatedEcmpSpgMap.get(ep.dev1));
- currentEcmpSpgMap.put(ep.dev2, updatedEcmpSpgMap.get(ep.dev2));
- log.debug("Updating ECMPspg for edge-pair:{}-{}", ep.dev1, ep.dev2);
- }
-
- // here is where we update all devices not touched by this instance
- updatedEcmpSpgMap.keySet().stream()
- .filter(devId -> !edgePairs.stream().anyMatch(ep -> ep.includes(devId)))
- .filter(devId -> !updatedDevices.contains(devId))
- .forEach(devId -> {
- currentEcmpSpgMap.put(devId, updatedEcmpSpgMap.get(devId));
- log.debug("Updating ECMPspg for remaining dev:{}", devId);
- });
- return true;
- }
-
- /**
- * Stores the routes seen before. Routes are two-elements arrays.
- * @param seenRoutes seen before routes
- */
- private void storeSeenBeforeRoutes(Set<ArrayList<DeviceId>> seenRoutes) {
- Set<DeviceId> nextHops;
- for (ArrayList<DeviceId> route : seenRoutes) {
- log.debug("Route {} -> {} has been programmed", route.get(0), route.get(1));
- nextHops = getNextHops(route.get(0), route.get(1));
- // No valid next hops - cannot be considered a programmed route
- if (nextHops.isEmpty()) {
- log.debug("Could not find next hop from target:{} --> dst {} "
- + "skipping this route", route.get(0), route.get(1));
- continue;
- }
- // Already present - do not add again
- if (seenBeforeRoutes.containsEntry(route.get(1), route.get(0))) {
- log.debug("Route from target:{} --> dst {} " +
- "already present, skipping this route", route.get(0), route.get(1));
- continue;
- }
- seenBeforeRoutes.put(route.get(1), route.get(0));
- }
- }
-
- /**
- * Programs targetSw in the changedRoutes for given prefixes reachable by
- * an edgePair. If no prefixes are given, the method will use configured
- * subnets/prefixes. If some configured subnets belong only to a specific
- * destination in the edgePair, then the target switch will be programmed
- * only to that destination.
- *
- * @param edgePairs set of edge-pairs for which target will be programmed
- * @param subnets a set of prefixes that need to be populated in the routing
- * table of the target switch in the changedRoutes. Can be null,
- * in which case all the configured prefixes belonging to the
- * paired switches will be populated in the target switch
- * @param changedRoutes a set of route-path changes, where each route-path is
- * a list with its first element the src-switch (target)
- * of the path, and the second element the dst-switch of
- * the path.
- * @return true if successful
- */
- private boolean redoRoutingEdgePairs(Set<EdgePair> edgePairs, Set<IpPrefix> subnets,
- Set<ArrayList<DeviceId>> changedRoutes) {
- for (EdgePair ep : edgePairs) {
- // temp store for a target's changedRoutes to this edge-pair
- Map<DeviceId, Set<ArrayList<DeviceId>>> targetRoutes = new HashMap<>();
- Iterator<ArrayList<DeviceId>> i = changedRoutes.iterator();
- while (i.hasNext()) {
- ArrayList<DeviceId> route = i.next();
- DeviceId dstSw = route.get(1);
- if (ep.includes(dstSw)) {
- // routeChange for edge pair found
- // sort by target iff target is edge and remove from changedRoutes
- DeviceId targetSw = route.get(0);
- try {
- if (!srManager.deviceConfiguration.isEdgeDevice(targetSw)) {
- continue;
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + "aborting redoRouting");
- return false;
- }
- // route is from another edge to this edge-pair
- if (targetRoutes.containsKey(targetSw)) {
- targetRoutes.get(targetSw).add(route);
- } else {
- Set<ArrayList<DeviceId>> temp = new HashSet<>();
- temp.add(route);
- targetRoutes.put(targetSw, temp);
- }
- i.remove();
- }
- }
- // so now for this edgepair we have a per target set of routechanges
- // process target->edgePair route
- List<Future<Boolean>> futures = Lists.newArrayList();
- for (Entry<DeviceId, Set<ArrayList<DeviceId>>> entry :
- targetRoutes.entrySet()) {
- log.debug("* redoRoutingDstPair Target:{} -> edge-pair {}",
- entry.getKey(), ep);
- futures.add(routePopulators.submit(new RedoRoutingEdgePair(entry.getKey(), entry.getValue(),
- subnets, ep)));
- }
- if (!checkJobs(futures)) {
- return false;
- }
- // if it gets here it has succeeded for all targets to this edge-pair
- }
- return true;
- }
-
- private final class RedoRoutingEdgePair implements PickyCallable<Boolean> {
- private DeviceId targetSw;
- private Set<ArrayList<DeviceId>> routes;
- private Set<IpPrefix> subnets;
- private EdgePair ep;
-
- /**
- * Builds a RedoRoutingEdgePair task which provides a result.
- *
- * @param targetSw the target switch
- * @param routes the changed routes
- * @param subnets the subnets
- * @param ep the edge pair
- */
- RedoRoutingEdgePair(DeviceId targetSw, Set<ArrayList<DeviceId>> routes,
- Set<IpPrefix> subnets, EdgePair ep) {
- this.targetSw = targetSw;
- this.routes = routes;
- this.subnets = subnets;
- this.ep = ep;
- }
-
- @Override
- public Boolean call() throws Exception {
- return redoRoutingEdgePair();
- }
-
- @Override
- public int hint() {
- return targetSw.hashCode();
- }
-
- private boolean redoRoutingEdgePair() {
- Map<DeviceId, Set<DeviceId>> perDstNextHops = new HashMap<>();
- routes.forEach(route -> {
- Set<DeviceId> nhops = getNextHops(route.get(0), route.get(1));
- log.debug("route: target {} -> dst {} found with next-hops {}",
- route.get(0), route.get(1), nhops);
- perDstNextHops.put(route.get(1), nhops);
- });
-
- List<Set<IpPrefix>> batchedSubnetDev1, batchedSubnetDev2;
- if (subnets != null) {
- batchedSubnetDev1 = Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(subnets));
- batchedSubnetDev2 = Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(subnets));
- } else {
- batchedSubnetDev1 = config.getBatchedSubnets(ep.dev1);
- batchedSubnetDev2 = config.getBatchedSubnets(ep.dev2);
- }
- List<Set<IpPrefix>> batchedSubnetBoth = Streams
- .zip(batchedSubnetDev1.stream(), batchedSubnetDev2.stream(), (a, b) -> Sets.intersection(a, b))
- .filter(set -> !set.isEmpty())
- .collect(Collectors.toList());
- List<Set<IpPrefix>> batchedSubnetDev1Only = Streams
- .zip(batchedSubnetDev1.stream(), batchedSubnetDev2.stream(), (a, b) -> Sets.difference(a, b))
- .filter(set -> !set.isEmpty())
- .collect(Collectors.toList());
- List<Set<IpPrefix>> batchedSubnetDev2Only = Streams
- .zip(batchedSubnetDev1.stream(), batchedSubnetDev2.stream(), (a, b) -> Sets.difference(b, a))
- .filter(set -> !set.isEmpty())
- .collect(Collectors.toList());
-
- Set<DeviceId> nhDev1 = perDstNextHops.get(ep.dev1);
- Set<DeviceId> nhDev2 = perDstNextHops.get(ep.dev2);
-
- // handle routing to subnets common to edge-pair
- // only if the targetSw is not part of the edge-pair and there
- // exists a next hop to at least one of the devices in the edge-pair
- if (!ep.includes(targetSw)
- && ((nhDev1 != null && !nhDev1.isEmpty()) || (nhDev2 != null && !nhDev2.isEmpty()))) {
- log.trace("getSubnets on both {} and {}: {}", ep.dev1, ep.dev2, batchedSubnetBoth);
- for (Set<IpPrefix> prefixes : batchedSubnetBoth) {
- if (!populateEcmpRoutingRulePartial(targetSw, ep.dev1, ep.dev2,
- perDstNextHops, prefixes)) {
- return false; // abort everything and fail fast
- }
- }
-
- }
- // handle routing to subnets that only belong to dev1 only if
- // a next-hop exists from the target to dev1
- if (!batchedSubnetDev1Only.isEmpty() &&
- batchedSubnetDev1Only.stream().anyMatch(subnet -> !subnet.isEmpty()) &&
- nhDev1 != null && !nhDev1.isEmpty()) {
- Map<DeviceId, Set<DeviceId>> onlyDev1NextHops = new HashMap<>();
- onlyDev1NextHops.put(ep.dev1, nhDev1);
- log.trace("getSubnets on {} only: {}", ep.dev1, batchedSubnetDev1Only);
- for (Set<IpPrefix> prefixes : batchedSubnetDev1Only) {
- if (!populateEcmpRoutingRulePartial(targetSw, ep.dev1, null,
- onlyDev1NextHops, prefixes)) {
- return false; // abort everything and fail fast
- }
- }
- }
- // handle routing to subnets that only belong to dev2 only if
- // a next-hop exists from the target to dev2
- if (!batchedSubnetDev2Only.isEmpty() &&
- batchedSubnetDev2Only.stream().anyMatch(subnet -> !subnet.isEmpty()) &&
- nhDev2 != null && !nhDev2.isEmpty()) {
- Map<DeviceId, Set<DeviceId>> onlyDev2NextHops = new HashMap<>();
- onlyDev2NextHops.put(ep.dev2, nhDev2);
- log.trace("getSubnets on {} only: {}", ep.dev2, batchedSubnetDev2Only);
- for (Set<IpPrefix> prefixes : batchedSubnetDev2Only) {
- if (!populateEcmpRoutingRulePartial(targetSw, ep.dev2, null,
- onlyDev2NextHops, prefixes)) {
- return false; // abort everything and fail fast
- }
- }
- }
- return true;
- }
- }
-
- /**
- * Programs targetSw in the changedRoutes for given prefixes reachable by
- * a destination switch that is not part of an edge-pair.
- * If no prefixes are given, the method will use configured subnets/prefixes.
- *
- * @param subnets a set of prefixes that need to be populated in the routing
- * table of the target switch in the changedRoutes. Can be null,
- * in which case all the configured prefixes belonging to the
- * paired switches will be populated in the target switch
- * @param changedRoutes a set of route-path changes, where each route-path is
- * a list with its first element the src-switch (target)
- * of the path, and the second element the dst-switch of
- * the path.
- * @return true if successful
- */
- private boolean redoRoutingIndividualDests(Set<IpPrefix> subnets, Set<ArrayList<DeviceId>> changedRoutes,
- Set<DeviceId> updatedDevices) {
- // aggregate route-path changes for each dst device
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> routesBydevice =
- new HashMap<>();
- for (ArrayList<DeviceId> route: changedRoutes) {
- DeviceId dstSw = route.get(1);
- ArrayList<ArrayList<DeviceId>> deviceRoutes =
- routesBydevice.get(dstSw);
- if (deviceRoutes == null) {
- deviceRoutes = new ArrayList<>();
- routesBydevice.put(dstSw, deviceRoutes);
- }
- deviceRoutes.add(route);
- }
- // iterate over the impacted devices
- for (DeviceId impactedDstDevice : routesBydevice.keySet()) {
- ArrayList<ArrayList<DeviceId>> deviceRoutes =
- routesBydevice.get(impactedDstDevice);
- List<Future<Boolean>> futures = Lists.newArrayList();
- for (ArrayList<DeviceId> route: deviceRoutes) {
- log.debug("* redoRoutingIndiDst Target: {} -> dst: {}",
- route.get(0), route.get(1));
- futures.add(routePopulators.submit(new RedoRoutingIndividualDest(subnets, route)));
- changedRoutes.remove(route);
- }
- // check the execution of each job
- if (!checkJobs(futures)) {
- return false;
- }
- //Only if all the flows for all impacted routes to a
- //specific target are pushed successfully, update the
- //ECMP graph for that target. Or else the next event
- //would not see any changes in the ECMP graphs.
- //In another case, the target switch has gone away, so
- //routes can't be installed. In that case, the current map
- //is updated here, without any flows being pushed.
- currentEcmpSpgMap.put(impactedDstDevice,
- updatedEcmpSpgMap.get(impactedDstDevice));
- updatedDevices.add(impactedDstDevice);
- log.debug("Updating ECMPspg for impacted dev:{}", impactedDstDevice);
- }
- return true;
- }
-
- private final class RedoRoutingIndividualDest implements PickyCallable<Boolean> {
- private DeviceId targetSw;
- private ArrayList<DeviceId> route;
- private Set<IpPrefix> subnets;
-
- /**
- * Builds a RedoRoutingIndividualDest task, which provides a result.
- *
- * @param subnets a set of prefixes
- * @param route a route-path change
- */
- RedoRoutingIndividualDest(Set<IpPrefix> subnets, ArrayList<DeviceId> route) {
- this.targetSw = route.get(0);
- this.route = route;
- this.subnets = subnets;
- }
-
- @Override
- public Boolean call() throws Exception {
- DeviceId dstSw = route.get(1); // same as impactedDstDevice
- Set<DeviceId> nextHops = getNextHops(targetSw, dstSw);
- if (nextHops.isEmpty()) {
- log.debug("Could not find next hop from target:{} --> dst {} "
- + "skipping this route", targetSw, dstSw);
- return true;
- }
- Map<DeviceId, Set<DeviceId>> nhops = new HashMap<>();
- nhops.put(dstSw, nextHops);
- if (!populateEcmpRoutingRulePartial(targetSw, dstSw, null, nhops,
- (subnets == null) ? Sets.newHashSet() : subnets)) {
- return false; // abort routing and fail fast
- }
- log.debug("Populating flow rules from target: {} to dst: {}"
- + " is successful", targetSw, dstSw);
- return true;
- }
-
- @Override
- public int hint() {
- return targetSw.hashCode();
- }
- }
-
- /**
- * Populate ECMP rules for subnets from target to destination via nexthops.
- *
- * @param targetSw Device ID of target switch in which rules will be programmed
- * @param destSw1 Device ID of final destination switch to which the rules will forward
- * @param destSw2 Device ID of paired destination switch to which the rules will forward
- * A null deviceId indicates packets should only be sent to destSw1
- * @param nextHops Map of a set of next hops per destSw
- * @param subnets Subnets to be populated. If empty, populate all configured subnets.
- * @return true if it succeeds in populating rules
- */ // refactor
- private boolean populateEcmpRoutingRulePartial(DeviceId targetSw, DeviceId destSw1, DeviceId destSw2,
- Map<DeviceId, Set<DeviceId>> nextHops, Set<IpPrefix> subnets) {
- boolean result;
- // If both target switch and dest switch are edge routers, then set IP
- // rule for both subnet and router IP.
- boolean targetIsEdge;
- boolean dest1IsEdge;
- Ip4Address dest1RouterIpv4, dest2RouterIpv4 = null;
- Ip6Address dest1RouterIpv6, dest2RouterIpv6 = null;
-
- try {
- targetIsEdge = config.isEdgeDevice(targetSw);
- dest1IsEdge = config.isEdgeDevice(destSw1);
- dest1RouterIpv4 = config.getRouterIpv4(destSw1);
- dest1RouterIpv6 = config.getRouterIpv6(destSw1);
- if (destSw2 != null) {
- dest2RouterIpv4 = config.getRouterIpv4(destSw2);
- dest2RouterIpv6 = config.getRouterIpv6(destSw2);
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting populateEcmpRoutingRulePartial.");
- return false;
- }
-
- if (targetIsEdge && dest1IsEdge) {
- List<Set<IpPrefix>> batchedSubnets;
- if (subnets != null && !subnets.isEmpty()) {
- batchedSubnets = Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(subnets));
- } else {
- batchedSubnets = config.getBatchedSubnets(destSw1);
- }
- // XXX - Rethink this - ignoring routerIPs in all other switches
- // even edge to edge switches
- /*subnets.add(dest1RouterIpv4.toIpPrefix());
- if (dest1RouterIpv6 != null) {
- subnets.add(dest1RouterIpv6.toIpPrefix());
- }
- if (destSw2 != null && dest2RouterIpv4 != null) {
- subnets.add(dest2RouterIpv4.toIpPrefix());
- if (dest2RouterIpv6 != null) {
- subnets.add(dest2RouterIpv6.toIpPrefix());
- }
- }*/
- log.trace("getSubnets on {}: {}", destSw1, batchedSubnets);
- for (Set<IpPrefix> prefixes : batchedSubnets) {
- log.debug(". populateEcmpRoutingRulePartial in device {} towards {} {} "
- + "for subnets {}", targetSw, destSw1,
- (destSw2 != null) ? ("& " + destSw2) : "",
- prefixes);
- if (!rulePopulator.populateIpRuleForSubnet(targetSw, prefixes, destSw1, destSw2, nextHops)) {
- return false;
- }
- }
- }
-
- if (!targetIsEdge && dest1IsEdge) {
- // MPLS rules in all non-edge target devices. These rules are for
- // individual destinations, even if the dsts are part of edge-pairs.
- log.debug(". populateEcmpRoutingRulePartial in device{} towards {} for "
- + "all MPLS rules", targetSw, destSw1);
- result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1), dest1RouterIpv4);
- if (!result) {
- return false;
- }
- if (dest1RouterIpv6 != null) {
- int v4sid = 0, v6sid = 0;
- try {
- v4sid = config.getIPv4SegmentId(destSw1);
- v6sid = config.getIPv6SegmentId(destSw1);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage());
- }
- if (v4sid != v6sid) {
- result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1),
- dest1RouterIpv6);
- if (!result) {
- return false;
- }
- }
- }
- }
-
- if (!targetIsEdge && !dest1IsEdge) {
- // MPLS rules for inter-connected spines
- // can be merged with above if, left it here for clarity
- log.debug(". populateEcmpRoutingRulePartial in device{} towards {} for "
- + "all MPLS rules", targetSw, destSw1);
-
- result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1), dest1RouterIpv4);
- if (!result) {
- return false;
- }
-
- if (dest1RouterIpv6 != null) {
- int v4sid = 0, v6sid = 0;
- try {
- v4sid = config.getIPv4SegmentId(destSw1);
- v6sid = config.getIPv6SegmentId(destSw1);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage());
- }
- if (v4sid != v6sid) {
- result = rulePopulator.populateMplsRule(targetSw, destSw1, nextHops.get(destSw1),
- dest1RouterIpv6);
- if (!result) {
- return false;
- }
- }
- }
- }
-
- // To save on ECMP groups
- // avoid MPLS rules in non-edge-devices to non-edge-devices
- // avoid MPLS transit rules in edge-devices
- // avoid loopback IP rules in edge-devices to non-edge-devices
- return true;
- }
-
- /**
- * Processes a set a route-path changes due to a switch/link failure by editing hash groups.
- *
- * @param routeChanges a set of route-path changes, where each route-path is
- * a list with its first element the src-switch of the path
- * and the second element the dst-switch of the path.
- * @param failedSwitch the switchId if the route changes are for a failed switch,
- * otherwise null
- */
- private void processHashGroupChangeForFailure(Set<ArrayList<DeviceId>> routeChanges,
- DeviceId failedSwitch) {
- // first, ensure each routeChanges entry has two elements
- Set<ArrayList<DeviceId>> changedRoutes = getAllExpandedRoutes(routeChanges);
- boolean someFailed = false;
- boolean success;
- Set<DeviceId> updatedDevices = Sets.newHashSet();
- for (ArrayList<DeviceId> route : changedRoutes) {
- DeviceId targetSw = route.get(0);
- DeviceId dstSw = route.get(1);
- success = fixHashGroupsForRoute(route, true);
- // it's possible that we cannot fix hash groups for a route
- // if the target switch has failed. Nevertheless the ecmp graph
- // for the impacted switch must still be updated.
- if (!success && failedSwitch != null && targetSw.equals(failedSwitch)) {
- currentEcmpSpgMap.put(dstSw, updatedEcmpSpgMap.get(dstSw));
- currentEcmpSpgMap.remove(targetSw);
- log.debug("Updating ECMPspg for dst:{} removing failed switch "
- + "target:{}", dstSw, targetSw);
- updatedDevices.add(targetSw);
- updatedDevices.add(dstSw);
- continue;
-
- }
- //linkfailed - update both sides
- if (success) {
- currentEcmpSpgMap.put(targetSw, updatedEcmpSpgMap.get(targetSw));
- currentEcmpSpgMap.put(dstSw, updatedEcmpSpgMap.get(dstSw));
- log.debug("Updating ECMPspg for dst:{} and target:{} for linkdown"
- + " or switchdown", dstSw, targetSw);
- updatedDevices.add(targetSw);
- updatedDevices.add(dstSw);
- } else {
- someFailed = true;
- }
- }
- if (!someFailed) {
- // here is where we update all devices not touched by this instance
- updatedEcmpSpgMap.keySet().stream()
- .filter(devId -> !updatedDevices.contains(devId))
- .forEach(devId -> {
- currentEcmpSpgMap.put(devId, updatedEcmpSpgMap.get(devId));
- log.debug("Updating ECMPspg for remaining dev:{}", devId);
- });
- }
- }
-
- /**
- * Processes a set a route-path changes due to link up by editing hash groups.
- *
- * @param routeChanges a set of route-path changes, where each route-path is
- * a list with its first element the src-switch of the path
- * and the second element the dst-switch of the path.
- * @return set of changed routes
- */
- private Set<ArrayList<DeviceId>> processHashGroupChangeForLinkUp(Set<ArrayList<DeviceId>> routeChanges) {
- // Stores changed routes
- Set<ArrayList<DeviceId>> doneRoutes = new HashSet<>();
- // first, ensure each routeChanges entry has two elements
- Set<ArrayList<DeviceId>> changedRoutes = getAllExpandedRoutes(routeChanges);
- boolean someFailed = false;
- boolean success;
- Set<DeviceId> updatedDevices = Sets.newHashSet();
- for (ArrayList<DeviceId> route : changedRoutes) {
- DeviceId targetSw = route.get(0);
- DeviceId dstSw = route.get(1);
- // linkup - fix (if possible)
- success = fixHashGroupsForRoute(route, false);
- if (success) {
- currentEcmpSpgMap.put(targetSw, updatedEcmpSpgMap.get(targetSw));
- currentEcmpSpgMap.put(dstSw, updatedEcmpSpgMap.get(dstSw));
- log.debug("Updating ECMPspg for target:{} and dst:{} for linkup",
- targetSw, dstSw);
- updatedDevices.add(targetSw);
- updatedDevices.add(dstSw);
- doneRoutes.add(route);
- } else {
- someFailed = true;
- }
-
- }
- if (!someFailed) {
- // here is where we update all devices not touched by this instance
- updatedEcmpSpgMap.keySet().stream()
- .filter(devId -> !updatedDevices.contains(devId))
- .forEach(devId -> {
- currentEcmpSpgMap.put(devId, updatedEcmpSpgMap.get(devId));
- log.debug("Updating ECMPspg for remaining dev:{}", devId);
- });
- }
- return doneRoutes;
- }
-
- /**
- * Edits hash groups in the src-switch (targetSw) of a route-path by
- * calling the groupHandler to either add or remove buckets in an existing
- * hash group.
- *
- * @param route a single list representing a route-path where the first element
- * is the src-switch (targetSw) of the route-path and the
- * second element is the dst-switch
- * @param revoke true if buckets in the hash-groups need to be removed;
- * false if buckets in the hash-groups need to be added
- * @return true if the hash group editing is successful
- */
- private boolean fixHashGroupsForRoute(ArrayList<DeviceId> route,
- boolean revoke) {
- DeviceId targetSw = route.get(0);
- if (route.size() < 2) {
- log.warn("Cannot fixHashGroupsForRoute - no dstSw in route {}", route);
- return false;
- }
- DeviceId destSw = route.get(1);
- if (!seenBeforeRoutes.containsEntry(destSw, targetSw)) {
- log.warn("Cannot fixHashGroupsForRoute {} -> {} has not been programmed before",
- targetSw, destSw);
- return false;
- }
- log.debug("* processing fixHashGroupsForRoute: Target {} -> Dest {}",
- targetSw, destSw);
- // figure out the new next hops at the targetSw towards the destSw
- Set<DeviceId> nextHops = getNextHops(targetSw, destSw);
- // call group handler to change hash group at targetSw
- DefaultGroupHandler grpHandler = srManager.getGroupHandler(targetSw);
- if (grpHandler == null) {
- log.warn("Cannot find grouphandler for dev:{} .. aborting"
- + " {} hash group buckets for route:{} ", targetSw,
- (revoke) ? "revoke" : "repopulate", route);
- return false;
- }
- log.debug("{} hash-groups buckets For Route {} -> {} to new next-hops {}",
- (revoke) ? "revoke" : "repopulating",
- targetSw, destSw, nextHops);
- return (revoke) ? grpHandler.fixHashGroups(targetSw, nextHops,
- destSw, true)
- : grpHandler.fixHashGroups(targetSw, nextHops,
- destSw, false);
- }
-
- /**
- * Start the flow rule population process if it was never started. The
- * process finishes successfully when all flow rules are set and stops with
- * ABORTED status when any groups required for flows is not set yet.
- */
- public void startPopulationProcess() {
- statusLock.lock();
- try {
- if (populationStatus == Status.IDLE
- || populationStatus == Status.SUCCEEDED
- || populationStatus == Status.ABORTED) {
- populateAllRoutingRules();
- } else {
- log.warn("Not initiating startPopulationProcess as populationStatus is {}",
- populationStatus);
- }
- } finally {
- statusLock.unlock();
- }
- }
-
- /**
- * Revoke rules of given subnet in all edge switches.
- *
- * @param subnets subnet being removed
- * @return true if succeed
- */
- protected boolean revokeSubnet(Set<IpPrefix> subnets) {
- DeviceId targetSw;
- List<Future<Boolean>> futures = Lists.newArrayList();
- for (Device sw : srManager.deviceService.getAvailableDevices()) {
- targetSw = sw.id();
- if (shouldProgram(targetSw)) {
- futures.add(routePopulators.submit(new RevokeSubnet(targetSw, subnets)));
- } else {
- futures.add(CompletableFuture.completedFuture(true));
- }
- }
- // check the execution of each job
- return checkJobs(futures);
- }
-
- /**
- * Revoke rules of given subnets in the given switches.
- *
- * @param targetSwitches switched from which subnets to be removed
- * @param subnets subnet bring removed
- * @return true if succeed
- */
- protected boolean revokeSubnet(Set<DeviceId> targetSwitches, Set<IpPrefix> subnets) {
- List<Future<Boolean>> futures = Lists.newArrayList();
- for (DeviceId targetSw : targetSwitches) {
- if (shouldProgram(targetSw)) {
- futures.add(routePopulators.submit(new RevokeSubnet(targetSw, subnets)));
- } else {
- futures.add(CompletableFuture.completedFuture(true));
- }
- }
- // check the execution of each job
- return checkJobs(futures);
- }
-
- private final class RevokeSubnet implements PickyCallable<Boolean> {
- private DeviceId targetSw;
- private Set<IpPrefix> subnets;
-
- /**
- * Builds a RevokeSubnet task, which provides a result.
- *
- * @param subnets a set of prefixes
- * @param targetSw target switch
- */
- RevokeSubnet(DeviceId targetSw, Set<IpPrefix> subnets) {
- this.targetSw = targetSw;
- this.subnets = subnets;
- }
-
- @Override
- public Boolean call() throws Exception {
- return srManager.routingRulePopulator.revokeIpRuleForSubnet(targetSw, subnets);
- }
-
- @Override
- public int hint() {
- return targetSw.hashCode();
- }
- }
-
- /**
- * Populates IP rules for a route that has direct connection to the switch
- * if the current instance is the master of the switch.
- *
- * @param deviceId device ID of the device that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param hostVlanId Vlan ID of the nexthop
- * @param outPort port where the next hop attaches to
- * @param directHost host is of type direct or indirect
- * @return future that includes the flow objective if succeeded, null if otherwise
- */
- CompletableFuture<Objective> populateRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
- VlanId hostVlanId, PortNumber outPort, boolean directHost) {
- if (shouldProgram(deviceId)) {
- return srManager.routingRulePopulator.populateRoute(deviceId, prefix,
- hostMac, hostVlanId, outPort, directHost);
- }
- return CompletableFuture.completedFuture(null);
- }
-
- /**
- * Removes IP rules for a route when the next hop is gone.
- * if the current instance is the master of the switch.
- *
- * @param deviceId device ID of the device that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param hostVlanId Vlan ID of the nexthop
- * @param outPort port that next hop attaches to
- * @param directHost host is of type direct or indirect
- * @return future that carries the flow objective if succeeded, null if otherwise
- */
- CompletableFuture<Objective> revokeRoute(DeviceId deviceId, IpPrefix prefix,
- MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
- if (shouldProgram(deviceId)) {
- return srManager.routingRulePopulator.revokeRoute(deviceId, prefix, hostMac, hostVlanId,
- outPort, directHost);
- }
- return CompletableFuture.completedFuture(null);
- }
-
- CompletableFuture<Objective> populateBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
- if (shouldProgram(deviceId)) {
- return srManager.routingRulePopulator.populateBridging(deviceId, port, mac, vlanId);
- }
- return CompletableFuture.completedFuture(null);
- }
-
- CompletableFuture<Objective> revokeBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
- if (shouldProgram(deviceId)) {
- return srManager.routingRulePopulator.revokeBridging(deviceId, port, mac, vlanId);
- }
- return CompletableFuture.completedFuture(null);
- }
-
- void updateBridging(DeviceId deviceId, PortNumber portNum, MacAddress hostMac,
- VlanId vlanId, boolean popVlan, boolean install) {
- if (shouldProgram(deviceId)) {
- srManager.routingRulePopulator.updateBridging(deviceId, portNum, hostMac, vlanId, popVlan, install);
- }
- }
-
- void updateFwdObj(DeviceId deviceId, PortNumber portNumber, IpPrefix prefix, MacAddress hostMac,
- VlanId vlanId, boolean popVlan, boolean install) {
- if (shouldProgram(deviceId)) {
- srManager.routingRulePopulator.updateFwdObj(deviceId, portNumber, prefix, hostMac,
- vlanId, popVlan, install);
- }
- }
-
- /**
- * Populates IP rules for a route when the next hop is double-tagged.
- *
- * @param deviceId device ID that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param innerVlan Inner Vlan ID of the next hop
- * @param outerVlan Outer Vlan ID of the next hop
- * @param outerTpid Outer TPID of the next hop
- * @param outPort port that the next hop attaches to
- */
- void populateDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac, VlanId innerVlan,
- VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
- if (srManager.mastershipService.isLocalMaster(deviceId)) {
- srManager.routingRulePopulator.populateDoubleTaggedRoute(
- deviceId, prefix, hostMac, innerVlan, outerVlan, outerTpid, outPort);
- srManager.routingRulePopulator.processDoubleTaggedFilter(
- deviceId, outPort, outerVlan, innerVlan, true);
- }
- }
-
- /**
- * Revokes IP rules for a route when the next hop is double-tagged.
- *
- * @param deviceId device ID that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param innerVlan Inner Vlan ID of the next hop
- * @param outerVlan Outer Vlan ID of the next hop
- * @param outerTpid Outer TPID of the next hop
- * @param outPort port that the next hop attaches to
- */
- void revokeDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac, VlanId innerVlan,
- VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
- // Revoke route either if this node have the mastership (when device is available) or
- // if this node is the leader (even when device is unavailable)
- if (!srManager.mastershipService.isLocalMaster(deviceId)) {
- if (srManager.deviceService.isAvailable(deviceId)) {
- // Master node will revoke specified rule.
- log.debug("This node is not a master for {}, stop revoking route.", deviceId);
- return;
- }
-
- // isLocalMaster will return false when the device is unavailable.
- // Verify if this node is the leader in that case.
- NodeId leader = srManager.leadershipService.runForLeadership(
- deviceId.toString()).leaderNodeId();
- if (!srManager.clusterService.getLocalNode().id().equals(leader)) {
- // Leader node will revoke specified rule.
- log.debug("This node is not a master for {}, stop revoking route.", deviceId);
- return;
- }
- }
-
- srManager.routingRulePopulator.revokeDoubleTaggedRoute(deviceId, prefix, hostMac,
- innerVlan, outerVlan, outerTpid, outPort);
- srManager.routingRulePopulator.processDoubleTaggedFilter(deviceId, outPort, outerVlan, innerVlan, false);
- }
-
- /**
- * Purges seen before routes for a given device.
- * @param deviceId the device id
- */
- void purgeSeenBeforeRoutes(DeviceId deviceId) {
- log.debug("Purging seen before routes having as target {}", deviceId);
- Set<Entry<DeviceId, DeviceId>> routesToPurge = seenBeforeRoutes.stream()
- .filter(entry -> entry.getValue().equals(deviceId))
- .collect(Collectors.toSet());
- routesToPurge.forEach(entry -> seenBeforeRoutes.remove(entry.getKey(), entry.getValue()));
- }
-
- /**
- * Remove ECMP graph entry for the given device. Typically called when
- * device is no longer available.
- *
- * @param deviceId the device for which graphs need to be purged
- */
- void purgeEcmpGraph(DeviceId deviceId) {
- statusLock.lock();
- try {
- if (populationStatus == Status.STARTED) {
- log.warn("Previous rule population is not finished. Cannot"
- + " proceeed with purgeEcmpGraph for {}", deviceId);
- return;
- }
- log.debug("Updating ECMPspg for unavailable dev:{}", deviceId);
- currentEcmpSpgMap.remove(deviceId);
- if (updatedEcmpSpgMap != null) {
- updatedEcmpSpgMap.remove(deviceId);
- }
- } finally {
- statusLock.unlock();
- }
- }
-
- /**
- * Attempts a full reroute of route-paths if topology has changed relatively
- * close to a mastership change event. Does not do a reroute if mastership
- * change is due to reasons other than a ONOS cluster event - for example a
- * call to balance-masters, or a switch up/down event.
- *
- * @param devId the device identifier for which mastership has changed
- * @param me the mastership event
- */
- void checkFullRerouteForMasterChange(DeviceId devId, MastershipEvent me) {
- // give small delay to absorb mastership events that are caused by
- // device that has disconnected from cluster
- executorServiceMstChg.schedule(new MasterChange(devId, me),
- MASTER_CHANGE_DELAY, TimeUnit.MILLISECONDS);
- }
-
- protected final class MasterChange implements Runnable {
- private DeviceId devId;
- private MastershipEvent me;
- private static final long CLUSTER_EVENT_THRESHOLD = 4500; // ms
- private static final long DEVICE_EVENT_THRESHOLD = 2000; // ms
- private static final long EDGE_PORT_EVENT_THRESHOLD = 10000; //ms
- private static final long FULL_REROUTE_THRESHOLD = 10000; // ms
-
- MasterChange(DeviceId devId, MastershipEvent me) {
- this.devId = devId;
- this.me = me;
- }
-
- @Override
- public void run() {
- long lce = srManager.clusterListener.timeSinceLastClusterEvent();
- boolean clusterEvent = lce < CLUSTER_EVENT_THRESHOLD;
-
- // ignore event for lost switch if cluster event hasn't happened -
- // device down event will handle it
- if ((me.roleInfo().master() == null
- || !srManager.deviceService.isAvailable(devId))
- && !clusterEvent) {
- log.debug("Full reroute not required for lost device: {}/{} "
- + "clusterEvent/timeSince: {}/{}",
- devId, me.roleInfo(), clusterEvent, lce);
- return;
- }
-
- long update = srManager.deviceService.getLastUpdatedInstant(devId);
- long lde = Instant.now().toEpochMilli() - update;
- boolean deviceEvent = lde < DEVICE_EVENT_THRESHOLD;
-
- // ignore event for recently connected switch if cluster event hasn't
- // happened - link up events will handle it
- if (srManager.deviceService.isAvailable(devId) && deviceEvent
- && !clusterEvent) {
- log.debug("Full reroute not required for recently available"
- + " device: {}/{} deviceEvent/timeSince: {}/{} "
- + "clusterEvent/timeSince: {}/{}",
- devId, me.roleInfo(), deviceEvent, lde, clusterEvent, lce);
- return;
- }
-
- long lepe = Instant.now().toEpochMilli()
- - srManager.lastEdgePortEvent.toEpochMilli();
- boolean edgePortEvent = lepe < EDGE_PORT_EVENT_THRESHOLD;
-
- // if it gets here, then mastership change is likely due to onos
- // instance failure, or network partition in onos cluster
- // normally a mastership change like this does not require re-programming
- // but if topology changes happen at the same time then we may miss events
- if (!isRoutingStable() && clusterEvent) {
- log.warn("Mastership changed for dev: {}/{} while programming route-paths "
- + "due to clusterEvent {} ms ago .. attempting full reroute",
- devId, me.roleInfo(), lce);
- if (srManager.mastershipService.isLocalMaster(devId)) {
- // old master could have died when populating filters
- populatePortAddressingRules(devId);
- }
- // old master could have died when creating groups
- // XXX right now we have no fine-grained way to only make changes
- // for the route paths affected by this device. Thus we do a
- // full reroute after purging all hash groups. We also try to do
- // it only once, irrespective of the number of devices
- // that changed mastership when their master instance died.
- long lfrr = Instant.now().toEpochMilli() - lastFullReroute.toEpochMilli();
- boolean doFullReroute = lfrr > FULL_REROUTE_THRESHOLD;
- if (doFullReroute) {
- lastFullReroute = Instant.now();
- for (Device dev : srManager.deviceService.getDevices()) {
- if (shouldProgram(dev.id())) {
- srManager.purgeHashedNextObjectiveStore(dev.id());
- seenBeforeRoutes.removeAll(dev.id());
- }
- }
- // give small delay to ensure entire store is purged
- executorServiceFRR.schedule(new FullRerouteAfterPurge(),
- PURGE_DELAY,
- TimeUnit.MILLISECONDS);
- } else {
- log.warn("Full reroute attempted {} ms ago .. skipping", lfrr);
- }
-
- } else if (edgePortEvent && clusterEvent) {
- log.warn("Mastership changed for dev: {}/{} due to clusterEvent {} ms ago "
- + "while edge-port event happened {} ms ago "
- + " .. reprogramming all edge-ports",
- devId, me.roleInfo(), lce, lepe);
- if (shouldProgram(devId)) {
- srManager.deviceService.getPorts(devId).stream()
- .filter(p -> srManager.interfaceService
- .isConfigured(new ConnectPoint(devId, p.number())))
- .forEach(p -> srManager.processPortUpdated(devId, p));
- }
-
- } else {
- log.debug("Stable route-paths .. full reroute not attempted for "
- + "mastership change {}/{} deviceEvent/timeSince: {}/{} "
- + "clusterEvent/timeSince: {}/{}", devId, me.roleInfo(),
- deviceEvent, lde, clusterEvent, lce);
- }
- }
- }
-
- /**
- * Performs a full reroute of routing rules in all the switches. Assumes
- * caller has purged hash groups from the nextObjective store, otherwise
- * re-uses ones available in the store.
- */
- protected final class FullRerouteAfterPurge implements Runnable {
- @Override
- public void run() {
- populateAllRoutingRules();
- }
- }
-
-
- //////////////////////////////////////
- // Routing helper methods and classes
- //////////////////////////////////////
-
- /**
- * Computes set of affected routes due to failed link. Assumes previous ecmp
- * shortest-path graph exists for a switch in order to compute affected
- * routes. If such a graph does not exist, the method returns null.
- *
- * @param linkFail the failed link
- * @return the set of affected routes which may be empty if no routes were
- * affected
- */
- private Set<ArrayList<DeviceId>> computeDamagedRoutes(Link linkFail) {
- Set<ArrayList<DeviceId>> routes = new HashSet<>();
-
- for (Device sw : srManager.deviceService.getDevices()) {
- log.debug("Computing the impacted routes for device {} due to link fail",
- sw.id());
- if (!shouldProgram(sw.id())) {
- lastProgrammed.remove(sw.id());
- continue;
- }
- for (DeviceId rootSw : deviceAndItsPair(sw.id())) {
- // check for mastership change since last run
- if (!lastProgrammed.contains(sw.id())) {
- log.warn("New responsibility for this node to program dev:{}"
- + " ... nuking current ECMPspg", sw.id());
- currentEcmpSpgMap.remove(sw.id());
- }
- lastProgrammed.add(sw.id());
-
- EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(rootSw);
- if (ecmpSpg == null) {
- log.warn("No existing ECMP graph for switch {}. Assuming "
- + "all route-paths have changed towards it.", rootSw);
- for (DeviceId targetSw : srManager.deviceConfiguration.getRouters()) {
- if (targetSw.equals(rootSw)) {
- continue;
- }
- routes.add(Lists.newArrayList(targetSw, rootSw));
- log.debug("Impacted route:{}->{}", targetSw, rootSw);
- }
- continue;
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Root switch: {}", rootSw);
- log.debug(" Current/Existing SPG: {}", ecmpSpg);
- log.debug(" New/Updated SPG: {}", updatedEcmpSpgMap.get(rootSw));
- }
- HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>>
- switchVia = ecmpSpg.getAllLearnedSwitchesAndVia();
- // figure out if the broken link affected any route-paths in this graph
- for (Integer itrIdx : switchVia.keySet()) {
- log.trace("Current/Exiting SPG Iterindex# {}", itrIdx);
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
- switchVia.get(itrIdx);
- for (DeviceId targetSw : swViaMap.keySet()) {
- log.trace("TargetSwitch {} --> RootSwitch {}",
- targetSw, rootSw);
- for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
- log.trace(" Via:");
- via.forEach(e -> log.trace(" {}", e));
- }
- Set<ArrayList<DeviceId>> subLinks =
- computeLinks(targetSw, rootSw, swViaMap);
- for (ArrayList<DeviceId> alink: subLinks) {
- if ((alink.get(0).equals(linkFail.src().deviceId()) &&
- alink.get(1).equals(linkFail.dst().deviceId()))
- ||
- (alink.get(0).equals(linkFail.dst().deviceId()) &&
- alink.get(1).equals(linkFail.src().deviceId()))) {
- log.debug("Impacted route:{}->{}", targetSw, rootSw);
- ArrayList<DeviceId> aRoute = new ArrayList<>();
- aRoute.add(targetSw); // switch with rules to populate
- aRoute.add(rootSw); // towards this destination
- routes.add(aRoute);
- break;
- }
- }
- }
- }
-
- }
-
- }
- return routes;
- }
-
- /**
- * Computes set of affected routes due to new links or failed switches.
- *
- * @param failedSwitch deviceId of failed switch if any
- * @return the set of affected routes which may be empty if no routes were
- * affected
- */
- private Set<ArrayList<DeviceId>> computeRouteChange(DeviceId failedSwitch) {
- ImmutableSet.Builder<ArrayList<DeviceId>> changedRtBldr =
- ImmutableSet.builder();
-
- for (Device sw : srManager.deviceService.getDevices()) {
- log.debug("Computing the impacted routes for device {}", sw.id());
- if (!shouldProgram(sw.id())) {
- lastProgrammed.remove(sw.id());
- continue;
- }
- for (DeviceId rootSw : deviceAndItsPair(sw.id())) {
- if (log.isTraceEnabled()) {
- log.trace("Device links for dev: {}", rootSw);
- for (Link link: srManager.linkService.getDeviceLinks(rootSw)) {
- log.trace("{} -> {} ", link.src().deviceId(),
- link.dst().deviceId());
- }
- }
- // check for mastership change since last run
- if (!lastProgrammed.contains(sw.id())) {
- log.warn("New responsibility for this node to program dev:{}"
- + " ... nuking current ECMPspg", sw.id());
- currentEcmpSpgMap.remove(sw.id());
- }
- lastProgrammed.add(sw.id());
- EcmpShortestPathGraph currEcmpSpg = currentEcmpSpgMap.get(rootSw);
- if (currEcmpSpg == null) {
- log.debug("No existing ECMP graph for device {}.. adding self as "
- + "changed route", rootSw);
- changedRtBldr.add(Lists.newArrayList(rootSw));
- continue;
- }
- EcmpShortestPathGraph newEcmpSpg = updatedEcmpSpgMap.get(rootSw);
- if (newEcmpSpg == null) {
- log.warn("Cannot find updated ECMP graph for dev:{}", rootSw);
- continue;
- }
- if (log.isDebugEnabled()) {
- log.debug("Root switch: {}", rootSw);
- log.debug(" Current/Existing SPG: {}", currEcmpSpg);
- log.debug(" New/Updated SPG: {}", newEcmpSpg);
- }
- // first use the updated/new map to compare to current/existing map
- // as new links may have come up
- changedRtBldr.addAll(compareGraphs(newEcmpSpg, currEcmpSpg, rootSw));
- // then use the current/existing map to compare to updated/new map
- // as switch may have been removed
- changedRtBldr.addAll(compareGraphs(currEcmpSpg, newEcmpSpg, rootSw));
- }
- }
-
- // handle clearing state for a failed switch in case the switch does
- // not have a pair, or the pair is not available
- if (failedSwitch != null) {
- Optional<DeviceId> pairDev = srManager.getPairDeviceId(failedSwitch);
- if (!pairDev.isPresent() || !srManager.deviceService.isAvailable(pairDev.get())) {
- log.debug("Proxy Route changes to downed Sw:{}", failedSwitch);
- srManager.deviceService.getDevices().forEach(dev -> {
- if (!dev.id().equals(failedSwitch) &&
- srManager.mastershipService.isLocalMaster(dev.id())) {
- log.debug(" : {}", dev.id());
- changedRtBldr.add(Lists.newArrayList(dev.id(), failedSwitch));
- }
- });
- }
- }
-
- Set<ArrayList<DeviceId>> changedRoutes = changedRtBldr.build();
- for (ArrayList<DeviceId> route: changedRoutes) {
- log.debug("Route changes Target -> Root");
- if (route.size() == 1) {
- log.debug(" : all -> {}", route.get(0));
- } else {
- log.debug(" : {} -> {}", route.get(0), route.get(1));
- }
- }
- return changedRoutes;
- }
-
- // Utility method to expands the route changes in two elements array using
- // the ECMP graph. Caller represents all to dst switch routes with an
- // array containing only the dst switch.
- private Set<ArrayList<DeviceId>> getExpandedRoutes(Set<ArrayList<DeviceId>> routeChanges) {
- Set<ArrayList<DeviceId>> changedRoutes = new HashSet<>();
- // Ensure each routeChanges entry has two elements
- for (ArrayList<DeviceId> route : routeChanges) {
- if (route.size() == 1) {
- DeviceId dstSw = route.get(0);
- EcmpShortestPathGraph ec = updatedEcmpSpgMap.get(dstSw);
- if (ec == null) {
- log.warn("No graph found for {} .. aborting redoRouting", dstSw);
- return Collections.emptySet();
- }
- ec.getAllLearnedSwitchesAndVia().keySet().forEach(key -> {
- ec.getAllLearnedSwitchesAndVia().get(key).keySet().forEach(target -> {
- changedRoutes.add(Lists.newArrayList(target, dstSw));
- });
- });
- } else {
- DeviceId targetSw = route.get(0);
- DeviceId dstSw = route.get(1);
- changedRoutes.add(Lists.newArrayList(targetSw, dstSw));
- }
- }
- return changedRoutes;
- }
-
- // Utility method to expands the route changes in two elements array using
- // the available devices. Caller represents all to dst switch routes with an
- // array containing only the dst switch.
- private Set<ArrayList<DeviceId>> getAllExpandedRoutes(Set<ArrayList<DeviceId>> routeChanges) {
- Set<ArrayList<DeviceId>> changedRoutes = new HashSet<>();
- // Ensure each routeChanges entry has two elements
- for (ArrayList<DeviceId> route : routeChanges) {
- if (route.size() == 1) {
- // route-path changes are from everyone else to this switch
- DeviceId dstSw = route.get(0);
- srManager.deviceService.getAvailableDevices().forEach(sw -> {
- if (!sw.id().equals(dstSw)) {
- changedRoutes.add(Lists.newArrayList(sw.id(), dstSw));
- }
- });
- } else {
- changedRoutes.add(route);
- }
- }
- return changedRoutes;
- }
-
- /**
- * For the root switch, searches all the target nodes reachable in the base
- * graph, and compares paths to the ones in the comp graph.
- *
- * @param base the graph that is indexed for all reachable target nodes
- * from the root node
- * @param comp the graph that the base graph is compared to
- * @param rootSw both ecmp graphs are calculated for the root node
- * @return all the routes that have changed in the base graph
- */
- private Set<ArrayList<DeviceId>> compareGraphs(EcmpShortestPathGraph base,
- EcmpShortestPathGraph comp,
- DeviceId rootSw) {
- ImmutableSet.Builder<ArrayList<DeviceId>> changedRoutesBuilder =
- ImmutableSet.builder();
- HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> baseMap =
- base.getAllLearnedSwitchesAndVia();
- HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> compMap =
- comp.getAllLearnedSwitchesAndVia();
- for (Integer itrIdx : baseMap.keySet()) {
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> baseViaMap =
- baseMap.get(itrIdx);
- for (DeviceId targetSw : baseViaMap.keySet()) {
- ArrayList<ArrayList<DeviceId>> basePath = baseViaMap.get(targetSw);
- ArrayList<ArrayList<DeviceId>> compPath = getVia(compMap, targetSw);
- if ((compPath == null) || !basePath.equals(compPath)) {
- log.trace("Impacted route:{} -> {}", targetSw, rootSw);
- ArrayList<DeviceId> route = new ArrayList<>();
- route.add(targetSw); // switch with rules to populate
- route.add(rootSw); // towards this destination
- changedRoutesBuilder.add(route);
- }
- }
- }
- return changedRoutesBuilder.build();
- }
-
- /**
- * Returns the ECMP paths traversed to reach the target switch.
- *
- * @param switchVia a per-iteration view of the ECMP graph for a root switch
- * @param targetSw the switch to reach from the root switch
- * @return the nodes traversed on ECMP paths to the target switch
- */
- private ArrayList<ArrayList<DeviceId>> getVia(HashMap<Integer, HashMap<DeviceId,
- ArrayList<ArrayList<DeviceId>>>> switchVia, DeviceId targetSw) {
- for (Integer itrIdx : switchVia.keySet()) {
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
- switchVia.get(itrIdx);
- if (swViaMap.get(targetSw) == null) {
- continue;
- } else {
- return swViaMap.get(targetSw);
- }
- }
-
- return null;
- }
-
- /**
- * Utility method to break down a path from src to dst device into a collection
- * of links.
- *
- * @param src src device of the path
- * @param dst dst device of the path
- * @param viaMap path taken from src to dst device
- * @return collection of links in the path
- */
- private Set<ArrayList<DeviceId>> computeLinks(DeviceId src,
- DeviceId dst,
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> viaMap) {
- Set<ArrayList<DeviceId>> subLinks = Sets.newHashSet();
- for (ArrayList<DeviceId> via : viaMap.get(src)) {
- DeviceId linkSrc = src;
- DeviceId linkDst = dst;
- for (DeviceId viaDevice: via) {
- ArrayList<DeviceId> link = new ArrayList<>();
- linkDst = viaDevice;
- link.add(linkSrc);
- link.add(linkDst);
- subLinks.add(link);
- linkSrc = viaDevice;
- }
- ArrayList<DeviceId> link = new ArrayList<>();
- link.add(linkSrc);
- link.add(dst);
- subLinks.add(link);
- }
-
- return subLinks;
- }
-
- /**
- * Determines whether this controller instance should program the
- * given {@code deviceId}, based on mastership and pairDeviceId if one exists.
- * <p>
- * Once an instance is elected, it will be the only instance responsible for programming
- * both devices in the pair until it goes down.
- *
- * @param deviceId device identifier to consider for routing
- * @return true if current instance should handle the routing for given device
- */
- boolean shouldProgram(DeviceId deviceId) {
- Boolean cached = shouldProgramCache.get(deviceId);
- if (cached != null) {
- log.debug("shouldProgram dev:{} cached:{}", deviceId, cached);
- return cached;
- }
-
- Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(deviceId);
-
- NodeId currentNodeId = srManager.clusterService.getLocalNode().id();
- NodeId masterNodeId = srManager.mastershipService.getMasterFor(deviceId);
- Optional<NodeId> pairMasterNodeId = pairDeviceId.map(srManager.mastershipService::getMasterFor);
- log.debug("Evaluate shouldProgram {}/pair={}. currentNodeId={}, master={}, pairMaster={}",
- deviceId, pairDeviceId, currentNodeId, masterNodeId, pairMasterNodeId);
-
- // No pair device configured. Only handle when current instance is the master of the device
- if (!pairDeviceId.isPresent()) {
- log.debug("No pair device. currentNodeId={}, master={}", currentNodeId, masterNodeId);
- return currentNodeId.equals(masterNodeId);
- }
-
- // Should not handle if current instance is not the master of either switch
- if (!currentNodeId.equals(masterNodeId) &&
- !(pairMasterNodeId.isPresent() && currentNodeId.equals(pairMasterNodeId.get()))) {
- log.debug("Current nodeId {} is neither the master of target device {} nor pair device {}",
- currentNodeId, deviceId, pairDeviceId);
- return false;
- }
-
- Set<DeviceId> key = Sets.newHashSet(deviceId, pairDeviceId.get());
-
- NodeId king = shouldProgram.compute(key, ((k, v) -> {
- if (v == null) {
- // There is no value in the map. Elect a node
- return elect(Lists.newArrayList(masterNodeId, pairMasterNodeId.orElse(null)));
- } else {
- if (v.equals(masterNodeId) || v.equals(pairMasterNodeId.orElse(null))) {
- // Use the node in the map if it is still alive and is a master of any of the two switches
- return v;
- } else {
- // Previously elected node is no longer the master of either switch. Re-elect a node.
- return elect(Lists.newArrayList(masterNodeId, pairMasterNodeId.orElse(null)));
- }
- }
- }));
-
- if (king != null) {
- log.debug("{} is king, should handle routing for {}/pair={}", king, deviceId, pairDeviceId);
- shouldProgramCache.put(deviceId, king.equals(currentNodeId));
- return king.equals(currentNodeId);
- } else {
- log.error("Fail to elect a king for {}/pair={}. Abort.", deviceId, pairDeviceId);
- shouldProgramCache.remove(deviceId);
- return false;
- }
- }
-
- /**
- * Elects a node who should take responsibility of programming devices.
- * @param nodeIds list of candidate node ID
- *
- * @return NodeId of the node that gets elected, or null if none of the node can be elected
- */
- private NodeId elect(List<NodeId> nodeIds) {
- // Remove all null elements. This could happen when some device has no master
- nodeIds.removeAll(Collections.singleton(null));
- nodeIds.sort(null);
- return nodeIds.size() == 0 ? null : nodeIds.get(0);
- }
-
- void invalidateShouldProgramCache(DeviceId deviceId) {
- shouldProgramCache.remove(deviceId);
- }
-
- /**
- * Returns a set of device ID, containing given device and its pair device if exist.
- *
- * @param deviceId Device ID
- * @return a set of device ID, containing given device and its pair device if exist.
- */
- private Set<DeviceId> deviceAndItsPair(DeviceId deviceId) {
- Set<DeviceId> ret = Sets.newHashSet(deviceId);
- srManager.getPairDeviceId(deviceId).ifPresent(ret::add);
- return ret;
- }
-
- /**
- * Returns the set of deviceIds which are the next hops from the targetSw
- * to the dstSw according to the latest ECMP spg.
- *
- * @param targetSw the switch for which the next-hops are desired
- * @param dstSw the switch to which the next-hops lead to from the targetSw
- * @return set of next hop deviceIds, could be empty if no next hops are found
- */
- private Set<DeviceId> getNextHops(DeviceId targetSw, DeviceId dstSw) {
- boolean targetIsEdge = false;
- try {
- targetIsEdge = srManager.deviceConfiguration.isEdgeDevice(targetSw);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + "Cannot determine if targetIsEdge {}.. "
- + "continuing to getNextHops", targetSw);
- }
-
- EcmpShortestPathGraph ecmpSpg = updatedEcmpSpgMap.get(dstSw);
- if (ecmpSpg == null) {
- log.debug("No ecmpSpg found for dstSw: {}", dstSw);
- return ImmutableSet.of();
- }
- HashMap<Integer,
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
- ecmpSpg.getAllLearnedSwitchesAndVia();
- for (Integer itrIdx : switchVia.keySet()) {
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
- switchVia.get(itrIdx);
- for (DeviceId target : swViaMap.keySet()) {
- if (!target.equals(targetSw)) {
- continue;
- }
- // optimization for spines to not use leaves to get
- // to a spine or other leaves. Also leaves should not use other
- // leaves to get to the destination
- if ((!targetIsEdge && itrIdx > 1) || targetIsEdge) {
- boolean pathdevIsEdge = false;
- for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
- log.debug("Evaluating next-hop in path: {}", via);
- for (DeviceId pathdev : via) {
- try {
- pathdevIsEdge = srManager.deviceConfiguration
- .isEdgeDevice(pathdev);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage());
- }
- if (pathdevIsEdge) {
- log.debug("Avoiding {} hop path for targetSw:{}"
- + " --> dstSw:{} which goes through an edge"
- + " device {} in path {}", itrIdx,
- targetSw, dstSw, pathdev, via);
- return ImmutableSet.of();
- }
- }
- }
- }
- Set<DeviceId> nextHops = new HashSet<>();
- for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
- if (via.isEmpty()) {
- // the dstSw is the next-hop from the targetSw
- nextHops.add(dstSw);
- } else {
- // first elem is next-hop in each ECMP path
- nextHops.add(via.get(0));
- }
- }
- log.debug("target {} --> dst: {} has next-hops:{}", targetSw,
- dstSw, nextHops);
- return nextHops;
- }
- }
- log.debug("No next hops found for target:{} --> dst: {}", targetSw, dstSw);
- return ImmutableSet.of(); //no next-hops found
- }
-
- //////////////////////////////////////
- // Filtering rule creation
- //////////////////////////////////////
-
- /**
- * Populates filtering rules for port, and punting rules
- * for gateway IPs, loopback IPs and arp/ndp traffic.
- * Should only be called by the master instance for this device/port.
- *
- * @param deviceId Switch ID to set the rules
- */
- void populatePortAddressingRules(DeviceId deviceId) {
- // Although device is added, sometimes device store does not have the
- // ports for this device yet. It results in missing filtering rules in the
- // switch. We will attempt it a few times. If it still does not work,
- // user can manually repopulate using CLI command sr-reroute-network
- PortFilterInfo firstRun = rulePopulator.populateVlanMacFilters(deviceId);
- if (firstRun == null) {
- firstRun = new PortFilterInfo(0, 0, 0);
- }
- executorService.schedule(new RetryFilters(deviceId, firstRun),
- RETRY_INTERVAL_MS, TimeUnit.MILLISECONDS);
- }
-
- /**
- * RetryFilters populates filtering objectives for a device and keeps retrying
- * till the number of ports filtered are constant for a predefined number
- * of attempts.
- */
- protected final class RetryFilters implements Runnable {
- int constantAttempts = MAX_CONSTANT_RETRY_ATTEMPTS;
- DeviceId devId;
- int counter;
- PortFilterInfo prevRun;
-
- private RetryFilters(DeviceId deviceId, PortFilterInfo previousRun) {
- devId = deviceId;
- prevRun = previousRun;
- counter = 0;
- }
-
- @Override
- public void run() {
- log.debug("RETRY FILTER ATTEMPT {} ** dev:{}", ++counter, devId);
- PortFilterInfo thisRun = rulePopulator.populateVlanMacFilters(devId);
- boolean sameResult = prevRun.equals(thisRun);
- log.debug("dev:{} prevRun:{} thisRun:{} sameResult:{}", devId, prevRun,
- thisRun, sameResult);
- if (thisRun == null || !sameResult || (--constantAttempts > 0)) {
- // exponentially increasing intervals for retries
- executorService.schedule(this,
- RETRY_INTERVAL_MS * (int) Math.pow(counter, RETRY_INTERVAL_SCALE),
- TimeUnit.MILLISECONDS);
- if (!sameResult) {
- constantAttempts = MAX_CONSTANT_RETRY_ATTEMPTS; //reset
- }
- }
- prevRun = (thisRun == null) ? prevRun : thisRun;
- }
- }
-
- // Check jobs completion. It returns false if one of the job fails
- // and cancel the remaining
- private boolean checkJobs(List<Future<Boolean>> futures) {
- boolean completed = true;
- for (Future<Boolean> future : futures) {
- try {
- if (completed) {
- if (!future.get()) {
- completed = false;
- }
- } else {
- future.cancel(true);
- }
- } catch (InterruptedException | ExecutionException e) {
- completed = false;
- }
- }
- return completed;
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
deleted file mode 100644
index 0fd7c077..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import java.util.List;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Default Tunnel class.
- */
-public class DefaultTunnel implements Tunnel {
-
- private final String id;
- private final List<Integer> labelIds;
-
- private int groupId;
- private boolean allowedToRemoveGroup;
-
- /**
- * Creates a Tunnel reference.
- *
- * @param tid Tunnel ID
- * @param labelIds Label stack of the tunnel
- */
- public DefaultTunnel(String tid, List<Integer> labelIds) {
- this.id = checkNotNull(tid);
- this.labelIds = labelIds;
- //TODO: need to register the class in Kryo for this
- //this.labelIds = Collections.unmodifiableList(labelIds);
- this.groupId = -1;
- }
-
- /**
- * Creates a new DefaultTunnel reference using the tunnel reference.
- *
- * @param tunnel DefaultTunnel reference
- */
- public DefaultTunnel(DefaultTunnel tunnel) {
- this.id = tunnel.id;
- this.labelIds = tunnel.labelIds;
- this.groupId = tunnel.groupId;
- }
-
- @Override
- public String id() {
- return this.id;
- }
-
- @Override
- public List<Integer> labelIds() {
- return this.labelIds;
- }
-
- @Override
- public int groupId() {
- return this.groupId;
- }
-
- @Override
- public void setGroupId(int id) {
- this.groupId = id;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o instanceof DefaultTunnel) {
- DefaultTunnel tunnel = (DefaultTunnel) o;
- // We compare only the tunnel paths.
- if (tunnel.labelIds.equals(this.labelIds)) {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public int hashCode() {
- return labelIds.hashCode();
- }
-
- @Override
- public boolean isAllowedToRemoveGroup() {
- return this.allowedToRemoveGroup;
- }
-
- @Override
- public void allowToRemoveGroup(boolean b) {
- this.allowedToRemoveGroup = b;
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java
deleted file mode 100644
index 036044c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import org.onlab.graph.ScalarWeight;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.provider.ProviderId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Set;
-
-/**
- * This class creates breadth-first-search (BFS) tree for a given root device
- * and returns paths from the root Device to leaf Devices (target devices).
- * The paths are snapshot paths at the point of the class instantiation.
- */
-public class EcmpShortestPathGraph {
- LinkedList<DeviceId> deviceQueue = new LinkedList<>();
- LinkedList<Integer> distanceQueue = new LinkedList<>();
- HashMap<DeviceId, Integer> deviceSearched = new HashMap<>();
- HashMap<DeviceId, ArrayList<Link>> upstreamLinks = new HashMap<>();
- HashMap<DeviceId, ArrayList<Path>> paths = new HashMap<>();
- HashMap<Integer, ArrayList<DeviceId>> distanceDeviceMap = new HashMap<>();
- DeviceId rootDevice;
- private SegmentRoutingManager srManager;
- private static final Logger log = LoggerFactory.getLogger(EcmpShortestPathGraph.class);
-
- /**
- * Constructor.
- *
- * @param rootDevice root of the BFS tree
- * @param srManager SegmentRoutingManager object
- */
- public EcmpShortestPathGraph(DeviceId rootDevice, SegmentRoutingManager srManager) {
- this.rootDevice = rootDevice;
- this.srManager = srManager;
- calcECMPShortestPathGraph();
- }
-
- /**
- * Calculates the BFS tree.
- */
- private void calcECMPShortestPathGraph() {
- deviceQueue.add(rootDevice);
- int currDistance = 0;
- distanceQueue.add(currDistance);
- deviceSearched.put(rootDevice, currDistance);
- while (!deviceQueue.isEmpty()) {
- DeviceId sw = deviceQueue.poll();
- Set<DeviceId> prevSw = Sets.newHashSet();
- currDistance = distanceQueue.poll();
-
- for (Link link : srManager.linkHandler.getDeviceEgressLinks(sw)) {
- if (srManager.linkHandler.avoidLink(link)) {
- continue;
- }
- DeviceId reachedDevice = link.dst().deviceId();
- if (prevSw.contains(reachedDevice)) {
- // Ignore LAG links between the same set of Devices
- continue;
- } else {
- prevSw.add(reachedDevice);
- }
-
- Integer distance = deviceSearched.get(reachedDevice);
- if ((distance != null) && (distance < (currDistance + 1))) {
- continue;
- }
- if (distance == null) {
- // First time visiting this Device node
- deviceQueue.add(reachedDevice);
- distanceQueue.add(currDistance + 1);
- deviceSearched.put(reachedDevice, currDistance + 1);
-
- ArrayList<DeviceId> distanceSwArray = distanceDeviceMap
- .get(currDistance + 1);
- if (distanceSwArray == null) {
- distanceSwArray = new ArrayList<>();
- distanceSwArray.add(reachedDevice);
- distanceDeviceMap.put(currDistance + 1, distanceSwArray);
- } else {
- distanceSwArray.add(reachedDevice);
- }
- }
-
- ArrayList<Link> upstreamLinkArray =
- upstreamLinks.get(reachedDevice);
- if (upstreamLinkArray == null) {
- upstreamLinkArray = new ArrayList<>();
- upstreamLinkArray.add(copyDefaultLink(link));
- //upstreamLinkArray.add(link);
- upstreamLinks.put(reachedDevice, upstreamLinkArray);
- } else {
- // ECMP links
- upstreamLinkArray.add(copyDefaultLink(link));
- }
- }
- }
- }
-
- private void getDFSPaths(DeviceId dstDeviceDeviceId, Path path, ArrayList<Path> paths) {
- DeviceId rootDeviceDeviceId = rootDevice;
- for (Link upstreamLink : upstreamLinks.get(dstDeviceDeviceId)) {
- /* Deep clone the path object */
- Path sofarPath;
- ArrayList<Link> sofarLinks = new ArrayList<>();
- if (path != null && !path.links().isEmpty()) {
- sofarLinks.addAll(path.links());
- }
- sofarLinks.add(upstreamLink);
- sofarPath = new DefaultPath(ProviderId.NONE, sofarLinks, ScalarWeight.toWeight(0));
- if (upstreamLink.src().deviceId().equals(rootDeviceDeviceId)) {
- paths.add(sofarPath);
- return;
- } else {
- getDFSPaths(upstreamLink.src().deviceId(), sofarPath, paths);
- }
- }
- }
-
- /**
- * Return root Device for the graph.
- *
- * @return root Device
- */
- public DeviceId getRootDevice() {
- return rootDevice;
- }
-
- /**
- * Return the computed ECMP paths from the root Device to a given Device in
- * the network.
- *
- * @param targetDevice the target Device
- * @return the list of ECMP Paths from the root Device to the target Device
- */
- public ArrayList<Path> getECMPPaths(DeviceId targetDevice) {
- ArrayList<Path> pathArray = paths.get(targetDevice);
- if (pathArray == null && deviceSearched.containsKey(
- targetDevice)) {
- pathArray = new ArrayList<>();
- DeviceId sw = targetDevice;
- getDFSPaths(sw, null, pathArray);
- paths.put(targetDevice, pathArray);
- }
- return pathArray;
- }
-
- /**
- * Return the complete info of the computed ECMP paths for each Device
- * learned in multiple iterations from the root Device.
- *
- * @return the hash table of Devices learned in multiple Dijkstra
- * iterations and corresponding ECMP paths to it from the root
- * Device
- */
- public HashMap<Integer, HashMap<DeviceId,
- ArrayList<Path>>> getCompleteLearnedDeviceesAndPaths() {
-
- HashMap<Integer, HashMap<DeviceId, ArrayList<Path>>> pathGraph = new HashMap<>();
-
- for (Integer itrIndx : distanceDeviceMap.keySet()) {
- HashMap<DeviceId, ArrayList<Path>> swMap = new HashMap<>();
- for (DeviceId sw : distanceDeviceMap.get(itrIndx)) {
- swMap.put(sw, getECMPPaths(sw));
- }
- pathGraph.put(itrIndx, swMap);
- }
-
- return pathGraph;
- }
-
- /**
- * Returns the complete info of the computed ECMP paths for each target device
- * learned in multiple iterations from the root Device. The computed info
- * returned is per iteration (Integer key of outer HashMap). In each
- * iteration, for the target devices reached (DeviceId key of inner HashMap),
- * the ECMP paths are detailed (2D array).
- *
- * @return the hash table of target Devices learned in multiple Dijkstra
- * iterations and corresponding ECMP paths in terms of Devices to
- * be traversed (via) from the root Device to the target Device
- */
- public HashMap<Integer, HashMap<DeviceId,
- ArrayList<ArrayList<DeviceId>>>> getAllLearnedSwitchesAndVia() {
-
- HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> deviceViaMap = new HashMap<>();
-
- for (Integer itrIndx : distanceDeviceMap.keySet()) {
- HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swMap = new HashMap<>();
-
- for (DeviceId sw : distanceDeviceMap.get(itrIndx)) {
- ArrayList<ArrayList<DeviceId>> swViaArray = new ArrayList<>();
- for (Path path : getECMPPaths(sw)) {
- ArrayList<DeviceId> swVia = new ArrayList<>();
- for (Link link : path.links()) {
- if (link.src().deviceId().equals(rootDevice)) {
- /* No need to add the root Device again in
- * the Via list
- */
- continue;
- }
- swVia.add(link.src().deviceId());
- }
- swViaArray.add(swVia);
- }
- swMap.put(sw, swViaArray);
- }
- deviceViaMap.put(itrIndx, swMap);
- }
- return deviceViaMap;
- }
-
-
- private Link copyDefaultLink(Link link) {
- DefaultLink src = (DefaultLink) link;
- DefaultLink defaultLink = DefaultLink.builder()
- .providerId(src.providerId())
- .src(src.src())
- .dst(src.dst())
- .type(src.type())
- .annotations(src.annotations())
- .build();
-
- return defaultLink;
- }
-
- @Override
- public String toString() {
- StringBuilder sBuilder = new StringBuilder();
- for (Device device: srManager.deviceService.getDevices()) {
- if (!device.id().equals(rootDevice)) {
- sBuilder.append("\r\n Paths from " + rootDevice + " to "
- + device.id());
- ArrayList<Path> paths = getECMPPaths(device.id());
- if (paths != null) {
- for (Path path : paths) {
- sBuilder.append("\r\n == "); // equal cost paths delimiter
- for (int i = path.links().size() - 1; i >= 0; i--) {
- Link link = path.links().get(i);
- sBuilder.append(" : " + link.src() + " -> " + link.dst());
- }
- }
- } else {
- sBuilder.append("\r\n == no paths");
- }
- }
- }
- return sBuilder.toString();
- }
-}
-
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EdgePair.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EdgePair.java
deleted file mode 100644
index 571e87f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/EdgePair.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Represents two devices that are paired by configuration. An EdgePair for
- * (dev1, dev2) is the same as as EdgePair for (dev2, dev1)
- */
-public final class EdgePair {
- DeviceId dev1;
- DeviceId dev2;
-
- EdgePair(DeviceId dev1, DeviceId dev2) {
- this.dev1 = dev1;
- this.dev2 = dev2;
- }
-
- boolean includes(DeviceId dev) {
- return dev1.equals(dev) || dev2.equals(dev);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof EdgePair)) {
- return false;
- }
- EdgePair that = (EdgePair) o;
- return ((this.dev1.equals(that.dev1) && this.dev2.equals(that.dev2)) ||
- (this.dev1.equals(that.dev2) && this.dev2.equals(that.dev1)));
- }
-
- @Override
- public int hashCode() {
- if (dev1.toString().compareTo(dev2.toString()) <= 0) {
- return Objects.hash(dev1, dev2);
- } else {
- return Objects.hash(dev2, dev1);
- }
- }
-
- @Override
- public String toString() {
- return toStringHelper(this)
- .add("Dev1", dev1)
- .add("Dev2", dev2)
- .toString();
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
deleted file mode 100644
index 46231b0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ /dev/null
@@ -1,872 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Lists;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.PredictableExecutor;
-import org.onlab.util.Tools;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.ProbeMode;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Handles host-related events.
- */
-public class HostHandler {
- private static final Logger log = LoggerFactory.getLogger(HostHandler.class);
-
- protected final SegmentRoutingManager srManager;
- private HostService hostService;
- // Host workers - 0 will leverage available processors
- private static final int DEFAULT_THREADS = 0;
- protected PredictableExecutor hostWorkers;
-
- /**
- * Constructs the HostHandler.
- *
- * @param srManager Segment Routing manager
- */
- HostHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- hostService = srManager.hostService;
- this.hostWorkers = new PredictableExecutor(DEFAULT_THREADS,
- groupedThreads("onos/sr", "h-worker-%d", log));
- }
-
- /**
- * Shutdowns the workers.
- */
- void terminate() {
- hostWorkers.shutdown();
- }
-
- protected void init(DeviceId devId) {
- log.info("Initializing hosts on {}", devId);
- List<CompletableFuture<Void>> hostFutures = Lists.newArrayList();
-
- // Init hosts in parallel using hostWorkers executor
- hostService.getHosts().forEach(host -> {
- hostFutures.add(hostWorkers.submit(() -> initHost(host, devId), host.id().hashCode()));
- });
-
- log.debug("{} hostFutures for {}", hostFutures.size(), devId);
- CompletableFuture<Void> allHostFuture = CompletableFuture.allOf(hostFutures.toArray(new CompletableFuture[0]));
- CompletableFuture<Void> timeoutFuture =
- Tools.completeAfter(PhasedRecoveryService.PAIR_TIMEOUT, TimeUnit.SECONDS);
-
- allHostFuture.runAfterEitherAsync(timeoutFuture, () -> {
- if (allHostFuture.isDone()) {
- log.info("{} hosts initialized. Move {} to the next phase", hostFutures.size(), devId);
- } else {
- log.info("Timeout reached. Move {} to the next phase", devId);
- }
- srManager.phasedRecoveryService.setPhase(devId, Phase.INFRA);
- });
- }
-
- private void initHost(Host host, DeviceId deviceId) {
- List<CompletableFuture<Objective>> locationFutures = Lists.newArrayList();
-
- effectiveLocations(host).forEach(location -> {
- if (location.deviceId().equals(deviceId) ||
- location.deviceId().equals(srManager.getPairDeviceId(deviceId).orElse(null))) {
- locationFutures.addAll(processHostAddedAtLocation(host, location));
- }
- });
-
- log.debug("{} locationFutures for {}", locationFutures.size(), host);
-
- // Waiting for all locationFutures to be completed.
- // This is a blocking operation but it is fine since this is run in a separate thread
- try {
- CompletableFuture.allOf(locationFutures.toArray(new CompletableFuture[0]))
- .thenApply(objectives -> locationFutures.stream()
- .map(CompletableFuture::join)
- .collect(Collectors.toList())
- )
- .get();
- } catch (InterruptedException | ExecutionException e) {
- log.warn("Exception caught when executing locationFutures");
- locationFutures.forEach(future -> future.cancel(false));
- }
- }
-
- void processHostAddedEvent(HostEvent event) {
- Host host = event.subject();
- hostWorkers.execute(() -> processHostAdded(host), host.id().hashCode());
- }
-
- private void processHostAdded(Host host) {
- effectiveLocations(host).forEach(location -> processHostAddedAtLocation(host, location));
- // ensure dual-homed host locations have viable uplinks
- if (effectiveLocations(host).size() > 1 || srManager.singleHomedDown) {
- effectiveLocations(host).forEach(loc -> {
- if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
- srManager.linkHandler.checkUplinksForHost(loc);
- }
- });
- }
- }
-
- List<CompletableFuture<Objective>> processHostAddedAtLocation(Host host, HostLocation location) {
- checkArgument(effectiveLocations(host).contains(location), "{} is not a location of {}", location, host);
-
- MacAddress hostMac = host.mac();
- VlanId hostVlanId = host.vlan();
- Set<HostLocation> locations = effectiveLocations(host);
- Set<IpAddress> ips = host.ipAddresses();
- log.info("Host {}/{} is added at {}", hostMac, hostVlanId, locations);
-
- List<CompletableFuture<Objective>> objectiveFutures = Lists.newArrayList();
-
- // TODO Phased recovery does not trace double tagged hosts
- if (isDoubleTaggedHost(host)) {
- ips.forEach(ip ->
- processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
- host.innerVlan(), hostVlanId, host.tpid(), ip, false)
- );
- } else {
- objectiveFutures.add(
- processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, false)
- );
- ips.forEach(ip ->
- objectiveFutures.add(
- processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, false)
- )
- );
- }
-
- // Use the pair link temporarily before the second location of a dual-homed host shows up.
- // This do not affect single-homed hosts since the flow will be blocked in
- // processBridgingRule or processRoutingRule due to VLAN or IP mismatch respectively
- srManager.getPairDeviceId(location.deviceId()).ifPresent(pairDeviceId -> {
- if (effectiveLocations(host).stream().noneMatch(l -> l.deviceId().equals(pairDeviceId))) {
- srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort -> {
- // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
- // when the host is untagged
- VlanId vlanId = vlanForPairPort(hostVlanId, location);
- if (vlanId == null) {
- return;
- }
-
- objectiveFutures.add(
- processBridgingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, false)
- );
- ips.forEach(ip ->
- objectiveFutures.add(
- processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, false)
- )
- );
-
- if (srManager.activeProbing) {
- probe(host, location, pairDeviceId, pairRemotePort);
- }
- });
- }
- });
-
- int nextId = srManager.getMacVlanNextObjectiveId(location.deviceId(), hostMac, hostVlanId, null, false);
- if (nextId != -1) {
- VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(hostVlanId);
- log.debug(" Updating next objective for device {}, host {}/{}, port {}, nextid {}",
- location.deviceId(), hostMac, vlanId, location.port(), nextId);
- srManager.updateMacVlanTreatment(location.deviceId(), hostMac, vlanId,
- location.port(), nextId);
- }
-
- log.debug("{} objectiveFutures for {}", objectiveFutures.size(), location);
- return objectiveFutures;
- }
-
- void processHostRemovedEvent(HostEvent event) {
- Host host = event.subject();
- hostWorkers.execute(() -> processHostRemoved(host), host.id().hashCode());
- }
-
- private void processHostRemoved(Host host) {
- MacAddress hostMac = host.mac();
- VlanId hostVlanId = host.vlan();
- Set<HostLocation> locations = effectiveLocations(host);
- Set<IpAddress> ips = host.ipAddresses();
- log.info("Host {}/{} is removed from {}", hostMac, hostVlanId, locations);
-
- locations.forEach(location -> {
- if (isDoubleTaggedHost(host)) {
- ips.forEach(ip ->
- processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
- host.innerVlan(), hostVlanId, host.tpid(), ip, true)
- );
- } else {
- processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, true);
- ips.forEach(ip ->
- processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, true)
- );
- }
-
- // Also remove redirection flows on the pair device if exists.
- Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
- Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(location.deviceId());
- if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
- // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
- // when the host is untagged
- VlanId vlanId = vlanForPairPort(hostVlanId, location);
- if (vlanId == null) {
- return;
- }
-
- processBridgingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId, true);
- ips.forEach(ip ->
- processRoutingRule(pairDeviceId.get(), pairLocalPort.get(), hostMac, vlanId,
- ip, true));
- }
-
- // Delete prefix from sr-device-subnet when the next hop host is removed
- srManager.routeService.getRouteTables().forEach(tableId -> {
- srManager.routeService.getRoutes(tableId).forEach(routeInfo -> {
- if (routeInfo.allRoutes().stream().anyMatch(rr -> ips.contains(rr.nextHop()))) {
- log.debug("HostRemoved. removeSubnet {}, {}", location, routeInfo.prefix());
- srManager.deviceConfiguration.removeSubnet(location, routeInfo.prefix());
- }
- });
- });
-
- });
- }
-
- void processHostMovedEvent(HostEvent event) {
- Host host = event.subject();
- hostWorkers.execute(() -> processHostMovedEventInternal(event), host.id().hashCode());
- }
-
- private void processHostMovedEventInternal(HostEvent event) {
- // This method will be called when one of the following value has changed:
- // (1) locations (2) auxLocations or (3) both locations and auxLocations.
- // We only need to proceed when effectiveLocation has changed.
- Set<HostLocation> newLocations = effectiveLocations(event.subject());
- Set<HostLocation> prevLocations = effectiveLocations(event.prevSubject());
-
- if (newLocations.equals(prevLocations)) {
- log.info("effectiveLocations of {} has not changed. Skipping {}", event.subject().id(), event);
- return;
- }
-
- Host host = event.subject();
- Host prevHost = event.prevSubject();
- MacAddress hostMac = host.mac();
- VlanId hostVlanId = host.vlan();
- Set<IpAddress> prevIps = prevHost.ipAddresses();
- Set<IpAddress> newIps = host.ipAddresses();
- EthType hostTpid = host.tpid();
- boolean doubleTaggedHost = isDoubleTaggedHost(host);
-
- log.info("Host {}/{} is moved from {} to {}", hostMac, hostVlanId, prevLocations, newLocations);
- Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId)
- .collect(Collectors.toSet());
-
- // For each old location
- Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
- // Remove routing rules for old IPs
- Sets.difference(prevIps, newIps).forEach(ip -> {
- if (doubleTaggedHost) {
- processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(),
- hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
- } else {
- processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
- ip, true);
- }
- });
-
- // Redirect the flows to pair link if configured
- // Note: Do not continue removing any rule
- Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId());
- Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(prevLocation.deviceId());
- if (pairDeviceId.isPresent() && pairLocalPort.isPresent() &&
- newLocations.stream().anyMatch(location -> location.deviceId().equals(pairDeviceId.get())) &&
- newLocations.stream().noneMatch(location -> location.deviceId().equals(prevLocation.deviceId()))) {
- // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
- // when the host is untagged
- VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(prevLocation)).orElse(hostVlanId);
-
- processBridgingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId, false);
- newIps.forEach(ip ->
- processRoutingRule(prevLocation.deviceId(), pairLocalPort.get(), hostMac, vlanId,
- ip, false));
- return;
- }
-
- // Remove flows for unchanged IPs only when the host moves from a switch to another.
- // Otherwise, do not remove and let the adding part update the old flow
- if (!newDeviceIds.contains(prevLocation.deviceId())) {
- processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
- Sets.intersection(prevIps, newIps).forEach(ip -> {
- if (doubleTaggedHost) {
- processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(),
- hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
- } else {
- processRoutingRule(prevLocation.deviceId(), prevLocation.port(),
- hostMac, hostVlanId, ip, true);
- }
- });
- }
-
- // Remove bridging rules if new interface vlan is different from old interface vlan
- // Otherwise, do not remove and let the adding part update the old flow
- if (newLocations.stream().noneMatch(newLocation -> {
- VlanId oldAssignedVlan = srManager.getInternalVlanId(prevLocation);
- VlanId newAssignedVlan = srManager.getInternalVlanId(newLocation);
- // Host is tagged and the new location has the host vlan in vlan-tagged
- return srManager.interfaceService.getTaggedVlanId(newLocation).contains(hostVlanId) ||
- (oldAssignedVlan != null && newAssignedVlan != null &&
- // Host is untagged and the new location has the same assigned vlan
- oldAssignedVlan.equals(newAssignedVlan));
- })) {
- processBridgingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId, true);
- }
-
- // Remove routing rules for unchanged IPs if none of the subnet of new location contains
- // the IP. Otherwise, do not remove and let the adding part update the old flow
- Sets.intersection(prevIps, newIps).forEach(ip -> {
- if (newLocations.stream().noneMatch(newLocation ->
- srManager.deviceConfiguration.inSameSubnet(newLocation, ip))) {
- if (doubleTaggedHost) {
- processDoubleTaggedRoutingRule(prevLocation.deviceId(), prevLocation.port(),
- hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
- } else {
- processRoutingRule(prevLocation.deviceId(), prevLocation.port(),
- hostMac, hostVlanId, ip, true);
- }
- }
- });
- });
-
- // For each new location, add all new IPs.
- Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
- processBridgingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, false);
- newIps.forEach(ip -> {
- if (doubleTaggedHost) {
- processDoubleTaggedRoutingRule(newLocation.deviceId(), newLocation.port(),
- hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, false);
- } else {
- processRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId,
- ip, false);
- }
- });
-
- // Probe on pair device when host move
- // Majorly for the 2nd step of [1A/x, 1B/x] -> [1A/x, 1B/y] -> [1A/y, 1B/y]
- // But will also cover [1A/x] -> [1A/y] -> [1A/y, 1B/y]
- if (srManager.activeProbing) {
-
- srManager.getPairDeviceId(newLocation.deviceId()).ifPresent(pairDeviceId ->
- srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort ->
- probe(host, newLocation, pairDeviceId, pairRemotePort)
- )
- );
- }
- });
-
- // For each unchanged location, add new IPs and remove old IPs.
- Sets.intersection(newLocations, prevLocations).forEach(unchangedLocation -> {
- Sets.difference(prevIps, newIps).forEach(ip -> {
- if (doubleTaggedHost) {
- processDoubleTaggedRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
- hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, true);
- } else {
- processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
- hostMac, hostVlanId, ip, true);
- }
- });
-
- Sets.difference(newIps, prevIps).forEach(ip -> {
- if (doubleTaggedHost) {
- processDoubleTaggedRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
- hostMac, host.innerVlan(), hostVlanId, hostTpid, ip, false);
- } else {
- processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(),
- hostMac, hostVlanId, ip, false);
- }
- });
-
- // Verify existing location and see if it is still valid
- srManager.probingService.probeHost(host, unchangedLocation, ProbeMode.VERIFY);
- });
-
- // ensure dual-homed host locations have viable uplinks
- if (newLocations.size() > prevLocations.size() || srManager.singleHomedDown) {
- newLocations.forEach(loc -> {
- if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
- srManager.linkHandler.checkUplinksForHost(loc);
- }
- });
- }
- }
-
- void processHostUpdatedEvent(HostEvent event) {
- Host host = event.subject();
- hostWorkers.execute(() -> processHostUpdatedEventInternal(event), host.id().hashCode());
- }
-
- private void processHostUpdatedEventInternal(HostEvent event) {
- Host host = event.subject();
- MacAddress hostMac = host.mac();
- VlanId hostVlanId = host.vlan();
- EthType hostTpid = host.tpid();
- Set<HostLocation> locations = effectiveLocations(host);
- Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
- Set<IpAddress> newIps = host.ipAddresses();
- log.info("Host {}/{} is updated", hostMac, hostVlanId);
-
- locations.forEach(location -> {
- Sets.difference(prevIps, newIps).forEach(ip -> {
- if (isDoubleTaggedHost(host)) {
- processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
- host.innerVlan(), hostVlanId, hostTpid, ip, true);
- } else {
- processRoutingRule(location.deviceId(), location.port(), hostMac,
- hostVlanId, ip, true);
- }
- });
- Sets.difference(newIps, prevIps).forEach(ip -> {
- if (isDoubleTaggedHost(host)) {
- processDoubleTaggedRoutingRule(location.deviceId(), location.port(), hostMac,
- host.innerVlan(), hostVlanId, hostTpid, ip, false);
- } else {
- processRoutingRule(location.deviceId(), location.port(), hostMac,
- hostVlanId, ip, false);
- }
- });
- });
-
- // Use the pair link temporarily before the second location of a dual-homed host shows up.
- // This do not affect single-homed hosts since the flow will be blocked in
- // processBridgingRule or processRoutingRule due to VLAN or IP mismatch respectively
- locations.forEach(location ->
- srManager.getPairDeviceId(location.deviceId()).ifPresent(pairDeviceId -> {
- if (locations.stream().noneMatch(l -> l.deviceId().equals(pairDeviceId))) {
- Set<IpAddress> ipsToAdd = Sets.difference(newIps, prevIps);
- Set<IpAddress> ipsToRemove = Sets.difference(prevIps, newIps);
-
- srManager.getPairLocalPort(pairDeviceId).ifPresent(pairRemotePort -> {
- // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
- // when the host is untagged
- VlanId vlanId = vlanForPairPort(hostVlanId, location);
- if (vlanId == null) {
- return;
- }
-
- ipsToRemove.forEach(ip ->
- processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, true)
- );
- ipsToAdd.forEach(ip ->
- processRoutingRule(pairDeviceId, pairRemotePort, hostMac, vlanId, ip, false)
- );
-
- if (srManager.activeProbing) {
- probe(host, location, pairDeviceId, pairRemotePort);
- }
- });
- }
- })
- );
- }
-
- /**
- * When a non-pair port comes up, probe each host on the pair device if
- * (1) the host is tagged and the tagged vlan of current port contains host vlan; or
- * (2) the host is untagged and the internal vlan is the same on the host port and current port.
- *
- * @param cp connect point
- */
- // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
- void processPortUp(ConnectPoint cp) {
- if (cp.port().equals(srManager.getPairLocalPort(cp.deviceId()).orElse(null))) {
- return;
- }
- if (srManager.activeProbing) {
- srManager.getPairDeviceId(cp.deviceId())
- .ifPresent(pairDeviceId -> srManager.hostService.getConnectedHosts(pairDeviceId).forEach(
- host -> hostWorkers.execute(() -> probingIfNecessary(host, pairDeviceId, cp),
- host.id().hashCode())));
- }
- }
-
- // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
- private void probingIfNecessary(Host host, DeviceId pairDeviceId, ConnectPoint cp) {
- if (isHostInVlanOfPort(host, pairDeviceId, cp)) {
- srManager.probingService.probeHost(host, cp, ProbeMode.DISCOVER);
- }
- }
-
- /**
- * Checks if given host located on given device id matches VLAN config of current port.
- *
- * @param host host to check
- * @param deviceId device id to check
- * @param cp current connect point
- * @return true if the host located at deviceId matches the VLAN config on cp
- */
- private boolean isHostInVlanOfPort(Host host, DeviceId deviceId, ConnectPoint cp) {
- VlanId internalVlan = srManager.getInternalVlanId(cp);
- Set<VlanId> taggedVlan = srManager.interfaceService.getTaggedVlanId(cp);
-
- return taggedVlan.contains(host.vlan()) ||
- (internalVlan != null && effectiveLocations(host).stream()
- .filter(l -> l.deviceId().equals(deviceId))
- .map(srManager::getInternalVlanId)
- .anyMatch(internalVlan::equals));
- }
-
- /**
- * Send a probe on all locations with the same VLAN on pair device, excluding pair port.
- *
- * @param host host to probe
- * @param location newly discovered host location
- * @param pairDeviceId pair device id
- * @param pairRemotePort pair remote port
- */
- // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
- private void probe(Host host, ConnectPoint location, DeviceId pairDeviceId, PortNumber pairRemotePort) {
- //Check if the host still exists in the host store
- if (hostService.getHost(host.id()) == null) {
- log.debug("Host entry for host {} no more present. Aborting hostprobe discover for this host", host.id());
- return;
- }
-
- VlanId vlanToProbe = host.vlan().equals(VlanId.NONE) ?
- srManager.getInternalVlanId(location) : host.vlan();
- if (srManager.symmetricProbing) {
- srManager.interfaceService.getInterfaces().stream()
- .filter(i -> i.vlanTagged().contains(vlanToProbe) ||
- i.vlanUntagged().equals(vlanToProbe) ||
- i.vlanNative().equals(vlanToProbe))
- .filter(i -> i.connectPoint().deviceId().equals(pairDeviceId))
- .filter(i -> i.connectPoint().port().equals(location.port()))
- .forEach(i -> {
- log.debug("Probing host {} on pair device {}", host.id(), i.connectPoint());
- srManager.probingService.probeHost(host, i.connectPoint(), ProbeMode.DISCOVER);
- });
- } else {
- srManager.interfaceService.getInterfaces().stream()
- .filter(i -> i.vlanTagged().contains(vlanToProbe) ||
- i.vlanUntagged().equals(vlanToProbe) ||
- i.vlanNative().equals(vlanToProbe))
- .filter(i -> i.connectPoint().deviceId().equals(pairDeviceId))
- .filter(i -> !i.connectPoint().port().equals(pairRemotePort))
- .forEach(i -> {
- log.debug("Probing host {} on pair device {}", host.id(), i.connectPoint());
- srManager.probingService.probeHost(host, i.connectPoint(), ProbeMode.DISCOVER);
- });
- }
- }
-
- /**
- * Populates or revokes a bridging rule on given deviceId that matches given mac,
- * given vlan and output to given port.
- *
- * @param deviceId device ID
- * @param port port
- * @param mac mac address
- * @param vlanId VLAN ID
- * @param revoke true to revoke the rule; false to populate
- * @return future that includes the flow objective if succeeded, null if otherwise
- */
- private CompletableFuture<Objective> processBridgingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
- VlanId vlanId, boolean revoke) {
- log.info("{} bridging entry for host {}/{} at {}:{}", revoke ? "Revoking" : "Populating",
- mac, vlanId, deviceId, port);
-
- if (!revoke) {
- return srManager.defaultRoutingHandler.populateBridging(deviceId, port, mac, vlanId);
- } else {
- return srManager.defaultRoutingHandler.revokeBridging(deviceId, port, mac, vlanId);
- }
- }
-
- /**
- * Populate or revoke a routing rule on given deviceId that matches given ip,
- * set destination mac to given mac, set vlan to given vlan and output to given port.
- *
- * @param deviceId device ID
- * @param port port
- * @param mac mac address
- * @param vlanId VLAN ID
- * @param ip IP address
- * @param revoke true to revoke the rule; false to populate
- * @return future that includes the flow objective if succeeded, null if otherwise
- */
- private CompletableFuture<Objective> processRoutingRule(DeviceId deviceId, PortNumber port, MacAddress mac,
- VlanId vlanId, IpAddress ip, boolean revoke) {
- ConnectPoint location = new ConnectPoint(deviceId, port);
- if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
- log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
- return CompletableFuture.completedFuture(null);
- }
-
- log.info("{} routing rule for {} at {}", revoke ? "Revoking" : "Populating", ip, location);
- if (revoke) {
- return srManager.defaultRoutingHandler.revokeRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port, true);
- } else {
- return srManager.defaultRoutingHandler.populateRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port, true);
- }
- }
-
- /**
- * Populate or revoke a routing rule and egress rules on given deviceId that matches given IP,
- * to set destination mac to given mac, set inner vlan and outer vlan to given vlans,
- * set outer TPID, and output to given port.
- *
- * @param deviceId device ID
- * @param port port
- * @param mac mac address
- * @param innerVlan inner VLAN ID
- * @param outerVlan outer VLAN ID
- * @param outerTpid outer TPID
- * @param ip IP address
- * @param revoke true to revoke the rule; false to populate
- */
- private void processDoubleTaggedRoutingRule(DeviceId deviceId, PortNumber port,
- MacAddress mac, VlanId innerVlan,
- VlanId outerVlan, EthType outerTpid,
- IpAddress ip, boolean revoke) {
- if (!srManager.routeDoubleTaggedHosts) {
- log.debug("Routing for double tagged host is disabled. Ignore {}/{}/{}", mac, outerVlan, innerVlan);
- return;
- }
-
- ConnectPoint location = new ConnectPoint(deviceId, port);
- if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
- log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
- return;
- }
- log.info("{} routing rule for double-tagged host {} at {}",
- revoke ? "Revoking" : "Populating", ip, location);
- if (revoke) {
- srManager.defaultRoutingHandler.revokeDoubleTaggedRoute(
- deviceId, ip.toIpPrefix(), mac, innerVlan, outerVlan, outerTpid, port);
- } else {
- srManager.defaultRoutingHandler.populateDoubleTaggedRoute(
- deviceId, ip.toIpPrefix(), mac, innerVlan, outerVlan, outerTpid, port);
- }
- }
-
- void populateAllDoubleTaggedHost() {
- log.info("Enabling routing for all double tagged hosts");
- Sets.newHashSet(srManager.hostService.getHosts()).stream().filter(this::isDoubleTaggedHost)
- .forEach(h -> effectiveLocations(h).forEach(l ->
- h.ipAddresses().forEach(i ->
- processDoubleTaggedRoutingRule(l.deviceId(), l.port(), h.mac(), h.innerVlan(),
- h.vlan(), h.tpid(), i, false)
- )
- )
- );
- }
-
- void revokeAllDoubleTaggedHost() {
- log.info("Disabling routing for all double tagged hosts");
- Sets.newHashSet(srManager.hostService.getHosts()).stream().filter(this::isDoubleTaggedHost)
- .forEach(h -> effectiveLocations(h).forEach(l ->
- h.ipAddresses().forEach(i ->
- processDoubleTaggedRoutingRule(l.deviceId(), l.port(), h.mac(), h.innerVlan(),
- h.vlan(), h.tpid(), i, true)
- )
- )
- );
- }
-
- /**
- * Returns VLAN ID to be used to program redirection flow on pair port.
- *
- * @param hostVlanId host VLAN ID
- * @param location host location
- * @return VLAN ID to be used; Or null if host VLAN does not match the interface config
- */
- VlanId vlanForPairPort(VlanId hostVlanId, ConnectPoint location) {
- VlanId internalVlan = srManager.getInternalVlanId(location);
- Set<VlanId> taggedVlan = srManager.interfaceService.getTaggedVlanId(location);
-
- if (!hostVlanId.equals(VlanId.NONE) && taggedVlan.contains(hostVlanId)) {
- return hostVlanId;
- } else if (hostVlanId.equals(VlanId.NONE) && internalVlan != null) {
- return internalVlan;
- } else {
- log.warn("VLAN mismatch. hostVlan={}, location={}, internalVlan={}, taggedVlan={}",
- hostVlanId, location, internalVlan, taggedVlan);
- return null;
- }
- }
-
- /**
- * Update forwarding objective for unicast bridging and unicast routing.
- * Also check the validity of updated interface configuration on VLAN.
- *
- * @param deviceId device ID that host attaches to
- * @param portNum port number that host attaches to
- * @param vlanId Vlan ID configured on the switch port
- * @param popVlan true to pop Vlan tag at TrafficTreatment, false otherwise
- * @param install true to populate the objective, false to revoke
- */
- // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
- void processIntfVlanUpdatedEvent(DeviceId deviceId, PortNumber portNum, VlanId vlanId,
- boolean popVlan, boolean install) {
- ConnectPoint connectPoint = new ConnectPoint(deviceId, portNum);
- Set<Host> hosts = hostService.getConnectedHosts(connectPoint);
-
- if (hosts == null || hosts.size() == 0) {
- log.debug("processIntfVlanUpdatedEvent: No hosts connected to {}", connectPoint);
- return;
- }
-
- hosts.forEach(host -> hostWorkers.execute(() -> processIntfVlanUpdatedEventInternal(
- host, deviceId, portNum, vlanId, popVlan, install), host.id().hashCode()));
- }
-
- private void processIntfVlanUpdatedEventInternal(Host host, DeviceId deviceId, PortNumber portNum,
- VlanId vlanId, boolean popVlan, boolean install) {
- MacAddress mac = host.mac();
- VlanId hostVlanId = host.vlan();
-
- if (!install) {
- // Do not check the host validity. Just remove all rules corresponding to the vlan id
- // Revoke forwarding objective for bridging to the host
- srManager.defaultRoutingHandler.updateBridging(deviceId, portNum, mac, vlanId, popVlan, false);
-
- // Revoke forwarding objective and corresponding simple Next objective
- // for each Host and IP address connected to given port
- host.ipAddresses().forEach(ipAddress ->
- srManager.routingRulePopulator.updateFwdObj(deviceId, portNum, ipAddress.toIpPrefix(),
- mac, vlanId, popVlan, false)
- );
- } else {
- // Check whether the host vlan is valid for new interface configuration
- if ((!popVlan && hostVlanId.equals(vlanId)) ||
- (popVlan && hostVlanId.equals(VlanId.NONE))) {
- srManager.defaultRoutingHandler.updateBridging(deviceId, portNum, mac, vlanId, popVlan, true);
- // Update Forwarding objective and corresponding simple Next objective
- // for each Host and IP address connected to given port
- host.ipAddresses().forEach(ipAddress ->
- srManager.routingRulePopulator.updateFwdObj(deviceId, portNum, ipAddress.toIpPrefix(),
- mac, vlanId, popVlan, true)
- );
- }
- }
- }
-
- /**
- * Populate or revoke routing rule for each host, according to the updated
- * subnet configuration on the interface.
- * @param cp connect point of the updated interface
- * @param ipPrefixSet IP Prefixes added or removed
- * @param install true if IP Prefixes added, false otherwise
- */
- // TODO Current implementation does not handle dual-homed hosts with auxiliary locations.
- void processIntfIpUpdatedEvent(ConnectPoint cp, Set<IpPrefix> ipPrefixSet, boolean install) {
- Set<Host> hosts = hostService.getConnectedHosts(cp);
-
- if (hosts == null || hosts.size() == 0) {
- log.debug("processIntfIpUpdatedEvent: No hosts connected to {}", cp);
- return;
- }
-
- // Check whether the host IP address is in the interface's subnet
- hosts.forEach(host -> hostWorkers.execute(() -> processIntfIpUpdatedEventInternal(
- host, cp, ipPrefixSet, install)));
- }
-
- private void processIntfIpUpdatedEventInternal(Host host, ConnectPoint cp, Set<IpPrefix> ipPrefixSet,
- boolean install) {
- host.ipAddresses().forEach(hostIpAddress -> {
- ipPrefixSet.forEach(ipPrefix -> {
- if (install && ipPrefix.contains(hostIpAddress)) {
- srManager.defaultRoutingHandler.populateRoute(cp.deviceId(), hostIpAddress.toIpPrefix(),
- host.mac(), host.vlan(), cp.port(), true);
- } else if (!install && ipPrefix.contains(hostIpAddress)) {
- srManager.defaultRoutingHandler.revokeRoute(cp.deviceId(), hostIpAddress.toIpPrefix(),
- host.mac(), host.vlan(), cp.port(), true);
- }
- });
- });
- }
-
- /**
- * Returns the set of portnumbers on the given device that are part of the
- * locations for dual-homed hosts.
- *
- * @param deviceId the given deviceId
- * @return set of port numbers on given device that are dual-homed host
- * locations. May be empty if no dual homed hosts are connected to
- * the given device
- */
- Set<PortNumber> getDualHomedHostPorts(DeviceId deviceId) {
- Set<PortNumber> dualHomedLocations = new HashSet<>();
- srManager.hostService.getConnectedHosts(deviceId).stream()
- .filter(host -> effectiveLocations(host).size() == 2)
- .forEach(host -> effectiveLocations(host).stream()
- .filter(loc -> loc.deviceId().equals(deviceId))
- .forEach(loc -> dualHomedLocations.add(loc.port())));
- return dualHomedLocations;
- }
-
- /**
- * Checks if the given host is double-tagged or not.
- *
- * @param host host to check
- * @return true if it is double-tagged, false otherwise
- */
- private boolean isDoubleTaggedHost(Host host) {
- return !host.innerVlan().equals(VlanId.NONE);
- }
-
- /**
- * Returns effective locations of given host.
- *
- * @param host host to check
- * @return auxLocations of the host if exists, or locations of the host otherwise.
- */
- Set<HostLocation> effectiveLocations(Host host) {
- return (host.auxLocations() != null) ? host.auxLocations() : host.locations();
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
deleted file mode 100644
index fc3dd17..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MPLS;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ndp.NeighborSolicitation;
-import org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.neighbour.NeighbourMessageType;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Handler of ICMP packets that responses or forwards ICMP packets that
- * are sent to the controller.
- */
-public class IcmpHandler extends SegmentRoutingNeighbourHandler {
-
- private static Logger log = LoggerFactory.getLogger(IcmpHandler.class);
-
- /**
- * Creates an IcmpHandler object.
- *
- * @param srManager SegmentRoutingManager object
- */
- public IcmpHandler(SegmentRoutingManager srManager) {
- super(srManager);
- }
-
- /**
- * Utility function to send packet out.
- *
- * @param outport the output port
- * @param payload the packet to send
- * @param destSid the segment id of the dest device
- * @param destIpAddress the destination ip address
- * @param allowedHops the hop limit/ttl
- */
- private void sendPacketOut(ConnectPoint outport,
- Ethernet payload,
- int destSid,
- IpAddress destIpAddress,
- byte allowedHops) {
- int origSid;
- try {
- if (destIpAddress.isIp4()) {
- origSid = config.getIPv4SegmentId(outport.deviceId());
- } else {
- origSid = config.getIPv6SegmentId(outport.deviceId());
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting sendPacketOut");
- return;
- }
-
- if (destSid == -1 || origSid == destSid ||
- srManager.interfaceService.isConfigured(outport)) {
- TrafficTreatment treatment = DefaultTrafficTreatment.builder().
- setOutput(outport.port()).build();
- OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
- treatment, ByteBuffer.wrap(payload.serialize()));
- log.trace("Sending packet {} to {}", payload, outport);
- srManager.packetService.emit(packet);
- } else {
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(outport.port())
- .build();
-
- payload.setEtherType(Ethernet.MPLS_UNICAST);
- MPLS mplsPkt = new MPLS();
- mplsPkt.setLabel(destSid);
- mplsPkt.setTtl(allowedHops);
- mplsPkt.setPayload(payload.getPayload());
- payload.setPayload(mplsPkt);
- OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(),
- treatment, ByteBuffer.wrap(payload.serialize()));
- log.trace("Sending packet {} to {}", payload, outport);
- srManager.packetService.emit(packet);
- }
- }
-
- private IpAddress selectRouterIpAddress(IpAddress destIpAddress, ConnectPoint outPort,
- Set<ConnectPoint> connectPoints) {
- IpAddress routerIpAddress;
- // Let's get first the online connect points
- Set<ConnectPoint> onlineCps = connectPoints.stream()
- .filter(connectPoint -> srManager.deviceService.isAvailable(connectPoint.deviceId()))
- .collect(Collectors.toSet());
- // Check if ping is local
- if (onlineCps.contains(outPort)) {
- routerIpAddress = config.getRouterIpAddress(destIpAddress, outPort.deviceId());
- log.trace("Local ping received from {} - send to {}", destIpAddress, routerIpAddress);
- return routerIpAddress;
- }
- // Check if it comes from a remote device. Loopbacks are sorted comparing byte by byte
- // FIXME if we lose both links from the chosen leaf to spine - ping will fail
- routerIpAddress = onlineCps.stream()
- .filter(onlineCp -> !onlineCp.deviceId().equals(outPort.deviceId()))
- .map(selectedCp -> config.getRouterIpAddress(destIpAddress, selectedCp.deviceId()))
- .filter(Objects::nonNull)
- .sorted()
- .findFirst().orElse(null);
- if (routerIpAddress != null) {
- log.trace("Remote ping received from {} - send to {}", destIpAddress, routerIpAddress);
- } else {
- log.warn("Not found a valid loopback for ping coming from {} - {}", destIpAddress, outPort);
- }
- return routerIpAddress;
- }
-
- private Ip4Address selectRouterIp4Address(IpAddress destIpAddress, ConnectPoint outPort,
- Set<ConnectPoint> connectPoints) {
- IpAddress routerIpAddress = selectRouterIpAddress(destIpAddress, outPort, connectPoints);
- return routerIpAddress != null ? routerIpAddress.getIp4Address() : null;
- }
-
- private Ip6Address selectRouterIp6Address(IpAddress destIpAddress, ConnectPoint outPort,
- Set<ConnectPoint> connectPoints) {
- IpAddress routerIpAddress = selectRouterIpAddress(destIpAddress, outPort, connectPoints);
- return routerIpAddress != null ? routerIpAddress.getIp6Address() : null;
- }
-
- //////////////////////////////////////
- // ICMP Echo/Reply Protocol //
- //////////////////////////////////////
-
- /**
- * Process incoming ICMP packet.
- * If it is an ICMP request to router, then sends an ICMP response.
- * Otherwise ignore the packet.
- *
- * @param eth inbound ICMP packet
- * @param inPort the input port
- */
- public void processIcmp(Ethernet eth, ConnectPoint inPort) {
- DeviceId deviceId = inPort.deviceId();
- IPv4 ipv4Packet = (IPv4) eth.getPayload();
- ICMP icmp = (ICMP) ipv4Packet.getPayload();
- Ip4Address destinationAddress = Ip4Address.valueOf(ipv4Packet.getDestinationAddress());
- Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
- IpAddress routerIp;
-
- // Only proceed with echo request
- if (icmp.getIcmpType() != ICMP.TYPE_ECHO_REQUEST) {
- return;
- }
-
- try {
- routerIp = config.getRouterIpv4(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting processPacketIn.");
- return;
- }
-
- // Get pair ip - if it exists
- IpAddress pairRouterIp;
- try {
- DeviceId pairDeviceId = config.getPairDeviceId(deviceId);
- pairRouterIp = pairDeviceId != null ? config.getRouterIpv4(pairDeviceId) : null;
- } catch (DeviceConfigNotFoundException e) {
- pairRouterIp = null;
- }
-
- // ICMP to the router IP or gateway IP
- if (destinationAddress.equals(routerIp.getIp4Address()) ||
- (pairRouterIp != null && destinationAddress.equals(pairRouterIp.getIp4Address())) ||
- gatewayIpAddresses.contains(destinationAddress)) {
- sendIcmpResponse(eth, inPort);
- } else {
- log.trace("Ignore ICMP that targets for {}", destinationAddress);
- }
- }
-
- /**
- * Sends an ICMP reply message.
- *
- * @param icmpRequest the original ICMP request
- * @param outport the output port where the ICMP reply should be sent to
- */
- private void sendIcmpResponse(Ethernet icmpRequest, ConnectPoint outport) {
- Ethernet icmpReplyEth = ICMP.buildIcmpReply(icmpRequest);
- IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
- IPv4 icmpReplyIpv4 = (IPv4) icmpReplyEth.getPayload();
- Ip4Address destIpAddress = Ip4Address.valueOf(icmpRequestIpv4.getSourceAddress());
-
- // Get the available connect points
- Set<ConnectPoint> destConnectPoints = config.getConnectPointsForASubnetHost(destIpAddress);
- // Select a router
- Ip4Address destRouterAddress = selectRouterIp4Address(destIpAddress, outport, destConnectPoints);
-
- // Note: Source IP of the ICMP request doesn't belong to any configured subnet.
- // The source might be an indirectly attached host (e.g. behind a router)
- // Lookup the route store for the nexthop instead.
- if (destRouterAddress == null) {
- Optional<DeviceId> deviceId = srManager.routeService
- .longestPrefixLookup(destIpAddress).map(srManager::nextHopLocations)
- .flatMap(locations -> locations.stream().findFirst())
- .map(ConnectPoint::deviceId);
- if (deviceId.isPresent()) {
- try {
- destRouterAddress = config.getRouterIpv4(deviceId.get());
- } catch (DeviceConfigNotFoundException e) {
- log.warn("Device config for {} not found. Abort ICMP processing", deviceId);
- return;
- }
- }
- }
-
- int destSid = config.getIPv4SegmentId(destRouterAddress);
- if (destSid < 0) {
- log.warn("Failed to lookup SID of the switch that {} attaches to. " +
- "Unable to process ICMP request.", destIpAddress);
- return;
- }
- sendPacketOut(outport, icmpReplyEth, destSid, destIpAddress, icmpReplyIpv4.getTtl());
- }
-
- ///////////////////////////////////////////
- // ICMPv6 Echo/Reply Protocol //
- ///////////////////////////////////////////
-
- /**
- * Process incoming ICMPv6 packet.
- * If it is an ICMPv6 request to router, then sends an ICMPv6 response.
- * Otherwise ignore the packet.
- *
- * @param eth the incoming ICMPv6 packet
- * @param inPort the input port
- */
- public void processIcmpv6(Ethernet eth, ConnectPoint inPort) {
- DeviceId deviceId = inPort.deviceId();
- IPv6 ipv6Packet = (IPv6) eth.getPayload();
- ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
- Ip6Address destinationAddress = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
- Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
- IpAddress routerIp;
-
- // Only proceed with echo request
- if (icmp6.getIcmpType() != ICMP6.ECHO_REQUEST) {
- return;
- }
-
- try {
- routerIp = config.getRouterIpv6(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting processPacketIn.");
- return;
- }
-
- // Get pair ip - if it exists
- IpAddress pairRouterIp;
- try {
- DeviceId pairDeviceId = config.getPairDeviceId(deviceId);
- pairRouterIp = pairDeviceId != null ? config.getRouterIpv6(pairDeviceId) : null;
- } catch (DeviceConfigNotFoundException e) {
- pairRouterIp = null;
- }
-
- Optional<Ip6Address> linkLocalIp = getLinkLocalIp(inPort);
- // Ensure ICMP to the router IP, EUI-64 link-local IP, or gateway IP
- if (destinationAddress.equals(routerIp.getIp6Address()) ||
- (linkLocalIp.isPresent() && destinationAddress.equals(linkLocalIp.get())) ||
- (pairRouterIp != null && destinationAddress.equals(pairRouterIp.getIp6Address())) ||
- gatewayIpAddresses.contains(destinationAddress)) {
- sendIcmpv6Response(eth, inPort);
- } else {
- log.trace("Ignore ICMPv6 that targets for {}", destinationAddress);
- }
- }
-
- /**
- * Sends an ICMPv6 reply message.
- *
- * @param ethRequest the original ICMP request
- * @param outport the output port where the ICMP reply should be sent to
- */
- private void sendIcmpv6Response(Ethernet ethRequest, ConnectPoint outport) {
- int destSid = -1;
- Ethernet ethReply = ICMP6.buildIcmp6Reply(ethRequest);
- IPv6 icmpRequestIpv6 = (IPv6) ethRequest.getPayload();
- IPv6 icmpReplyIpv6 = (IPv6) ethRequest.getPayload();
- // Source IP of the echo "reply"
- Ip6Address srcIpAddress = Ip6Address.valueOf(icmpRequestIpv6.getDestinationAddress());
- // Destination IP of the echo "reply"
- Ip6Address destIpAddress = Ip6Address.valueOf(icmpRequestIpv6.getSourceAddress());
- Optional<Ip6Address> linkLocalIp = getLinkLocalIp(outport);
-
- // Fast path if the echo request targets the link-local address of switch interface
- if (linkLocalIp.isPresent() && srcIpAddress.equals(linkLocalIp.get())) {
- sendPacketOut(outport, ethReply, destSid, destIpAddress, icmpReplyIpv6.getHopLimit());
- return;
- }
-
- // Get the available connect points
- Set<ConnectPoint> destConnectPoints = config.getConnectPointsForASubnetHost(destIpAddress);
- // Select a router
- Ip6Address destRouterAddress = selectRouterIp6Address(destIpAddress, outport, destConnectPoints);
-
- // Note: Source IP of the ICMP request doesn't belong to any configured subnet.
- // The source might be an indirect host behind a router.
- // Lookup the route store for the nexthop instead.
- if (destRouterAddress == null) {
- Optional<DeviceId> deviceId = srManager.routeService
- .longestPrefixLookup(destIpAddress).map(srManager::nextHopLocations)
- .flatMap(locations -> locations.stream().findFirst())
- .map(ConnectPoint::deviceId);
- if (deviceId.isPresent()) {
- try {
- destRouterAddress = config.getRouterIpv6(deviceId.get());
- } catch (DeviceConfigNotFoundException e) {
- log.warn("Device config for {} not found. Abort ICMPv6 processing", deviceId);
- return;
- }
- }
- }
-
- destSid = config.getIPv6SegmentId(destRouterAddress);
- if (destSid < 0) {
- log.warn("Failed to lookup SID of the switch that {} attaches to. " +
- "Unable to process ICMPv6 request.", destIpAddress);
- return;
- }
- sendPacketOut(outport, ethReply, destSid, destIpAddress, icmpReplyIpv6.getHopLimit());
- }
-
- ///////////////////////////////////////////
- // ICMPv6 Neighbour Discovery Protocol //
- ///////////////////////////////////////////
-
- /**
- * Process incoming NDP packet.
- *
- * If it is an NDP request for the router or for the gateway, then sends a NDP reply.
- * If it is an NDP request to unknown host flood in the subnet.
- * If it is an NDP packet to known host forward the packet to the host.
- *
- * FIXME If the NDP packets use link local addresses we fail.
- *
- * @param pkt inbound packet
- * @param hostService the host service
- */
- public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {
- // First we validate the ndp packet
- SegmentRoutingAppConfig appConfig = srManager.cfgService
- .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
- if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
- // Ignore NDP packets come from suppressed ports
- pkt.drop();
- return;
- }
-
- if (pkt.type() == NeighbourMessageType.REQUEST) {
- handleNdpRequest(pkt, hostService);
- } else {
- handleNdpReply(pkt, hostService);
- }
-
- }
-
- /**
- * Helper method to handle the ndp requests.
- * @param pkt the ndp packet request and context information
- * @param hostService the host service
- */
- private void handleNdpRequest(NeighbourMessageContext pkt, HostService hostService) {
- // ND request for the gateway. We have to reply on behalf of the gateway.
- if (isNdpForGateway(pkt)) {
- log.trace("Sending NDP reply on behalf of gateway IP for pkt: {}", pkt.target());
- MacAddress routerMac = config.getRouterMacForAGatewayIp(pkt.target());
- if (routerMac == null) {
- log.warn("Router MAC of {} is not configured. Cannot handle NDP request from {}",
- pkt.inPort().deviceId(), pkt.sender());
- return;
- }
- sendResponse(pkt, routerMac, hostService, true);
- } else {
-
- // Process NDP targets towards EUI-64 address.
- try {
- DeviceId deviceId = pkt.inPort().deviceId();
-
- Optional<Ip6Address> linkLocalIp = getLinkLocalIp(pkt.inPort());
- if (linkLocalIp.isPresent() && pkt.target().equals(linkLocalIp.get())) {
- MacAddress routerMac = config.getDeviceMac(deviceId);
- sendResponse(pkt, routerMac, hostService, true);
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Unable to handle NDP packet to {}. Aborting.", pkt.target());
- return;
- }
-
- // NOTE: Ignore NDP packets except those target for the router
- // We will reconsider enabling this when we have host learning support
- /*
- // ND request for an host. We do a search by Ip.
- Set<Host> hosts = hostService.getHostsByIp(pkt.target());
- // Possible misconfiguration ? In future this case
- // should be handled we can have same hosts in different VLANs.
- if (hosts.size() > 1) {
- log.warn("More than one host with IP {}", pkt.target());
- }
- Host targetHost = hosts.stream().findFirst().orElse(null);
- // If we know the host forward to its attachment point.
- if (targetHost != null) {
- log.debug("Forward NDP request to the target host");
- pkt.forward(targetHost.location());
- } else {
- // Flood otherwise.
- log.debug("Flood NDP request to the target subnet");
- flood(pkt);
- }
- */
- }
- }
-
- /**
- * Helper method to handle the ndp replies.
- *
- * @param pkt the ndp packet reply and context information
- * @param hostService the host service
- */
- private void handleNdpReply(NeighbourMessageContext pkt, HostService hostService) {
- if (isNdpForGateway(pkt)) {
- log.debug("Forwarding all the ip packets we stored");
- Ip6Address hostIpAddress = pkt.sender().getIp6Address();
- srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
- } else {
- // NOTE: Ignore NDP packets except those target for the router
- // We will reconsider enabling this when we have host learning support
- /*
- HostId hostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
- Host targetHost = hostService.getHost(hostId);
- if (targetHost != null) {
- log.debug("Forwarding the reply to the host");
- pkt.forward(targetHost.location());
- } else {
- // We don't have to flood towards spine facing ports.
- if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
- return;
- }
- log.debug("Flooding the reply to the subnet");
- flood(pkt);
- }
- */
- }
- }
-
- /**
- * Utility to verify if the ND are for the gateway.
- *
- * @param pkt the ndp packet
- * @return true if the ndp is for the gateway. False otherwise
- */
- private boolean isNdpForGateway(NeighbourMessageContext pkt) {
- DeviceId deviceId = pkt.inPort().deviceId();
- Set<IpAddress> gatewayIpAddresses = null;
-
- try {
- if (pkt.target().equals(config.getRouterIpv6(deviceId))) {
- return true;
- }
- gatewayIpAddresses = config.getPortIPs(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting check for router IP in processing ndp");
- return false;
- }
- return gatewayIpAddresses != null && gatewayIpAddresses.stream()
- .filter(IpAddress::isIp6)
- .anyMatch(gatewayIp -> gatewayIp.equals(pkt.target()) ||
- Arrays.equals(IPv6.getSolicitNodeAddress(gatewayIp.toOctets()),
- pkt.target().toOctets()));
- }
-
- /**
- * Sends a NDP request for the target IP address to all ports except in-port.
- *
- * @param deviceId Switch device ID
- * @param targetAddress target IP address for ARP
- * @param inPort in-port
- */
- public void sendNdpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
- byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
- byte[] senderIpAddress = new byte[Ip6Address.BYTE_LENGTH];
- // Retrieves device info.
- if (!getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress)) {
- log.warn("Aborting sendNdpRequest, we cannot get all the information needed");
- return;
- }
- // We have to compute the dst mac address and dst ip address.
- byte[] dstIp = IPv6.getSolicitNodeAddress(targetAddress.toOctets());
- byte[] dstMac = IPv6.getMCastMacAddress(dstIp);
- // Creates the request.
- Ethernet ndpRequest = NeighborSolicitation.buildNdpSolicit(
- targetAddress.getIp6Address(),
- Ip6Address.valueOf(senderIpAddress),
- Ip6Address.valueOf(dstIp),
- MacAddress.valueOf(senderMacAddress),
- MacAddress.valueOf(dstMac),
- VlanId.NONE
- );
- flood(ndpRequest, inPort, targetAddress);
- }
-
- /**
- * Returns link-local IP of given connect point.
- *
- * @param cp connect point
- * @return optional link-local IP
- */
- private Optional<Ip6Address> getLinkLocalIp(ConnectPoint cp) {
- return srManager.interfaceService.getInterfacesByPort(cp)
- .stream()
- .map(Interface::mac)
- .map(MacAddress::toBytes)
- .map(IPv6::getLinkLocalAddress)
- .map(Ip6Address::valueOf)
- .findFirst();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IpHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IpHandler.java
deleted file mode 100644
index c445ac4..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/IpHandler.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IP;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onlab.packet.IpAddress.Version.INET6;
-
-/**
- * Handler of IP packets that forwards IP packets that are sent to the controller,
- * except the ICMP packets which are processed by @link{IcmpHandler}.
- */
-public class IpHandler {
-
- private static Logger log = LoggerFactory.getLogger(IpHandler.class);
- private SegmentRoutingManager srManager;
- private DeviceConfiguration config;
- private ConcurrentHashMap<IpAddress, ConcurrentLinkedQueue<IP>> ipPacketQueue;
-
- /**
- * Creates an IpHandler object.
- *
- * @param srManager SegmentRoutingManager object
- */
- public IpHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- this.config = checkNotNull(srManager.deviceConfiguration);
- ipPacketQueue = new ConcurrentHashMap<>();
- }
-
- /**
- * Enqueues the packet using the destination address as key.
- *
- * @param ipPacket the ip packet to store
- * @param destinationAddress the destination address
- */
- private void enqueuePacket(IP ipPacket, IpAddress destinationAddress) {
-
- ipPacketQueue
- .computeIfAbsent(destinationAddress, a -> new ConcurrentLinkedQueue<>())
- .add(ipPacket);
-
- }
-
- /**
- * Dequeues the packet using the destination address as key.
- *
- * @param ipPacket the ip packet to remove
- * @param destinationAddress the destination address
- */
- public void dequeuePacket(IP ipPacket, IpAddress destinationAddress) {
-
- if (ipPacketQueue.get(destinationAddress) == null) {
- return;
- }
- ipPacketQueue.get(destinationAddress).remove(ipPacket);
- }
-
- /**
- * Forwards the packet to a given host and deque the packet.
- *
- * @param deviceId the target device
- * @param eth the packet to send
- * @param dest the target host
- */
- private void forwardToHost(DeviceId deviceId, Ethernet eth, Host dest) {
- TrafficTreatment treatment = DefaultTrafficTreatment.builder().
- setOutput(dest.location().port()).build();
- OutboundPacket packet = new DefaultOutboundPacket(deviceId,
- treatment, ByteBuffer.wrap(eth.serialize()));
- srManager.packetService.emit(packet);
- }
-
- //////////////////////
- // IPv4 Handling //
- ////////////////////
-
- /**
- * Processes incoming IP packets.
- *
- * If it is an IP packet for known host, then forward it to the host.
- * If it is an IP packet for unknown host in subnet, then send an ARP request
- * to the subnet.
- *
- * @param pkt incoming packet
- * @param connectPoint the target device
- */
- public void processPacketIn(IPv4 pkt, ConnectPoint connectPoint) {
-
- DeviceId deviceId = connectPoint.deviceId();
- Ip4Address destinationAddress = Ip4Address.valueOf(pkt.getDestinationAddress());
-
- // IP packet for know hosts
- if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
- forwardPackets(deviceId, destinationAddress);
-
- // IP packet for unknown host in one of the configured subnets of the router
- } else if (config.inSameSubnet(deviceId, destinationAddress)) {
- srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, connectPoint);
-
- // IP packets for unknown host
- } else {
- log.debug("IPv4 packet for unknown host {} which is not in the subnet",
- destinationAddress);
- // Do nothing
- }
- }
-
- /**
- * Adds the IP packet to a buffer.
- * The packets are forwarded to corresponding destination when the destination
- * MAC address is known via ARP response.
- *
- * @param ipPacket IP packet to add to the buffer
- */
- public void addToPacketBuffer(IPv4 ipPacket) {
-
- // Better not buffer TCP packets due to out-of-order packet transfer
- if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) {
- return;
- }
- IpAddress destIpAddress = IpAddress.valueOf(ipPacket.getDestinationAddress());
- enqueuePacket(ipPacket, destIpAddress);
- }
-
- /**
- * Forwards IP packets in the buffer to the destination IP address.
- * It is called when the controller finds the destination MAC address
- * via ARP responses.
- *
- * @param deviceId switch device ID
- * @param destIpAddress destination IP address
- */
- public void forwardPackets(DeviceId deviceId, Ip4Address destIpAddress) {
- if (ipPacketQueue.get(destIpAddress) == null) {
- return;
- }
- for (IP ipPacket : ipPacketQueue.get(destIpAddress)) {
- if (ipPacket.getVersion() == ((byte) 4)) {
- IPv4 ipv4Packet = (IPv4) ipPacket;
- Ip4Address destAddress = Ip4Address.valueOf(ipv4Packet.getDestinationAddress());
- if (config.inSameSubnet(deviceId, destAddress)) {
- ipv4Packet.setTtl((byte) (ipv4Packet.getTtl() - 1));
- ipv4Packet.setChecksum((short) 0);
- for (Host dest : srManager.hostService.getHostsByIp(destIpAddress)) {
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(dest.mac());
- try {
- eth.setSourceMACAddress(config.getDeviceMac(deviceId));
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Skipping forwardPackets for this destination.");
- continue;
- }
- eth.setEtherType(Ethernet.TYPE_IPV4);
- eth.setPayload(ipv4Packet);
- forwardToHost(deviceId, eth, dest);
- ipPacketQueue.get(destIpAddress).remove(ipPacket);
- }
- ipPacketQueue.get(destIpAddress).remove(ipPacket);
- }
- }
- }
- }
-
- //////////////////////
- // IPv6 Handling //
- ////////////////////
-
- /**
- * Processes incoming IPv6 packets.
- *
- * If it is an IPv6 packet for known host, then forward it to the host.
- * If it is an IPv6 packet for unknown host in subnet, then send an NDP request
- * to the subnet.
- *
- * @param pkt incoming packet
- * @param connectPoint the target device
- */
- public void processPacketIn(IPv6 pkt, ConnectPoint connectPoint) {
-
- DeviceId deviceId = connectPoint.deviceId();
- Ip6Address destinationAddress = Ip6Address.valueOf(pkt.getDestinationAddress());
-
- // IPv6 packet for know hosts
- if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) {
- forwardPackets(deviceId, destinationAddress);
-
- // IPv6 packet for unknown host in one of the configured subnets of the router
- } else if (config.inSameSubnet(deviceId, destinationAddress)) {
- srManager.icmpHandler.sendNdpRequest(deviceId, destinationAddress, connectPoint);
-
- // IPv6 packets for unknown host
- } else {
- log.debug("IPv6 packet for unknown host {} which is not in the subnet",
- destinationAddress);
- }
- }
-
- /**
- * Adds the IPv6 packet to a buffer.
- * The packets are forwarded to corresponding destination when the destination
- * MAC address is known via NDP response.
- *
- * @param ipPacket IP packet to add to the buffer
- */
- public void addToPacketBuffer(IPv6 ipPacket) {
-
- // Better not buffer TCP packets due to out-of-order packet transfer
- if (ipPacket.getNextHeader() == IPv6.PROTOCOL_TCP) {
- return;
- }
- IpAddress destIpAddress = IpAddress.valueOf(INET6, ipPacket.getDestinationAddress());
- enqueuePacket(ipPacket, destIpAddress);
- }
-
- /**
- * Forwards IP packets in the buffer to the destination IP address.
- * It is called when the controller finds the destination MAC address
- * via NDP replies.
- *
- * @param deviceId the target device
- * @param destIpAddress the destination ip address
- */
- public void forwardPackets(DeviceId deviceId, Ip6Address destIpAddress) {
- if (ipPacketQueue.get(destIpAddress) == null) {
- return;
- }
- for (IP ipPacket : ipPacketQueue.get(destIpAddress)) {
- if (ipPacket.getVersion() == ((byte) 6)) {
- IPv6 ipv6Packet = (IPv6) ipPacket;
- Ip6Address destAddress = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
- if (config.inSameSubnet(deviceId, destAddress)) {
- ipv6Packet.setHopLimit((byte) (ipv6Packet.getHopLimit() - 1));
- for (Host dest : srManager.hostService.getHostsByIp(destIpAddress)) {
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(dest.mac());
- try {
- eth.setSourceMACAddress(config.getDeviceMac(deviceId));
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Skipping forwardPackets for this destination.");
- continue;
- }
- eth.setEtherType(Ethernet.TYPE_IPV6);
- eth.setPayload(ipv6Packet);
- forwardToHost(deviceId, eth, dest);
- ipPacketQueue.get(destIpAddress).remove(ipPacket);
- }
- ipPacketQueue.get(destIpAddress).remove(ipPacket);
- }
- }
- ipPacketQueue.get(destIpAddress).remove(ipPacket);
- }
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
deleted file mode 100644
index 2193c95..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
+++ /dev/null
@@ -1,736 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.onosproject.store.service.EventuallyConsistentMapBuilder;
-import org.onosproject.store.service.WallClockTimestamp;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
-
-
-public class LinkHandler {
- private static final Logger log = LoggerFactory.getLogger(LinkHandler.class);
- protected final SegmentRoutingManager srManager;
-
- // Local store for all links seen and their present status, used for
- // optimized routing. The existence of the link in the keys is enough to know
- // if the link has been "seen-before" by this instance of the controller.
- // The boolean value indicates if the link is currently up or not.
- // Currently the optimized routing logic depends on "forgetting" a link
- // when a switch goes down, but "remembering" it when only the link goes down.
- private Map<Link, Boolean> seenLinks = new ConcurrentHashMap<>();
- private Set<Link> seenBefore = Sets.newConcurrentHashSet();
- private EventuallyConsistentMap<DeviceId, Set<PortNumber>> downedPortStore = null;
-
- /**
- * Constructs the LinkHandler.
- *
- * @param srManager Segment Routing manager
- */
- LinkHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- log.debug("Creating EC map downedportstore");
- EventuallyConsistentMapBuilder<DeviceId, Set<PortNumber>> downedPortsMapBuilder
- = srManager.storageService.eventuallyConsistentMapBuilder();
- downedPortStore = downedPortsMapBuilder.withName("downedportstore")
- .withSerializer(srManager.createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
- log.trace("Current size {}", downedPortStore.size());
- }
-
- /**
- * Constructs the LinkHandler for unit-testing.
- *
- * @param srManager SegmentRoutingManager
- * @param linkService LinkService
- */
- LinkHandler(SegmentRoutingManager srManager, LinkService linkService) {
- this.srManager = srManager;
- }
-
- /**
- * Initialize LinkHandler.
- */
- void init() {
- log.info("Loading stored links");
- srManager.linkService.getActiveLinks().forEach(this::processLinkAdded);
- }
-
- /**
- * Preprocessing of added link before being sent for route-path handling.
- * Also performs post processing of link.
- *
- * @param link the link to be processed
- */
- void processLinkAdded(Link link) {
- log.info("** LINK ADDED {}", link.toString());
- if (!isLinkValid(link)) {
- return;
- }
- // Irrespective of whether the local is a MASTER or not for this device,
- // create group handler instance and push default TTP flow rules if needed,
- // as in a multi-instance setup, instances can initiate groups for any
- // device. Also update local groupHandler stores.
- DefaultGroupHandler groupHandler = srManager.groupHandlerMap
- .get(link.src().deviceId());
- if (groupHandler == null) {
- Device device = srManager.deviceService.getDevice(link.src().deviceId());
- if (device != null) {
- log.warn("processLinkAdded: Link Added notification without "
- + "Device Added event, still handling it");
- srManager.processDeviceAdded(device);
- }
- }
-
- if (isSeenLink(link)) {
- // temp store retains previous state, just before the state is updated in
- // seenLinks; previous state is necessary when processing the
- // linkupdate in defaultRoutingHandler
- seenBefore.add(link);
- }
- updateSeenLink(link, true);
-
- if (srManager.deviceConfiguration == null ||
- !srManager.deviceConfiguration.isConfigured(link.src().deviceId())) {
- log.warn("Source device of this link is not configured.. "
- + "not processing further");
- return;
- }
-
- // process link only if it is bidirectional
- if (!isBidirectionalLinkUp(link)) {
- log.debug("Link not bidirectional.. waiting for other direction " +
- "src {} --> dst {} ", link.dst(), link.src());
- return;
- }
-
- log.info("processing bidi links {} <--> {} UP", link.src(), link.dst());
- // update groupHandler internal port state for both directions
- List<Link> ulinks = getBidiComponentLinks(link);
- for (Link ulink : ulinks) {
- DefaultGroupHandler gh = srManager.groupHandlerMap
- .get(ulink.src().deviceId());
- if (gh != null) {
- gh.portUpForLink(ulink);
- }
- }
-
- for (Link ulink : ulinks) {
- log.info("-- Starting optimized route-path processing for component "
- + "unidirectional link {} --> {} UP", ulink.src(), ulink.dst());
- srManager.defaultRoutingHandler
- .populateRoutingRulesForLinkStatusChange(null, ulink, null,
- seenBefore.contains(ulink));
-
- if (srManager.mastershipService.isLocalMaster(ulink.src().deviceId())) {
- // handle edge-ports for dual-homed hosts
- updateHostPorts(ulink, true);
-
- // It's possible that linkUp causes no route-path change as ECMP graph does
- // not change if the link is a parallel link (same src-dst as
- // another link). However we still need to update ECMP hash
- // groups to include new buckets for the link that has come up.
- DefaultGroupHandler gh = srManager.groupHandlerMap
- .get(ulink.src().deviceId());
- if (gh != null) {
- if (!seenBefore.contains(ulink) && isParallelLink(ulink)) {
- // if link seen first time, we need to ensure hash-groups have
- // all ports
- log.debug("Attempting retryHash for paralled first-time link {}",
- ulink);
- gh.retryHash(ulink, false, true);
- } else {
- // seen before-link
- if (isParallelLink(ulink)) {
- log.debug("Attempting retryHash for paralled seen-before "
- + "link {}", ulink);
- gh.retryHash(ulink, false, false);
- }
- }
- }
- }
- //clean up temp state
- seenBefore.remove(ulink);
- }
-
- }
-
- /**
- * Preprocessing of removed link before being sent for route-path handling.
- * Also performs post processing of link.
- *
- * @param link the link to be processed
- */
- void processLinkRemoved(Link link) {
- log.info("** LINK REMOVED {}", link.toString());
- if (!isLinkValid(link)) {
- return;
- }
- // when removing links, update seen links first, before doing route-path
- // changes
- updateSeenLink(link, false);
- // handle edge-ports for dual-homed hosts
- if (srManager.mastershipService.isLocalMaster(link.src().deviceId())) {
- updateHostPorts(link, false);
- }
-
- // device availability check helps to ensure that multiple link-removed
- // events are actually treated as a single switch removed event.
- // purgeSeenLink is necessary so we do rerouting (instead of rehashing)
- // when switch comes back.
- if (link.src().elementId() instanceof DeviceId
- && !srManager.deviceService.isAvailable(link.src().deviceId())) {
- purgeSeenLink(link);
- return;
- }
- if (link.dst().elementId() instanceof DeviceId
- && !srManager.deviceService.isAvailable(link.dst().deviceId())) {
- purgeSeenLink(link);
- return;
- }
-
- // process link only if it is bidirectional
- if (!isBidirectionalLinkDown(link)) {
- log.debug("Link not bidirectional.. waiting for other direction " +
- "src {} --> dst {} ", link.dst(), link.src());
- return;
- }
- log.info("processing bidi links {} <--> {} DOWN", link.src(), link.dst());
-
- for (Link ulink : getBidiComponentLinks(link)) {
- log.info("-- Starting optimized route-path processing for component "
- + "unidirectional link {} --> {} DOWN", ulink.src(), ulink.dst());
- srManager.defaultRoutingHandler
- .populateRoutingRulesForLinkStatusChange(ulink, null, null, true);
-
- // attempt rehashing for parallel links
- DefaultGroupHandler groupHandler = srManager.groupHandlerMap
- .get(ulink.src().deviceId());
- if (groupHandler != null) {
- if (srManager.mastershipService.isLocalMaster(ulink.src().deviceId())
- && isParallelLink(ulink)) {
- log.debug("* retrying hash for parallel link removed:{}", ulink);
- groupHandler.retryHash(ulink, true, false);
- } else {
- log.debug("Not attempting retry-hash for link removed: {} .. {}",
- ulink,
- (srManager.mastershipService.isLocalMaster(ulink
- .src().deviceId())) ? "not parallel"
- : "not master");
- }
- // ensure local stores are updated after all rerouting or rehashing
- groupHandler.portDownForLink(ulink);
- } else {
- log.warn("group handler not found for dev:{} when removing link: {}",
- ulink.src().deviceId(), ulink);
- }
- }
- }
-
- /**
- * Checks validity of link. Examples of invalid links include
- * indirect-links, links between ports on the same switch, and more.
- *
- * @param link the link to be processed
- * @return true if valid link
- */
- boolean isLinkValid(Link link) {
- if (link.type() != Link.Type.DIRECT) {
- // NOTE: A DIRECT link might be transiently marked as INDIRECT
- // if BDDP is received before LLDP. We can safely ignore that
- // until the LLDP is received and the link is marked as DIRECT.
- log.info("Ignore link {}->{}. Link type is {} instead of DIRECT.",
- link.src(), link.dst(), link.type());
- return false;
- }
- DeviceId srcId = link.src().deviceId();
- DeviceId dstId = link.dst().deviceId();
- if (srcId.equals(dstId)) {
- log.warn("Links between ports on the same switch are not "
- + "allowed .. ignoring link {}", link);
- return false;
- }
- DeviceConfiguration devConfig = srManager.deviceConfiguration;
- if (devConfig == null) {
- log.warn("Cannot check validity of link without device config");
- return true;
- }
- try {
- /*if (!devConfig.isEdgeDevice(srcId)
- && !devConfig.isEdgeDevice(dstId)) {
- // ignore links between spines
- // XXX revisit when handling multi-stage fabrics
- log.warn("Links between spines not allowed...ignoring "
- + "link {}", link);
- return false;
- }*/
- if (devConfig.isEdgeDevice(srcId)
- && devConfig.isEdgeDevice(dstId)) {
- // ignore links between leaves if they are not pair-links
- // XXX revisit if removing pair-link config or allowing more than
- // one pair-link
- if (devConfig.getPairDeviceId(srcId).equals(dstId)
- && devConfig.getPairLocalPort(srcId)
- .equals(link.src().port())
- && devConfig.getPairLocalPort(dstId)
- .equals(link.dst().port())) {
- // found pair link - allow it
- return true;
- } else {
- log.warn("Links between leaves other than pair-links are "
- + "not allowed...ignoring link {}", link);
- return false;
- }
- }
- } catch (DeviceConfigNotFoundException e) {
- // We still want to count the links in seenLinks even though there
- // is no config. So we let it return true
- log.warn("Could not check validity of link {} as subtending devices "
- + "are not yet configured", link);
- }
- return true;
- }
-
- /**
- * Administratively enables or disables edge ports if the link that was
- * added or removed was the only uplink port from an edge device. Edge ports
- * that belong to dual-homed hosts are always processed. In addition,
- * single-homed host ports are optionally processed depending on the
- * singleHomedDown property.
- *
- * @param link the link to be processed
- * @param added true if link was added, false if link was removed
- */
- private void updateHostPorts(Link link, boolean added) {
- DeviceConfiguration devConfig = srManager.deviceConfiguration;
- if (added) {
- try {
- if (!devConfig.isEdgeDevice(link.src().deviceId())
- || devConfig.isEdgeDevice(link.dst().deviceId())) {
- return;
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn("Unable to determine if link is a valid uplink"
- + e.getMessage());
- }
- // re-enable previously disabled ports on this edge-device if any
- Set<PortNumber> p = downedPortStore.remove(link.src().deviceId());
- if (p != null) {
- log.warn("Link src {} --> dst {} added is an edge-device uplink, "
- + "enabling dual homed ports if any: {}", link.src().deviceId(),
- link.dst().deviceId(), (p.isEmpty()) ? "no ports" : p);
- p.forEach(pnum -> srManager.deviceAdminService
- .changePortState(link.src().deviceId(), pnum, true));
- }
- } else {
- // If the device does not have a pair device - skip
- DeviceId dev = link.src().deviceId();
- if (getPairDeviceIdOrNull(dev) == null) {
- log.info("Device {} does not have pair device " +
- "not disabling access port", dev);
- return;
- }
- // Verify if last uplink
- if (!lastUplink(link)) {
- return;
- }
- // find dual homed hosts on this dev to disable
- Set<PortNumber> dp = srManager.hostHandler
- .getDualHomedHostPorts(dev);
- log.warn("Link src {} --> dst {} removed was the last uplink, "
- + "disabling dual homed ports: {}", dev,
- link.dst().deviceId(), (dp.isEmpty()) ? "no ports" : dp);
- dp.forEach(pnum -> srManager.deviceAdminService
- .changePortState(dev, pnum, false));
- if (srManager.singleHomedDown) {
- // get all configured ports and down them if they haven't already
- // been downed
- srManager.deviceService.getPorts(dev).stream()
- .filter(p -> p.isEnabled() && !dp.contains(p.number()))
- .filter(p -> srManager.interfaceService
- .isConfigured(new ConnectPoint(dev, p.number())))
- .filter(p -> !srManager.deviceConfiguration
- .isPairLocalPort(dev, p.number()))
- .forEach(p -> {
- log.warn("Last uplink gone src {} -> dst {} .. removing "
- + "configured port {}", p.number());
- srManager.deviceAdminService
- .changePortState(dev, p.number(), false);
- dp.add(p.number());
- });
- }
- if (!dp.isEmpty()) {
- // update global store
- Set<PortNumber> p = downedPortStore.get(dev);
- if (p == null) {
- p = dp;
- } else {
- p.addAll(dp);
- }
- downedPortStore.put(link.src().deviceId(), p);
- }
- }
- }
-
- /**
- * Returns true if given link was the last active uplink from src-device of
- * link. An uplink is defined as a unidirectional link with src as
- * edgeRouter and dst as non-edgeRouter.
- *
- * @param link
- * @return true if given link was the last uplink from the src device
- */
- private boolean lastUplink(Link link) {
- DeviceConfiguration devConfig = srManager.deviceConfiguration;
- try {
- if (!devConfig.isEdgeDevice(link.src().deviceId())
- || devConfig.isEdgeDevice(link.dst().deviceId())) {
- return false;
- }
- // note that using linkservice here would cause race conditions as
- // more links can show up while the app is still processing the first one
- Set<Link> devLinks = seenLinks.entrySet().stream()
- .filter(entry -> entry.getKey().src().deviceId()
- .equals(link.src().deviceId()))
- .filter(entry -> entry.getValue())
- .filter(entry -> !entry.getKey().equals(link))
- .map(entry -> entry.getKey())
- .collect(Collectors.toSet());
-
- for (Link l : devLinks) {
- if (devConfig.isEdgeDevice(l.dst().deviceId())) {
- continue;
- }
- log.debug("Found another active uplink {}", l);
- return false;
- }
- log.debug("No active uplink found");
- return true;
- } catch (DeviceConfigNotFoundException e) {
- log.warn("Unable to determine if link was the last uplink"
- + e.getMessage());
- }
- return false;
- }
-
- /**
- * Returns true if this controller instance has seen this link before. The
- * link may not be currently up, but as long as the link had been seen
- * before this method will return true. The one exception is when the link
- * was indeed seen before, but this controller instance was forced to forget
- * it by a call to purgeSeenLink method.
- *
- * @param link the infrastructure link being queried
- * @return true if this controller instance has seen this link before
- */
- boolean isSeenLink(Link link) {
- return seenLinks.containsKey(link);
- }
-
- /**
- * Updates the seen link store. Updates can be for links that are currently
- * available or not.
- *
- * @param link the link to update in the seen-link local store
- * @param up the status of the link, true if up, false if down
- */
- void updateSeenLink(Link link, boolean up) {
- seenLinks.put(link, up);
- }
-
- /**
- * Returns the status of a seen-link (up or down). If the link has not been
- * seen-before, a null object is returned.
- *
- * @param link the infrastructure link being queried
- * @return null if the link was not seen-before; true if the seen-link is
- * up; false if the seen-link is down
- */
- private Boolean isSeenLinkUp(Link link) {
- return seenLinks.get(link);
- }
-
- /**
- * Makes this controller instance forget a previously seen before link.
- *
- * @param link the infrastructure link to purge
- */
- private void purgeSeenLink(Link link) {
- seenLinks.remove(link);
- seenBefore.remove(link);
- }
-
- /**
- * Returns the status of a link as parallel link. A parallel link is defined
- * as a link which has common src and dst switches as another seen-link that
- * is currently enabled. It is not necessary for the link being queried to
- * be a seen-link.
- *
- * @param link the infrastructure link being queried
- * @return true if a seen-link exists that is up, and shares the same src
- * and dst switches as the link being queried
- */
- private boolean isParallelLink(Link link) {
- for (Entry<Link, Boolean> seen : seenLinks.entrySet()) {
- Link seenLink = seen.getKey();
- if (seenLink.equals(link)) {
- continue;
- }
- if (seenLink.src().deviceId().equals(link.src().deviceId())
- && seenLink.dst().deviceId().equals(link.dst().deviceId())
- && seen.getValue()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns true if the link being queried is a bidirectional link that is
- * up. A bidi-link is defined as a component unidirectional link, whose
- * reverse link - ie. the component unidirectional link in the reverse
- * direction - has been seen-before and is up. It is NOT necessary for the
- * link being queried to be a previously seen-link.
- *
- * @param link the infrastructure (unidirectional) link being queried
- * @return true if another unidirectional link exists in the reverse
- * direction, has been seen-before and is up
- */
- boolean isBidirectionalLinkUp(Link link) {
- // cannot call linkService as link may be gone
- Link reverseLink = getReverseLink(link);
- if (reverseLink == null) {
- return false;
- }
- Boolean result = isSeenLinkUp(reverseLink);
- if (result == null) {
- return false;
- }
- return result.booleanValue();
- }
-
- /**
- * Returns true if the link being queried is a bidirectional link that is
- * down. A bidi-link is defined as a component unidirectional link, whose
- * reverse link - i.e the component unidirectional link in the reverse
- * direction - has been seen before and is down. It is necessary for the
- * reverse-link to have been previously seen.
- *
- * @param link the infrastructure (unidirectional) link being queried
- * @return true if another unidirectional link exists in the reverse
- * direction, has been seen-before and is down
- */
- boolean isBidirectionalLinkDown(Link link) {
- // cannot call linkService as link may be gone
- Link reverseLink = getReverseLink(link);
- if (reverseLink == null) {
- log.warn("Query for bidi-link down but reverse-link not found "
- + "for link {}", link);
- return false;
- }
- Boolean result = seenLinks.get(reverseLink);
- if (result == null) {
- return false;
- }
- // if reverse link is seen UP (true), then its not bidi yet
- return !result.booleanValue();
- }
-
- /**
- * Returns the link in the reverse direction from the given link, by
- * consulting the seen-links store.
- *
- * @param link the given link
- * @return the reverse link or null
- */
- Link getReverseLink(Link link) {
- return seenLinks.keySet().stream()
- .filter(l -> l.src().equals(link.dst()) && l.dst().equals(link.src()))
- .findAny()
- .orElse(null);
- }
-
- /**
- * Returns the component unidirectional links of a declared bidirectional
- * link, by consulting the seen-links store. Caller is responsible for
- * previously verifying bidirectionality. Returned list may be empty if
- * errors are encountered.
- *
- * @param link the declared bidirectional link
- * @return list of component unidirectional links
- */
- List<Link> getBidiComponentLinks(Link link) {
- Link reverseLink = getReverseLink(link);
- List<Link> componentLinks;
- if (reverseLink == null) { // really should not happen if link is bidi
- log.error("cannot find reverse link for given link: {} ... is it "
- + "bi-directional?", link);
- componentLinks = ImmutableList.of();
- } else {
- componentLinks = ImmutableList.of(reverseLink, link);
- }
- return componentLinks;
- }
-
- /**
- * Determines if the given link should be avoided in routing calculations by
- * policy or design.
- *
- * @param link the infrastructure link being queried
- * @return true if link should be avoided
- */
- boolean avoidLink(Link link) {
- // XXX currently only avoids all pair-links. In the future can be
- // extended to avoid any generic link
- DeviceId src = link.src().deviceId();
- PortNumber srcPort = link.src().port();
- DeviceConfiguration devConfig = srManager.deviceConfiguration;
- if (devConfig == null || !devConfig.isConfigured(src)) {
- log.warn("Device {} not configured..cannot avoid link {}", src,
- link);
- return false;
- }
- DeviceId pairDev;
- PortNumber pairLocalPort, pairRemotePort = null;
- try {
- pairDev = devConfig.getPairDeviceId(src);
- pairLocalPort = devConfig.getPairLocalPort(src);
- if (pairDev != null) {
- pairRemotePort = devConfig
- .getPairLocalPort(pairDev);
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn("Pair dev for dev {} not configured..cannot avoid link {}",
- src, link);
- return false;
- }
-
- return srcPort.equals(pairLocalPort)
- && link.dst().deviceId().equals(pairDev)
- && link.dst().port().equals(pairRemotePort);
- }
-
- /**
- * Cleans up internal LinkHandler stores.
- *
- * @param device the device that has been removed
- */
- void processDeviceRemoved(Device device) {
- seenLinks.keySet()
- .removeIf(key -> key.src().deviceId().equals(device.id())
- || key.dst().deviceId().equals(device.id()));
- }
-
- /**
- * Administratively disables the host location switchport if the edge device
- * has no viable uplinks. The caller needs to determine if such behavior is
- * desired for the single or dual-homed host.
- *
- * @param loc the host location
- */
- void checkUplinksForHost(HostLocation loc) {
- // If the device does not have a pair device - return
- if (getPairDeviceIdOrNull(loc.deviceId()) == null) {
- log.info("Device {} does not have pair device " +
- "not disabling access port", loc.deviceId());
- return;
- }
- // Verify link validity
- try {
- for (Link l : srManager.linkService.getDeviceLinks(loc.deviceId())) {
- if (srManager.deviceConfiguration.isEdgeDevice(l.dst().deviceId())
- || l.state() == Link.State.INACTIVE) {
- continue;
- }
- // found valid uplink - so, nothing to do
- return;
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn("Could not check for valid uplinks due to missing device"
- + "config " + e.getMessage());
- return;
- }
- log.warn("Host location {} has no valid uplinks disabling port", loc);
- srManager.deviceAdminService.changePortState(loc.deviceId(), loc.port(),
- false);
- Set<PortNumber> p = downedPortStore.get(loc.deviceId());
- if (p == null) {
- p = Sets.newHashSet(loc.port());
- } else {
- p.add(loc.port());
- }
- downedPortStore.put(loc.deviceId(), p);
- }
-
- private DeviceId getPairDeviceIdOrNull(DeviceId deviceId) {
- DeviceId pairDev;
- try {
- pairDev = srManager.deviceConfiguration.getPairDeviceId(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- pairDev = null;
- }
- return pairDev;
- }
-
- ImmutableMap<Link, Boolean> getSeenLinks() {
- return ImmutableMap.copyOf(seenLinks);
- }
-
- ImmutableMap<DeviceId, Set<PortNumber>> getDownedPorts() {
- return ImmutableMap.copyOf(downedPortStore.entrySet());
- }
-
- /**
- * Returns all links that egress from given device that are UP in the
- * seenLinks store. The returned links are also confirmed to be
- * bidirectional.
- *
- * @param deviceId the device identifier
- * @return set of egress links from the device
- */
- Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
- return seenLinks.keySet().stream()
- .filter(link -> link.src().deviceId().equals(deviceId))
- .filter(link -> seenLinks.get(link))
- .filter(link -> isBidirectionalLinkUp(link))
- .collect(Collectors.toSet());
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java
deleted file mode 100644
index ac63f73..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/OsgiPropertyConstants.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-/**
- * Constants for default values of configurable properties.
- */
-public final class OsgiPropertyConstants {
-
- private OsgiPropertyConstants() {}
-
- public static final String PROP_ACTIVE_PROBING = "activeProbing";
- public static final boolean ACTIVE_PROBING_DEFAULT = true;
-
- public static final String PROP_SINGLE_HOMED_DOWN = "singleHomedDown";
- public static final boolean SINGLE_HOMED_DOWN_DEFAULT = false;
-
- public static final String PROP_RESPOND_TO_UNKNOWN_HOSTS = "respondToUnknownHosts";
- public static final boolean RESPOND_TO_UNKNOWN_HOSTS_DEFAULT = true;
-
- public static final String PROP_ROUTE_DOUBLE_TAGGED_HOSTS = "routeDoubleTaggedHosts";
- public static final boolean ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT = false;
-
- public static final String PROP_DEFAULT_INTERNAL_VLAN = "defaultInternalVlan";
- public static final int DEFAULT_INTERNAL_VLAN_DEFAULT = 4094;
-
- public static final String PROP_PW_TRANSPORT_VLAN = "pwTransportVlan";
- public static final int PW_TRANSPORT_VLAN_DEFAULT = 4090;
-
- static final String PROP_SYMMETRIC_PROBING = "symmetricProbing";
- static final boolean SYMMETRIC_PROBING_DEFAULT = false;
-
- public static final String PROP_ROUTE_SIMPLIFICATION = "routeSimplification";
- public static final boolean ROUTE_SIMPLIFICATION_DEFAULT = false;
-
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Policy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Policy.java
deleted file mode 100644
index c9baf93..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Policy.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-/**
- * Interface for Segment Routing Policy.
- */
-public interface Policy {
- /**
- * Enums for policy type.
- */
- enum Type {
- /**
- * Tunnel flow policy type.
- */
- TUNNEL_FLOW,
-
- /**
- * Load balancing policy type.
- */
- LOADBALANCE,
-
- /**
- * policy to avoid specific routers or links.
- */
- AVOID,
-
- /**
- * Access Control policy type.
- */
- DENY
- }
-
- /**
- * Returns the policy ID.
- *
- * @return policy ID
- */
- String id();
-
- /**
- * Returns the priority of the policy.
- *
- * @return priority
- */
- int priority();
-
- /**
- * Returns the policy type.
- *
- * @return policy type
- */
- Type type();
-
- /**
- * Returns the source IP address of the policy.
- *
- * @return source IP address
- */
- String srcIp();
-
- /**
- * Returns the destination IP address of the policy.
- *
- * @return destination IP address
- */
- String dstIp();
-
- /**
- * Returns the IP protocol of the policy.
- *
- * @return IP protocol
- */
- String ipProto();
-
- /**
- * Returns the source port of the policy.
- *
- * @return source port
- */
- short srcPort();
-
- /**
- * Returns the destination of the policy.
- *
- * @return destination port
- */
- short dstPort();
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
deleted file mode 100644
index a341bb1..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.TpPort;
-import org.onosproject.cli.net.IpProtocol;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.slf4j.Logger;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Segment Routing Policy Handler.
- */
-public class PolicyHandler {
-
- protected final Logger log = getLogger(getClass());
-
- private ApplicationId appId;
- private DeviceConfiguration deviceConfiguration;
- private FlowObjectiveService flowObjectiveService;
- private TunnelHandler tunnelHandler;
- private final EventuallyConsistentMap<String, Policy> policyStore;
- /**
- * Result of policy creation.
- */
- public enum Result {
- /**
- * Success.
- */
- SUCCESS,
-
- /**
- * The same policy exists already.
- */
- POLICY_EXISTS,
-
- /**
- * The policy ID exists already.
- */
- ID_EXISTS,
-
- /**
- * Cannot find associated tunnel.
- */
- TUNNEL_NOT_FOUND,
-
- /**
- * Policy was not found.
- */
- POLICY_NOT_FOUND,
-
- /**
- * Policy type {} is not supported yet.
- */
- UNSUPPORTED_TYPE
- }
-
- /**
- * Constructs policy handler.
- *
- * @param appId segment routing application ID
- * @param deviceConfiguration DeviceConfiguration reference
- * @param flowObjectiveService FlowObjectiveService reference
- * @param tunnelHandler tunnel handler reference
- * @param policyStore policy store
- */
- public PolicyHandler(ApplicationId appId,
- DeviceConfiguration deviceConfiguration,
- FlowObjectiveService flowObjectiveService,
- TunnelHandler tunnelHandler,
- EventuallyConsistentMap<String, Policy> policyStore) {
- this.appId = appId;
- this.deviceConfiguration = deviceConfiguration;
- this.flowObjectiveService = flowObjectiveService;
- this.tunnelHandler = tunnelHandler;
- this.policyStore = policyStore;
- }
-
- /**
- * Returns the policies.
- *
- * @return policy list
- */
- public List<Policy> getPolicies() {
- return policyStore.values()
- .stream()
- .filter(policy -> policy instanceof TunnelPolicy)
- .map(policy -> new TunnelPolicy((TunnelPolicy) policy))
- .collect(Collectors.toList());
- }
-
- /**
- * Creates a policy using the policy information given.
- * @param policy policy reference to create
- * @return ID_EXISTS if the same policy ID exists,
- * POLICY_EXISTS if the same policy exists, TUNNEL_NOT_FOUND if the tunnel
- * does not exists, UNSUPPORTED_TYPE if the policy type is not supported,
- * SUCCESS if the policy is created successfully
- */
- public Result createPolicy(Policy policy) {
-
- if (policyStore.containsKey(policy.id())) {
- log.warn("The policy id {} exists already", policy.id());
- return Result.ID_EXISTS;
- }
-
- if (policyStore.containsValue(policy)) {
- log.warn("The same policy exists already");
- return Result.POLICY_EXISTS;
- }
-
- if (policy.type() == Policy.Type.TUNNEL_FLOW) {
-
- TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
- Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());
- if (tunnel == null) {
- return Result.TUNNEL_NOT_FOUND;
- }
-
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder()
- .fromApp(appId)
- .makePermanent()
- .nextStep(tunnel.groupId())
- .withPriority(tunnelPolicy.priority())
- .withSelector(buildSelector(policy))
- .withFlag(ForwardingObjective.Flag.VERSATILE);
-
- DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
- flowObjectiveService.forward(source, fwdBuilder.add());
-
- } else {
- log.warn("Policy type {} is not supported yet.", policy.type());
- return Result.UNSUPPORTED_TYPE;
- }
-
- policyStore.put(policy.id(), policy);
-
- return Result.SUCCESS;
- }
-
- /**
- * Removes the policy given.
- *
- * @param policyInfo policy information to remove
- * @return POLICY_NOT_FOUND if the policy to remove does not exists,
- * SUCCESS if it is removed successfully
- */
- public Result removePolicy(Policy policyInfo) {
-
- if (policyStore.get(policyInfo.id()) != null) {
- Policy policy = policyStore.get(policyInfo.id());
- if (policy.type() == Policy.Type.TUNNEL_FLOW) {
- TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
- Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());
-
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder()
- .fromApp(appId)
- .makePermanent()
- .withSelector(buildSelector(policy))
- .withPriority(tunnelPolicy.priority())
- .nextStep(tunnel.groupId())
- .withFlag(ForwardingObjective.Flag.VERSATILE);
-
- DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
- flowObjectiveService.forward(source, fwdBuilder.remove());
-
- policyStore.remove(policyInfo.id());
- }
- } else {
- log.warn("Policy {} was not found", policyInfo.id());
- return Result.POLICY_NOT_FOUND;
- }
-
- return Result.SUCCESS;
- }
-
-
- private TrafficSelector buildSelector(Policy policy) {
-
- TrafficSelector.Builder tsb = DefaultTrafficSelector.builder();
- tsb.matchEthType(Ethernet.TYPE_IPV4);
- if (policy.dstIp() != null && !policy.dstIp().isEmpty()) {
- tsb.matchIPDst(IpPrefix.valueOf(policy.dstIp()));
- }
- if (policy.srcIp() != null && !policy.srcIp().isEmpty()) {
- tsb.matchIPSrc(IpPrefix.valueOf(policy.srcIp()));
- }
- if (policy.ipProto() != null && !policy.ipProto().isEmpty()) {
- Short ipProto = IpProtocol.valueOf(policy.ipProto()).value();
- tsb.matchIPProtocol(ipProto.byteValue());
- if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.TCP)) {
- if (policy.srcPort() != 0) {
- tsb.matchTcpSrc(TpPort.tpPort(policy.srcPort()));
- }
- if (policy.dstPort() != 0) {
- tsb.matchTcpDst(TpPort.tpPort(policy.dstPort()));
- }
- } else if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.UDP)) {
- if (policy.srcPort() != 0) {
- tsb.matchUdpSrc(TpPort.tpPort(policy.srcPort()));
- }
- if (policy.dstPort() != 0) {
- tsb.matchUdpDst(TpPort.tpPort(policy.dstPort()));
- }
- }
- }
-
- return tsb.build();
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortAuthTracker.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortAuthTracker.java
deleted file mode 100644
index 2127019..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortAuthTracker.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-
-import com.google.common.base.Objects;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.config.BlockedPortsConfig;
-import org.onosproject.utils.Comparators;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Keeps track of ports that have been configured for blocking,
- * and their current authentication state.
- */
-public class PortAuthTracker {
-
- private static final Logger log = getLogger(PortAuthTracker.class);
-
- private Map<DeviceId, Map<PortNumber, BlockState>> blockedPorts = new HashMap<>();
- private Map<DeviceId, Map<PortNumber, BlockState>> oldMap;
-
- @Override
- public String toString() {
- return "PortAuthTracker{entries = " + blockedPorts.size() + "}";
- }
-
- /**
- * Changes the state of the given device id / port number pair to the
- * specified state.
- *
- * @param d device identifier
- * @param p port number
- * @param newState the updated state
- * @return true, if the state changed from what was previously mapped
- */
- private boolean changeStateTo(DeviceId d, PortNumber p, BlockState newState) {
- Map<PortNumber, BlockState> portMap =
- blockedPorts.computeIfAbsent(d, k -> new HashMap<>());
- BlockState oldState =
- portMap.computeIfAbsent(p, k -> BlockState.UNCHECKED);
- portMap.put(p, newState);
- return (oldState != newState);
- }
-
- /**
- * Radius has authorized the supplicant at this connect point. If
- * we are tracking this port, clear the blocking flow and mark the
- * port as authorized.
- *
- * @param connectPoint supplicant connect point
- */
- void radiusAuthorize(ConnectPoint connectPoint) {
- DeviceId d = connectPoint.deviceId();
- PortNumber p = connectPoint.port();
- if (configured(d, p)) {
- clearBlockingFlow(d, p);
- markAsAuthenticated(d, p);
- }
- }
-
- /**
- * Supplicant at specified connect point has logged off Radius. If
- * we are tracking this port, install a blocking flow and mark the
- * port as blocked.
- *
- * @param connectPoint supplicant connect point
- */
- void radiusLogoff(ConnectPoint connectPoint) {
- DeviceId d = connectPoint.deviceId();
- PortNumber p = connectPoint.port();
- if (configured(d, p)) {
- installBlockingFlow(d, p);
- markAsBlocked(d, p);
- }
- }
-
- /**
- * Marks the specified device/port as blocked.
- *
- * @param d device id
- * @param p port number
- * @return true if the state changed (was not already blocked)
- */
- private boolean markAsBlocked(DeviceId d, PortNumber p) {
- return changeStateTo(d, p, BlockState.BLOCKED);
- }
-
- /**
- * Marks the specified device/port as authenticated.
- *
- * @param d device id
- * @param p port number
- * @return true if the state changed (was not already authenticated)
- */
- private boolean markAsAuthenticated(DeviceId d, PortNumber p) {
- return changeStateTo(d, p, BlockState.AUTHENTICATED);
- }
-
- /**
- * Returns true if the given device/port are configured for blocking.
- *
- * @param d device id
- * @param p port number
- * @return true if this device/port configured for blocking
- */
- private boolean configured(DeviceId d, PortNumber p) {
- Map<PortNumber, BlockState> portMap = blockedPorts.get(d);
- return portMap != null && portMap.get(p) != null;
- }
-
- private BlockState whatState(DeviceId d, PortNumber p,
- Map<DeviceId, Map<PortNumber, BlockState>> m) {
- Map<PortNumber, BlockState> portMap = m.get(d);
- if (portMap == null) {
- return BlockState.UNCHECKED;
- }
- BlockState state = portMap.get(p);
- if (state == null) {
- return BlockState.UNCHECKED;
- }
- return state;
- }
-
- /**
- * Returns the current state of the given device/port.
- *
- * @param d device id
- * @param p port number
- * @return current block-state
- */
- BlockState currentState(DeviceId d, PortNumber p) {
- return whatState(d, p, blockedPorts);
- }
-
- /**
- * Returns the current state of the given connect point.
- *
- * @param cp connect point
- * @return current block-state
- */
-
- BlockState currentState(ConnectPoint cp) {
- return whatState(cp.deviceId(), cp.port(), blockedPorts);
- }
-
- /**
- * Returns the number of entries being tracked.
- *
- * @return the number of tracked entries
- */
- int entryCount() {
- int count = 0;
- for (Map<PortNumber, BlockState> m : blockedPorts.values()) {
- count += m.size();
- }
- return count;
- }
-
- /**
- * Returns the previously recorded state of the given device/port.
- *
- * @param d device id
- * @param p port number
- * @return previous block-state
- */
- private BlockState oldState(DeviceId d, PortNumber p) {
- return whatState(d, p, oldMap);
- }
-
- private void configurePort(DeviceId d, PortNumber p) {
- boolean alreadyAuthenticated =
- oldState(d, p) == BlockState.AUTHENTICATED;
-
- if (alreadyAuthenticated) {
- clearBlockingFlow(d, p);
- markAsAuthenticated(d, p);
- } else {
- installBlockingFlow(d, p);
- markAsBlocked(d, p);
- }
- log.info("Configuring port {}/{} as {}", d, p,
- alreadyAuthenticated ? "AUTHENTICATED" : "BLOCKED");
- }
-
- private boolean notInMap(DeviceId deviceId, PortNumber portNumber) {
- Map<PortNumber, BlockState> m = blockedPorts.get(deviceId);
- return m == null || m.get(portNumber) == null;
- }
-
- private void logPortsNoLongerBlocked() {
- for (Map.Entry<DeviceId, Map<PortNumber, BlockState>> entry :
- oldMap.entrySet()) {
- DeviceId d = entry.getKey();
- Map<PortNumber, BlockState> portMap = entry.getValue();
-
- for (PortNumber p : portMap.keySet()) {
- if (notInMap(d, p)) {
- clearBlockingFlow(d, p);
- log.info("De-configuring port {}/{} (UNCHECKED)", d, p);
- }
- }
- }
- }
-
-
- /**
- * Reconfigures the port tracker using the supplied configuration.
- *
- * @param cfg the new configuration
- */
- void configurePortBlocking(BlockedPortsConfig cfg) {
- // remember the old map; prepare a new map
- oldMap = blockedPorts;
- blockedPorts = new HashMap<>();
-
- // for each configured device, add configured ports to map
- for (String devId : cfg.deviceIds()) {
- cfg.portIterator(devId)
- .forEachRemaining(p -> configurePort(deviceId(devId),
- portNumber(p)));
- }
-
- // have we de-configured any ports?
- logPortsNoLongerBlocked();
-
- // allow old map to be garbage collected
- oldMap = null;
- }
-
- private List<PortAuthState> reportPortsAuthState() {
- List<PortAuthState> result = new ArrayList<>();
-
- for (Map.Entry<DeviceId, Map<PortNumber, BlockState>> entry :
- blockedPorts.entrySet()) {
- DeviceId d = entry.getKey();
- Map<PortNumber, BlockState> portMap = entry.getValue();
-
- for (PortNumber p : portMap.keySet()) {
- result.add(new PortAuthState(d, p, portMap.get(p)));
- }
- }
- Collections.sort(result);
- return result;
- }
-
- /**
- * Installs a "blocking" flow for device/port specified.
- *
- * @param d device id
- * @param p port number
- */
- void installBlockingFlow(DeviceId d, PortNumber p) {
- log.debug("Installing Blocking Flow at {}/{}", d, p);
- // TODO: invoke SegmentRoutingService.block(...) appropriately
- log.info("TODO >> Installing Blocking Flow at {}/{}", d, p);
- }
-
- /**
- * Removes the "blocking" flow from device/port specified.
- *
- * @param d device id
- * @param p port number
- */
- void clearBlockingFlow(DeviceId d, PortNumber p) {
- log.debug("Clearing Blocking Flow from {}/{}", d, p);
- // TODO: invoke SegmentRoutingService.block(...) appropriately
- log.info("TODO >> Clearing Blocking Flow from {}/{}", d, p);
- }
-
-
- /**
- * Designates the state of a given port. One of:
- * <ul>
- * <li> UNCHECKED: not configured for blocking </li>
- * <li> BLOCKED: configured for blocking, and not yet authenticated </li>
- * <li> AUTHENTICATED: configured for blocking, but authenticated </li>
- * </ul>
- */
- public enum BlockState {
- UNCHECKED,
- BLOCKED,
- AUTHENTICATED
- }
-
- /**
- * A simple DTO binding of device identifier, port number, and block state.
- */
- public static final class PortAuthState implements Comparable<PortAuthState> {
- private final DeviceId d;
- private final PortNumber p;
- private final BlockState s;
-
- private PortAuthState(DeviceId d, PortNumber p, BlockState s) {
- this.d = d;
- this.p = p;
- this.s = s;
- }
-
- @Override
- public String toString() {
- return String.valueOf(d) + "/" + p + " -- " + s;
- }
-
- @Override
- public int compareTo(PortAuthState o) {
- // NOTE: only compare against "deviceid/port"
- int result = Comparators.ELEMENT_ID_COMPARATOR.compare(d, o.d);
- return (result != 0) ? result : Long.signum(p.toLong() - o.p.toLong());
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final PortAuthTracker.PortAuthState that = (PortAuthTracker.PortAuthState) obj;
-
- return Comparators.ELEMENT_ID_COMPARATOR.compare(this.d, that.d) == 0 &&
- p.toLong() == that.p.toLong();
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(this.d, this.p);
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortFilterInfo.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortFilterInfo.java
deleted file mode 100644
index 75c12d6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/PortFilterInfo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import com.google.common.base.MoreObjects;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Utility class used to temporarily store information about the ports on a
- * device processed for filtering objectives.
- */
-public final class PortFilterInfo {
- int disabledPorts = 0, errorPorts = 0, filteredPorts = 0;
-
- public PortFilterInfo(int disabledPorts, int errorPorts,
- int filteredPorts) {
- this.disabledPorts = disabledPorts;
- this.filteredPorts = filteredPorts;
- this.errorPorts = errorPorts;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(disabledPorts, filteredPorts, errorPorts);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if ((obj == null) || (!(obj instanceof PortFilterInfo))) {
- return false;
- }
- PortFilterInfo other = (PortFilterInfo) obj;
- return ((disabledPorts == other.disabledPorts) &&
- (filteredPorts == other.filteredPorts) &&
- (errorPorts == other.errorPorts));
- }
-
- @Override
- public String toString() {
- MoreObjects.ToStringHelper helper = toStringHelper(this)
- .add("disabledPorts", disabledPorts)
- .add("errorPorts", errorPorts)
- .add("filteredPorts", filteredPorts);
- return helper.toString();
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
deleted file mode 100644
index d9372fe..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Sets;
-
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteEvent;
-import org.onosproject.net.DeviceId;
-import org.onosproject.routeservice.RouteInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Handles RouteEvent and manages routing entries.
- */
-public class RouteHandler {
- private static final Logger log = LoggerFactory.getLogger(RouteHandler.class);
- private final SegmentRoutingManager srManager;
-
- RouteHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- }
-
- protected void init(DeviceId deviceId) {
- srManager.routeService.getRouteTables().stream()
- .map(srManager.routeService::getRoutes)
- .flatMap(Collection::stream)
- .map(RouteInfo::allRoutes)
- .filter(allRoutes -> allRoutes.stream().anyMatch(resolvedRoute ->
- srManager.nextHopLocations(resolvedRoute).stream()
- .anyMatch(cp -> deviceId.equals(cp.deviceId()))))
- .forEach(rr -> processRouteAddedInternal(rr, true));
- }
-
- void processRouteAdded(RouteEvent event) {
- processRouteAddedInternal(event.alternatives(), false);
- }
-
- /**
- * Internal logic that handles route addition.
- *
- * @param routes collection of routes to be processed
- * @param populateRouteOnly true if we only want to populateRoute but not populateSubnet.
- * Set it to true when initializing a device coming up.
- * populateSubnet will be done when link comes up later so it is redundant.
- * populateRoute still needs to be done for statically configured next hop hosts.
- */
- private void processRouteAddedInternal(Collection<ResolvedRoute> routes, boolean populateRouteOnly) {
- if (!isReady()) {
- log.info("System is not ready. Skip adding route for {}", routes);
- return;
- }
-
- log.info("processRouteAddedInternal. routes={}", routes);
-
- if (routes.size() > 2) {
- log.info("Route {} has more than two next hops. Do not process route change", routes);
- return;
- }
-
- ResolvedRoute rr = routes.stream().findFirst().orElse(null);
- if (rr == null) {
- log.warn("No resolved route found. Abort processRouteAddedInternal");
- }
-
- Set<ConnectPoint> allLocations = Sets.newHashSet();
- Set<IpPrefix> allPrefixes = Sets.newHashSet();
- routes.forEach(route -> {
- allLocations.addAll(srManager.nextHopLocations(route));
- allPrefixes.add(route.prefix());
- });
- log.debug("RouteAdded. populateSubnet {}, {}", allLocations, allPrefixes);
- srManager.defaultRoutingHandler.populateSubnet(allLocations, allPrefixes);
-
-
- routes.forEach(route -> {
- IpPrefix prefix = route.prefix();
- MacAddress nextHopMac = route.nextHopMac();
- VlanId nextHopVlan = route.nextHopVlan();
- Set<ConnectPoint> locations = srManager.nextHopLocations(route);
-
- locations.forEach(location -> {
- log.debug("RouteAdded. addSubnet {}, {}", location, prefix);
- srManager.deviceConfiguration.addSubnet(location, prefix);
- log.debug("RouteAdded populateRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
- srManager.defaultRoutingHandler.populateRoute(location.deviceId(), prefix,
- nextHopMac, nextHopVlan, location.port(), false);
- });
- });
- }
-
- void processRouteUpdated(RouteEvent event) {
- processRouteUpdatedInternal(Sets.newHashSet(event.alternatives()),
- Sets.newHashSet(event.prevAlternatives()));
- }
-
- void processAlternativeRoutesChanged(RouteEvent event) {
- processRouteUpdatedInternal(Sets.newHashSet(event.alternatives()),
- Sets.newHashSet(event.prevAlternatives()));
- }
-
- private void processRouteUpdatedInternal(Set<ResolvedRoute> routes, Set<ResolvedRoute> oldRoutes) {
- if (!isReady()) {
- log.info("System is not ready. Skip updating route for {} -> {}", oldRoutes, routes);
- return;
- }
-
- log.info("processRouteUpdatedInternal. routes={}, oldRoutes={}", routes, oldRoutes);
-
- if (routes.size() > 2) {
- log.info("Route {} has more than two next hops. Do not process route change", routes);
- return;
- }
-
- Set<ConnectPoint> allLocations = Sets.newHashSet();
- Set<IpPrefix> allPrefixes = Sets.newHashSet();
- routes.forEach(route -> {
- allLocations.addAll(srManager.nextHopLocations(route));
- allPrefixes.add(route.prefix());
- });
-
- // Just come back from an invalid next hop count
- // Revoke subnet from all locations and reset oldRoutes such that system will be reprogrammed from scratch
- if (oldRoutes.size() > 2) {
- log.info("Revoke subnet {} and reset oldRoutes");
- srManager.defaultRoutingHandler.revokeSubnet(allPrefixes);
- oldRoutes = Sets.newHashSet();
- }
-
- log.debug("RouteUpdated. populateSubnet {}, {}", allLocations, allPrefixes);
- srManager.defaultRoutingHandler.populateSubnet(allLocations, allPrefixes);
-
- Set<ResolvedRoute> toBeRemoved = Sets.difference(oldRoutes, routes).immutableCopy();
- Set<ResolvedRoute> toBeAdded = Sets.difference(routes, oldRoutes).immutableCopy();
-
- toBeRemoved.forEach(route -> {
- srManager.nextHopLocations(route).forEach(oldLocation -> {
- if (toBeAdded.stream().map(srManager::nextHopLocations)
- .flatMap(Set::stream).map(ConnectPoint::deviceId)
- .noneMatch(deviceId -> deviceId.equals(oldLocation.deviceId()))) {
- IpPrefix prefix = route.prefix();
- log.debug("RouteUpdated. removeSubnet {}, {}", oldLocation, prefix);
- srManager.deviceConfiguration.removeSubnet(oldLocation, prefix);
- // We don't remove the flow on the old location in occasion of two next hops becoming one
- // since the populateSubnet will point the old location to the new location via spine.
- }
- });
- });
-
- toBeAdded.forEach(route -> {
- IpPrefix prefix = route.prefix();
- MacAddress nextHopMac = route.nextHopMac();
- VlanId nextHopVlan = route.nextHopVlan();
- Set<ConnectPoint> locations = srManager.nextHopLocations(route);
-
- locations.forEach(location -> {
- log.debug("RouteUpdated. addSubnet {}, {}", location, prefix);
- srManager.deviceConfiguration.addSubnet(location, prefix);
- log.debug("RouteUpdated. populateRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
- srManager.defaultRoutingHandler.populateRoute(location.deviceId(), prefix,
- nextHopMac, nextHopVlan, location.port(), false);
- });
- });
- }
-
- void processRouteRemoved(RouteEvent event) {
- processRouteRemovedInternal(event.alternatives());
- }
-
- private void processRouteRemovedInternal(Collection<ResolvedRoute> routes) {
- if (!isReady()) {
- log.info("System is not ready. Skip removing route for {}", routes);
- return;
- }
-
- log.info("processRouteRemovedInternal. routes={}", routes);
-
- Set<IpPrefix> allPrefixes = Sets.newHashSet();
- routes.forEach(route -> {
- allPrefixes.add(route.prefix());
- });
- log.debug("RouteRemoved. revokeSubnet {}", allPrefixes);
- srManager.defaultRoutingHandler.revokeSubnet(allPrefixes);
-
- routes.forEach(route -> {
- IpPrefix prefix = route.prefix();
- MacAddress nextHopMac = route.nextHopMac();
- VlanId nextHopVlan = route.nextHopVlan();
- Set<ConnectPoint> locations = srManager.nextHopLocations(route);
-
- locations.forEach(location -> {
- log.debug("RouteRemoved. removeSubnet {}, {}", location, prefix);
- srManager.deviceConfiguration.removeSubnet(location, prefix);
- // We don't need to call revokeRoute again since revokeSubnet will remove the prefix
- // from all devices, including the ones that next hop attaches to.
-
- // Also remove redirection flows on the pair device if exists.
- Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
- Optional<PortNumber> pairLocalPort = srManager.getPairLocalPort(location.deviceId());
- if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
- // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
- // when the host is untagged
- VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(nextHopVlan);
-
- log.debug("RouteRemoved. revokeRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
- srManager.defaultRoutingHandler.revokeRoute(pairDeviceId.get(), prefix,
- nextHopMac, vlanId, pairLocalPort.get(), false);
- }
- });
- });
- }
-
- void processHostMovedEvent(HostEvent event) {
- log.info("processHostMovedEvent {}", event);
- MacAddress hostMac = event.subject().mac();
- VlanId hostVlanId = event.subject().vlan();
-
- Set<HostLocation> prevLocations = event.prevSubject().locations();
- Set<HostLocation> newLocations = event.subject().locations();
- Set<ConnectPoint> connectPoints = newLocations.stream()
- .map(l -> (ConnectPoint) l).collect(Collectors.toSet());
- List<Set<IpPrefix>> batchedSubnets =
- srManager.deviceConfiguration.getBatchedSubnets(event.subject().id());
- Set<DeviceId> newDeviceIds = newLocations.stream().map(HostLocation::deviceId)
- .collect(Collectors.toSet());
-
- // Set of deviceIDs of the previous locations where the host was connected
- // Used to determine if host moved to different connect points
- // on same device or moved to a different device altogether
- Set<DeviceId> oldDeviceIds = prevLocations.stream().map(HostLocation::deviceId)
- .collect(Collectors.toSet());
-
- // L3 Ucast bucket needs to be updated only once per host
- // and only when the no. of routes with the host as next-hop is not zero
- if (!batchedSubnets.isEmpty()) {
- // For each new location, if NextObj exists for the host, update with new location ..
- Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
- int nextId = srManager.getMacVlanNextObjectiveId(newLocation.deviceId(),
- hostMac, hostVlanId, null, false);
- VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(newLocation)).orElse(hostVlanId);
-
- if (nextId != -1) {
- //Update the nextId group bucket
- log.debug("HostMoved. NextId exists, update L3 Ucast Group Bucket {}, {}, {} --> {}",
- newLocation, hostMac, vlanId, nextId);
- srManager.updateMacVlanTreatment(newLocation.deviceId(), hostMac, vlanId,
- newLocation.port(), nextId);
- } else {
- log.debug("HostMoved. NextId does not exist for this location {}, host {}/{}",
- newLocation, hostMac, vlanId);
- }
- });
- }
-
- batchedSubnets.forEach(subnets -> {
- log.debug("HostMoved. populateSubnet {}, {}", newLocations, subnets);
- srManager.defaultRoutingHandler.populateSubnet(connectPoints, subnets);
-
- subnets.forEach(prefix -> {
- // For each old location
- Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
-
- // Remove flows for unchanged IPs only when the host moves from a switch to another.
- // Otherwise, do not remove and let the adding part update the old flow
- if (newDeviceIds.contains(prevLocation.deviceId())) {
- return;
- }
-
- log.debug("HostMoved. removeSubnet {}, {}", prevLocation, prefix);
- srManager.deviceConfiguration.removeSubnet(prevLocation, prefix);
-
- // Do not remove flow from a device if the route is still reachable via its pair device.
- // populateSubnet will update the flow to point to its pair device via spine.
- DeviceId pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId()).orElse(null);
- if (newLocations.stream().anyMatch(n -> n.deviceId().equals(pairDeviceId))) {
- return;
- }
-
- log.debug("HostMoved. revokeRoute {}, {}, {}, {}", prevLocation, prefix, hostMac, hostVlanId);
- srManager.defaultRoutingHandler.revokeRoute(prevLocation.deviceId(), prefix,
- hostMac, hostVlanId, prevLocation.port(), false);
- });
-
- // For each new location, add all new IPs.
- Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
- log.debug("HostMoved. addSubnet {}, {}", newLocation, prefix);
- srManager.deviceConfiguration.addSubnet(newLocation, prefix);
-
- //its a new connect point, not a move from an existing device, populateRoute
- if (!oldDeviceIds.contains(newLocation.deviceId())) {
- log.debug("HostMoved. populateRoute {}, {}, {}, {}", newLocation, prefix, hostMac, hostVlanId);
- srManager.defaultRoutingHandler.populateRoute(newLocation.deviceId(), prefix,
- hostMac, hostVlanId, newLocation.port(), false);
- }
- });
- });
- });
-
- }
-
- private boolean isReady() {
- return Objects.nonNull(srManager.deviceConfiguration) &&
- Objects.nonNull(srManager.defaultRoutingHandler);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteSimplifierUtils.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteSimplifierUtils.java
deleted file mode 100644
index 401007c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RouteSimplifierUtils.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.ImmutableList;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-
-/**
- * Utility class for route simplification.
- */
-final class RouteSimplifierUtils {
-
- /*
- * When route with source type listed in leafExclusionRouteTypes,
- * it will programme only on the leaf pair the nexthop attaches to. Other leaves will be ignored.
- */
- private static final ImmutableList<Route.Source> LEAF_EXCLUSION_ROUTE_TYPES =
- ImmutableList.of(Route.Source.DHCP, Route.Source.RIP, Route.Source.DHCPLQ);
-
- private SegmentRoutingManager srManager;
-
- RouteSimplifierUtils(SegmentRoutingManager srManager) {
-
- this.srManager = srManager;
- }
-
- /**
- * Checking whether the leafExclusionRouteTypes contains the given source type.
- *
- * @param s source type
- * @return boolean if it containsd the source type.
- *
- */
- public boolean hasLeafExclusionEnabledForType(Route.Source s) {
- return LEAF_EXCLUSION_ROUTE_TYPES.contains(s);
- }
-
- /**
- * When route with any source of given prefix is listed in leafExclusionRouteTypes,
- * it will programme only on the leaf pair the nexthop attaches to. Other leaves will be ignored.
- *
- * @param ipPrefix ip prefix of the route.
- * @return boolean if contains the prefix of the mentioned source type.
- */
- public boolean hasLeafExclusionEnabledForPrefix(IpPrefix ipPrefix) {
- for (ResolvedRoute route : srManager.routeService.getAllResolvedRoutes(ipPrefix)) {
- if (hasLeafExclusionEnabledForType(route.route().source())) {
- return true;
- }
- }
- 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
deleted file mode 100644
index a6f6e32..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ /dev/null
@@ -1,1942 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.onlab.packet.EthType;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.Host;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.packet.PacketPriority;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-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.onosproject.net.flowobjective.ForwardingObjective.Flag;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onlab.packet.Ethernet.TYPE_ARP;
-import static org.onlab.packet.Ethernet.TYPE_IPV6;
-import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
-import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
-import static org.onlab.packet.ICMP6.ROUTER_ADVERTISEMENT;
-import static org.onlab.packet.ICMP6.ROUTER_SOLICITATION;
-import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
-import static org.onosproject.segmentrouting.SegmentRoutingService.DEFAULT_PRIORITY;
-
-/**
- * Populator of segment routing flow rules.
- */
-public class RoutingRulePopulator {
- private static final Logger log = LoggerFactory.getLogger(RoutingRulePopulator.class);
-
- private static final int ARP_NDP_PRIORITY = 30000;
-
- private AtomicLong rulePopulationCounter;
- private SegmentRoutingManager srManager;
- private DeviceConfiguration config;
- private RouteSimplifierUtils routeSimplifierUtils;
-
- // used for signalling the driver to remove vlan table and tmac entry also
- private static final long CLEANUP_DOUBLE_TAGGED_HOST_ENTRIES = 1;
- private static final long DOUBLE_TAGGED_METADATA_MASK = 0xffffffffffffffffL;
-
- /**
- * Creates a RoutingRulePopulator object.
- *
- * @param srManager segment routing manager reference
- */
- RoutingRulePopulator(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- this.config = checkNotNull(srManager.deviceConfiguration);
- this.rulePopulationCounter = new AtomicLong(0);
- this.routeSimplifierUtils = new RouteSimplifierUtils(srManager);
- }
-
- /**
- * Resets the population counter.
- */
- void resetCounter() {
- rulePopulationCounter.set(0);
- }
-
- /**
- * Returns the number of rules populated.
- *
- * @return number of rules
- */
- long getCounter() {
- return rulePopulationCounter.get();
- }
-
- /**
- * Populate a bridging rule on given deviceId that matches given mac, given vlan and
- * output to given port.
- *
- * @param deviceId device ID
- * @param port port
- * @param mac mac address
- * @param vlanId VLAN ID
- * @return future that carries the flow objective if succeeded, null if otherwise
- */
- CompletableFuture<Objective> populateBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
- ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, false);
- if (fob == null) {
- log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
- return CompletableFuture.completedFuture(null);
- }
-
- CompletableFuture<Objective> future = new CompletableFuture<>();
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> {
- log.debug("Brigding rule for {}/{} populated", mac, vlanId);
- future.complete(objective);
- },
- (objective, error) -> {
- log.warn("Failed to populate bridging rule for {}/{}: {}", mac, vlanId, error);
- future.complete(null);
- });
- srManager.flowObjectiveService.forward(deviceId, fob.add(context));
- return future;
- }
-
- /**
- * Revoke a bridging rule on given deviceId that matches given mac, given vlan and
- * output to given port.
- *
- * @param deviceId device ID
- * @param port port
- * @param mac mac address
- * @param vlanId VLAN ID
- * @return future that carries the flow objective if succeeded, null if otherwise
- */
- CompletableFuture<Objective> revokeBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
- ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, true);
- if (fob == null) {
- log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
- return CompletableFuture.completedFuture(null);
- }
-
- CompletableFuture<Objective> future = new CompletableFuture<>();
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> {
- log.debug("Brigding rule for {}/{} revoked", mac, vlanId);
- future.complete(objective);
- },
- (objective, error) -> {
- log.warn("Failed to revoke bridging rule for {}/{}: {}", mac, vlanId, error);
- future.complete(null);
- });
- srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
- return future;
- }
-
- /**
- * Generates a forwarding objective builder for bridging rules.
- * <p>
- * The forwarding objective bridges packets destined to a given MAC to
- * given port on given device.
- *
- * @param deviceId Device that host attaches to
- * @param mac MAC address of the host
- * @param hostVlanId VLAN ID of the host
- * @param outport Port that host attaches to
- * @param revoke true if forwarding objective is meant to revoke forwarding rule
- * @return Forwarding objective builder
- */
- private ForwardingObjective.Builder bridgingFwdObjBuilder(
- DeviceId deviceId, MacAddress mac, VlanId hostVlanId, PortNumber outport, boolean revoke) {
- ConnectPoint connectPoint = new ConnectPoint(deviceId, outport);
- VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
- Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
- VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
- // Create host selector
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- sbuilder.matchEthDst(mac);
-
- // Create host treatment
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.immediate().setOutput(outport);
-
- // Create host meta
- TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-
- // Adjust the selector, treatment and meta according to VLAN configuration
- if (taggedVlans.contains(hostVlanId)) {
- sbuilder.matchVlanId(hostVlanId);
- mbuilder.matchVlanId(hostVlanId);
- } else if (hostVlanId.equals(VlanId.NONE)) {
- if (untaggedVlan != null) {
- sbuilder.matchVlanId(untaggedVlan);
- mbuilder.matchVlanId(untaggedVlan);
- tbuilder.immediate().popVlan();
- } else if (nativeVlan != null) {
- sbuilder.matchVlanId(nativeVlan);
- mbuilder.matchVlanId(nativeVlan);
- tbuilder.immediate().popVlan();
- } else {
- log.warn("Untagged host {}/{} is not allowed on {} without untagged or native" +
- "vlan config", mac, hostVlanId, connectPoint);
- return null;
- }
- } else {
- log.warn("Tagged host {}/{} is not allowed on {} without VLAN listed in tagged vlan",
- mac, hostVlanId, connectPoint);
- return null;
- }
-
- // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
- // 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, outport,
- tbuilder.build(), mbuilder.build(), !revoke);
- if (portNextObjId == -1) {
- // Warning log will come from getPortNextObjective method
- return null;
- }
-
- return DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .withSelector(sbuilder.build())
- .nextStep(portNextObjId)
- .withPriority(100)
- .fromApp(srManager.appId)
- .makePermanent();
- }
-
- /**
- * Populate or revoke a bridging rule on given deviceId that matches given vlanId,
- * and hostMAC connected to given port, and output to given port only when
- * vlan information is valid.
- *
- * @param deviceId device ID that host attaches to
- * @param portNum port number that host attaches to
- * @param hostMac mac address of the host connected to the switch port
- * @param vlanId Vlan ID configured on the switch port
- * @param popVlan true to pop Vlan tag at TrafficTreatment, false otherwise
- * @param install true to populate the objective, false to revoke
- */
- // TODO Refactor. There are a lot of duplications between this method, populateBridging,
- // revokeBridging and bridgingFwdObjBuilder.
- void updateBridging(DeviceId deviceId, PortNumber portNum, MacAddress hostMac,
- VlanId vlanId, boolean popVlan, boolean install) {
- // Create host selector
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- sbuilder.matchEthDst(hostMac);
-
- // Create host meta
- TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-
- sbuilder.matchVlanId(vlanId);
- mbuilder.matchVlanId(vlanId);
-
- // Create host treatment
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.immediate().setOutput(portNum);
-
- if (popVlan) {
- tbuilder.immediate().popVlan();
- }
-
- int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNum,
- tbuilder.build(), mbuilder.build(), install);
- if (portNextObjId != -1) {
- ForwardingObjective.Builder fob = DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .withSelector(sbuilder.build())
- .nextStep(portNextObjId)
- .withPriority(100)
- .fromApp(srManager.appId)
- .makePermanent();
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Brigding rule for {}/{} {}", hostMac, vlanId,
- install ? "populated" : "revoked"),
- (objective, error) -> log.warn("Failed to {} bridging rule for {}/{}: {}",
- install ? "populate" : "revoke", hostMac, vlanId, error));
- srManager.flowObjectiveService.forward(deviceId, install ? fob.add(context) : fob.remove(context));
- } else {
- log.warn("Failed to retrieve next objective for {}/{}", hostMac, vlanId);
- }
- }
-
- /**
- * Populates IP rules for a route that has direct connection to the switch.
- * This method should not be invoked directly without going through DefaultRoutingHandler.
- *
- * @param deviceId device ID of the device that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param hostVlanId Vlan ID of the nexthop
- * @param outPort port where the next hop attaches to
- * @param directHost host is of type direct or indirect
- * @return future that carries the flow objective if succeeded, null if otherwise
- */
- CompletableFuture<Objective> populateRoute(DeviceId deviceId, IpPrefix prefix,
- MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
- log.debug("Populate direct routing entry for route {} at {}:{}",
- prefix, deviceId, outPort);
- ForwardingObjective.Builder fwdBuilder;
- try {
- fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac,
- hostVlanId, outPort, null, null, directHost, false);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting direct populateRoute");
- return CompletableFuture.completedFuture(null);
- }
- if (fwdBuilder == null) {
- log.warn("Aborting host routing table entry due "
- + "to error for dev:{} route:{}", deviceId, prefix);
- return CompletableFuture.completedFuture(null);
- }
-
- int nextId = fwdBuilder.add().nextId();
- CompletableFuture<Objective> future = new CompletableFuture<>();
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> {
- log.debug("Direct routing rule for route {} populated. nextId={}", prefix, nextId);
- future.complete(objective);
- },
- (objective, error) -> {
- log.warn("Failed to populate direct routing rule for route {}: {}", prefix, error);
- future.complete(null);
- });
- srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
- rulePopulationCounter.incrementAndGet();
- return future;
- }
-
- /**
- * Removes IP rules for a route when the next hop is gone.
- * This method should not be invoked directly without going through DefaultRoutingHandler.
- *
- * @param deviceId device ID of the device that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param hostVlanId Vlan ID of the nexthop
- * @param outPort port that next hop attaches to
- * @param directHost host is of type direct or indirect
- * @return future that carries the flow objective if succeeded, null if otherwise
- */
- CompletableFuture<Objective> revokeRoute(DeviceId deviceId, IpPrefix prefix,
- MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
- log.debug("Revoke IP table entry for route {} at {}:{}",
- prefix, deviceId, outPort);
- ForwardingObjective.Builder fwdBuilder;
- try {
- fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac,
- hostVlanId, outPort, null, null, directHost, true);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting revokeIpRuleForHost.");
- return CompletableFuture.completedFuture(null);
- }
- if (fwdBuilder == null) {
- log.warn("Aborting host routing table entries due "
- + "to error for dev:{} route:{}", deviceId, prefix);
- return CompletableFuture.completedFuture(null);
- }
-
- CompletableFuture<Objective> future = new CompletableFuture<>();
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> {
- log.debug("IP rule for route {} revoked", prefix);
- future.complete(objective);
- },
- (objective, error) -> {
- log.warn("Failed to revoke IP rule for route {}: {}", prefix, error);
- future.complete(null);
- });
- srManager.flowObjectiveService.forward(deviceId, fwdBuilder.remove(context));
- return future;
- }
-
- /**
- * Returns a forwarding objective builder for routing rules.
- * <p>
- * The forwarding objective routes packets destined to a given prefix to
- * given port on given device with given destination MAC.
- *
- * @param deviceId device ID
- * @param prefix prefix that need to be routed
- * @param hostMac MAC address of the nexthop
- * @param hostVlanId Vlan ID of the nexthop
- * @param outPort port where the nexthop attaches to
- * @param revoke true if forwarding objective is meant to revoke forwarding rule
- * @param directHost host is direct or indirect
- * @return forwarding objective builder
- * @throws DeviceConfigNotFoundException if given device is not configured
- */
-
- private ForwardingObjective.Builder routingFwdObjBuilder(
- DeviceId deviceId, IpPrefix prefix,
- MacAddress hostMac, VlanId hostVlanId, PortNumber outPort,
- VlanId innerVlan, EthType outerTpid,
- boolean directHost, boolean revoke)
- throws DeviceConfigNotFoundException {
- int nextObjId;
- if (directHost) {
- // 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
- ImmutablePair<TrafficTreatment, TrafficSelector> treatmentAndMeta =
- getTreatmentAndMeta(deviceId, hostMac, hostVlanId, outPort, innerVlan, outerTpid);
- if (treatmentAndMeta == null) {
- // Warning log will come from getTreatmentAndMeta method
- return null;
- }
- nextObjId = srManager.getPortNextObjectiveId(deviceId, outPort,
- treatmentAndMeta.getLeft(), treatmentAndMeta.getRight(), !revoke);
- } else {
- // 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
- nextObjId = srManager.getMacVlanNextObjectiveId(deviceId, hostMac, hostVlanId,
- outPort, !revoke);
- }
- if (nextObjId == -1) {
- // Warning log will come from getMacVlanNextObjective method
- return null;
- }
-
- return DefaultForwardingObjective.builder()
- .withSelector(buildIpSelectorFromIpPrefix(prefix).build())
- .nextStep(nextObjId)
- .fromApp(srManager.appId).makePermanent()
- .withPriority(getPriorityFromPrefix(prefix))
- .withFlag(ForwardingObjective.Flag.SPECIFIC);
- }
-
- private ImmutablePair<TrafficTreatment, TrafficSelector> getTreatmentAndMeta(
- DeviceId deviceId, MacAddress hostMac, VlanId hostVlanId, PortNumber outPort,
- VlanId innerVlan, EthType outerTpid)
- throws DeviceConfigNotFoundException {
- MacAddress routerMac;
- routerMac = config.getDeviceMac(deviceId);
-
- ConnectPoint connectPoint = new ConnectPoint(deviceId, outPort);
- VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
- Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
- VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
- // Create route treatment
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.deferred()
- .setEthDst(hostMac)
- .setEthSrc(routerMac)
- .setOutput(outPort);
-
- // Create route meta
- TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
-
- // Adjust treatment and meta according to VLAN configuration
- if (taggedVlans.contains(hostVlanId)) {
- tbuilder.setVlanId(hostVlanId);
- } else if (hostVlanId.equals(VlanId.NONE)) {
- if (untaggedVlan != null) {
- mbuilder.matchVlanId(untaggedVlan);
- } else if (nativeVlan != null) {
- mbuilder.matchVlanId(nativeVlan);
- } else {
- log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan",
- hostMac, hostVlanId, connectPoint);
- return null;
- }
- } else {
- // Double tagged hosts
- if (innerVlan == null || outerTpid == null) {
- log.warn("Failed to construct NextObj for double tagged hosts {}/{}. {} {}",
- hostMac, hostVlanId,
- (innerVlan == null) ? "innerVlan = null." : "",
- (outerTpid == null) ? "outerTpid = null." : "");
- return null;
- }
- tbuilder.setVlanId(innerVlan);
- tbuilder.pushVlan(outerTpid);
- tbuilder.setVlanId(hostVlanId);
- mbuilder.matchVlanId(VlanId.ANY);
- }
-
- return ImmutablePair.of(tbuilder.build(), mbuilder.build());
- }
-
- /**
- * Populates IP flow rules for all the given prefixes reachable from the
- * destination switch(es).
- *
- * @param targetSw switch where rules are to be programmed
- * @param subnets subnets/prefixes being added
- * @param destSw1 destination switch where the prefixes are reachable
- * @param destSw2 paired destination switch if one exists for the subnets/prefixes.
- * Should be null if there is no paired destination switch (by config)
- * or if the given prefixes are reachable only via destSw1
- * @param nextHops a map containing a set of next-hops for each destination switch.
- * If destSw2 is not null, then this map must contain an
- * entry for destSw2 with its next-hops from the targetSw
- * (although the next-hop set may be empty in certain scenarios).
- * If destSw2 is null, there should not be an entry in this
- * map for destSw2.
- * @return true if all rules are set successfully, false otherwise
- */
- boolean populateIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets,
- DeviceId destSw1, DeviceId destSw2, Map<DeviceId, Set<DeviceId>> nextHops) {
- // Get pair device of the target switch
- Optional<DeviceId> pairDev = srManager.getPairDeviceId(targetSw);
- // Route simplification will be off in case of the nexthop location at target switch is down
- // (routing through spine case)
- boolean routeSimplOff = pairDev.isPresent() && pairDev.get().equals(destSw1) && destSw2 == null;
- // Iterates over the routes. Checking:
- // If route simplification is enabled
- // If the target device is another leaf in the network
- if (srManager.routeSimplification && !routeSimplOff) {
- Set<IpPrefix> subnetsToBePopulated = Sets.newHashSet();
- for (IpPrefix subnet : subnets) {
- // Skip route programming on the target device
- // If route simplification applies
- if (routeSimplifierUtils.hasLeafExclusionEnabledForPrefix(subnet)) {
- // XXX route simplification assumes that source of the traffic
- // towards the nexthops are co-located with the nexthops. In different
- // scenarios will not work properly.
- continue;
- }
- // populate the route in the remaning scenarios
- subnetsToBePopulated.add(subnet);
- }
- subnets = subnetsToBePopulated;
- }
- // populate the remaining routes in the target switch
- return populateIpRulesForRouter(targetSw, subnets, destSw1, destSw2, nextHops);
- }
-
- /**
- * Revokes IP flow rules for the subnets from given device.
- *
- * @param targetSw target switch from which the subnets need to be removed
- * @param subnets subnet being removed
- * @return true if all rules are removed successfully, false otherwise
- */
- boolean revokeIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets) {
- for (IpPrefix subnet : subnets) {
- if (!revokeIpRuleForRouter(targetSw, subnet)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Populates IP flow rules for a set of IP prefix in the target device.
- * The prefix are reachable via destination device(s).
- *
- * @param targetSw target device ID to set the rules
- * @param subnets the set of IP prefix
- * @param destSw1 destination switch where the prefixes are reachable
- * @param destSw2 paired destination switch if one exists for the subnets/prefixes.
- * Should be null if there is no paired destination switch (by config)
- * or if the given prefixes are reachable only via destSw1
- * @param nextHops map of destination switches and their next-hops.
- * Should only contain destination switches that are
- * actually meant to be routed to. If destSw2 is null, there
- * should not be an entry for destSw2 in this map.
- * @return true if all rules are set successfully, false otherwise
- */
- private boolean populateIpRulesForRouter(DeviceId targetSw,
- Set<IpPrefix> subnets,
- DeviceId destSw1, DeviceId destSw2,
- Map<DeviceId, Set<DeviceId>> nextHops) {
- // pre-compute the needed information
- int segmentIdIPv41, segmentIdIPv42 = -1;
- int segmentIdIPv61, segmentIdIPv62 = -1;
- TrafficTreatment treatment = null;
- DestinationSet dsIPv4, dsIPv6;
- TrafficSelector metaIpv4Selector, metaIpv6Selector = null;
- int nextIdIPv4, nextIdIPv6, nextId;
- TrafficSelector selector;
- // start with MPLS SIDs
- try {
- segmentIdIPv41 = config.getIPv4SegmentId(destSw1);
- segmentIdIPv61 = config.getIPv6SegmentId(destSw1);
- if (destSw2 != null) {
- segmentIdIPv42 = config.getIPv4SegmentId(destSw2);
- segmentIdIPv62 = config.getIPv6SegmentId(destSw2);
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting populateIpRuleForRouter.");
- return false;
- }
- // build the IPv4 and IPv6 destination set
- if (destSw2 == null) {
- // single dst - create destination set based on next-hop
- // If the next hop is the same as the final destination, then MPLS
- // label is not set.
- Set<DeviceId> nhd1 = nextHops.get(destSw1);
- if (nhd1.size() == 1 && nhd1.iterator().next().equals(destSw1)) {
- dsIPv4 = DestinationSet.createTypePushNone(destSw1);
- dsIPv6 = DestinationSet.createTypePushNone(destSw1);
- treatment = DefaultTrafficTreatment.builder()
- .immediate()
- .decNwTtl()
- .build();
- } else {
- dsIPv4 = DestinationSet.createTypePushBos(segmentIdIPv41, destSw1);
- dsIPv6 = DestinationSet.createTypePushBos(segmentIdIPv61, destSw1);
- }
- } else {
- // dst pair - IP rules for dst-pairs are always from other edge nodes
- // the destination set needs to have both destinations, even if there
- // are no next hops to one of them
- dsIPv4 = DestinationSet.createTypePushBos(segmentIdIPv41, destSw1, segmentIdIPv42, destSw2);
- dsIPv6 = DestinationSet.createTypePushBos(segmentIdIPv61, destSw1, segmentIdIPv62, destSw2);
- }
-
- // setup metadata to pass to nextObjective - indicate the vlan on egress
- // if needed by the switch pipeline. Since neighbor sets are always to
- // other neighboring routers, there is no subnet assigned on those ports.
- metaIpv4Selector = buildIpv4Selector()
- .matchVlanId(srManager.getDefaultInternalVlan())
- .build();
- metaIpv6Selector = buildIpv6Selector()
- .matchVlanId(srManager.getDefaultInternalVlan())
- .build();
- // get the group handler of the target switch
- DefaultGroupHandler grpHandler = srManager.getGroupHandler(targetSw);
- if (grpHandler == null) {
- log.warn("populateIPRuleForRouter: groupHandler for device {} "
- + "not found", targetSw);
- return false;
- }
- // get next id
- nextIdIPv4 = grpHandler.getNextObjectiveId(dsIPv4, nextHops, metaIpv4Selector, false);
- if (nextIdIPv4 <= 0) {
- log.warn("No next objective in {} for ds: {}", targetSw, dsIPv4);
- return false;
- }
- nextIdIPv6 = grpHandler.getNextObjectiveId(dsIPv6, nextHops, metaIpv6Selector, false);
- if (nextIdIPv6 <= 0) {
- log.warn("No next objective in {} for ds: {}", targetSw, dsIPv6);
- return false;
- }
- // build all the flow rules and send to the device
- for (IpPrefix subnet : subnets) {
- selector = buildIpSelectorFromIpPrefix(subnet).build();
- if (subnet.isIp4()) {
- nextId = nextIdIPv4;
- } else {
- nextId = nextIdIPv6;
- }
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder()
- .fromApp(srManager.appId)
- .makePermanent()
- .nextStep(nextId)
- .withSelector(selector)
- .withPriority(getPriorityFromPrefix(subnet))
- .withFlag(ForwardingObjective.Flag.SPECIFIC);
- if (treatment != null) {
- fwdBuilder.withTreatment(treatment);
- }
- log.debug("Installing {} forwarding objective for router IP/subnet {} "
- + "in switch {} with nextId: {}", subnet.isIp4() ? "IPv4" : "IPv6",
- subnet, targetSw, nextId);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("IP rule for router {} populated in dev:{}",
- subnet, targetSw),
- (objective, error) -> log.warn("Failed to populate IP rule for router {}: {} in dev:{}",
- subnet, error, targetSw));
- srManager.flowObjectiveService.forward(targetSw, fwdBuilder.add(context));
- }
- rulePopulationCounter.addAndGet(subnets.size());
- return true;
- }
-
- /**
- * Revokes IP flow rules for the router IP address from given device.
- *
- * @param targetSw target switch from which the ipPrefix need to be removed
- * @param ipPrefix the IP address of the destination router
- * @return true if all rules are removed successfully, false otherwise
- */
- private boolean revokeIpRuleForRouter(DeviceId targetSw, IpPrefix ipPrefix) {
- TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(ipPrefix);
- TrafficSelector selector = sbuilder.build();
- TrafficTreatment dummyTreatment = DefaultTrafficTreatment.builder().build();
-
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder()
- .fromApp(srManager.appId)
- .makePermanent()
- .withSelector(selector)
- .withTreatment(dummyTreatment)
- .withPriority(getPriorityFromPrefix(ipPrefix))
- .withFlag(ForwardingObjective.Flag.SPECIFIC);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("IP rule for router {} revoked from {}", ipPrefix, targetSw),
- (objective, error) -> log.warn("Failed to revoke IP rule for router {} from {}: {}",
- ipPrefix, targetSw, error));
- srManager.flowObjectiveService.forward(targetSw, fwdBuilder.remove(context));
-
- return true;
- }
-
- /**
- * Populates MPLS flow rules in the target device to point towards the
- * destination device.
- *
- * @param targetSwId target device ID of the switch to set the rules
- * @param destSwId destination switch device ID
- * @param nextHops next hops switch ID list
- * @param routerIp the router ip of the destination switch
- * @return true if all rules are set successfully, false otherwise
- */
- boolean populateMplsRule(DeviceId targetSwId, DeviceId destSwId,
- Set<DeviceId> nextHops, IpAddress routerIp) {
- int segmentId;
- try {
- if (routerIp.isIp4()) {
- segmentId = config.getIPv4SegmentId(destSwId);
- } else {
- segmentId = config.getIPv6SegmentId(destSwId);
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting populateMplsRule.");
- return false;
- }
-
- List<ForwardingObjective> fwdObjs = new ArrayList<>();
- Collection<ForwardingObjective> fwdObjsMpls;
- // Generates the transit rules used by the standard "routing".
- fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId,
- routerIp, true);
- if (fwdObjsMpls.isEmpty()) {
- return false;
- }
- fwdObjs.addAll(fwdObjsMpls);
-
- // Generates the transit rules used by the MPLS Pwaas.
- int pwSrLabel;
- try {
- pwSrLabel = config.getPWRoutingLabel(destSwId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Aborting populateMplsRule. No label for PseudoWire traffic.");
- return false;
- }
- fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, pwSrLabel,
- routerIp, false);
- if (fwdObjsMpls.isEmpty()) {
- return false;
- }
- fwdObjs.addAll(fwdObjsMpls);
-
- for (ForwardingObjective fwdObj : fwdObjs) {
- log.debug("Sending MPLS fwd obj {} for SID {}-> next {} in sw: {}",
- fwdObj.id(), segmentId, fwdObj.nextId(), targetSwId);
- srManager.flowObjectiveService.forward(targetSwId, fwdObj);
- rulePopulationCounter.incrementAndGet();
- }
-
- return true;
- }
-
- /**
- * Differentiates between popping and swapping labels when building an MPLS
- * forwarding objective.
- *
- * @param targetSwId the target sw
- * @param destSwId the destination sw
- * @param nextHops the set of next hops
- * @param segmentId the segmentId to match representing the destination
- * switch
- * @param routerIp the router ip representing the destination switch
- * @return a collection of fwdobjective
- */
- private Collection<ForwardingObjective> handleMpls(
- DeviceId targetSwId,
- DeviceId destSwId,
- Set<DeviceId> nextHops,
- int segmentId,
- IpAddress routerIp,
- boolean isMplsBos) {
-
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- List<ForwardingObjective.Builder> fwdObjBuilders = Lists.newArrayList();
- // For the transport of Pwaas we can use two or three MPLS label
- sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
- sbuilder.matchMplsLabel(MplsLabel.mplsLabel(segmentId));
- sbuilder.matchMplsBos(isMplsBos);
- TrafficSelector selector = sbuilder.build();
-
- // setup metadata to pass to nextObjective - indicate the vlan on egress
- // if needed by the switch pipeline. Since mpls next-hops are always to
- // other neighboring routers, there is no subnet assigned on those ports.
- TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
- metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
-
- if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
- // If the next hop is the destination router for the segment, do pop
- log.debug("populateMplsRule: Installing MPLS forwarding objective for "
- + "label {} in switch {} with pop to next-hops {}",
- segmentId, targetSwId, nextHops);
- ForwardingObjective.Builder fwdObjNoBosBuilder =
- getMplsForwardingObjective(targetSwId,
- nextHops,
- true,
- isMplsBos,
- metabuilder.build(),
- routerIp,
- segmentId,
- destSwId);
- // Error case, we cannot handle, exit.
- if (fwdObjNoBosBuilder == null) {
- return Collections.emptyList();
- }
- fwdObjBuilders.add(fwdObjNoBosBuilder);
-
- } else {
- // next hop is not destination, irrespective of the number of next
- // hops (1 or more) -- SR CONTINUE case (swap with self)
- log.debug("Installing MPLS forwarding objective for "
- + "label {} in switch {} without pop to next-hops {}",
- segmentId, targetSwId, nextHops);
- ForwardingObjective.Builder fwdObjNoBosBuilder =
- getMplsForwardingObjective(targetSwId,
- nextHops,
- false,
- isMplsBos,
- metabuilder.build(),
- routerIp,
- segmentId,
- destSwId);
- // Error case, we cannot handle, exit.
- if (fwdObjNoBosBuilder == null) {
- return Collections.emptyList();
- }
- fwdObjBuilders.add(fwdObjNoBosBuilder);
-
- }
-
- List<ForwardingObjective> fwdObjs = Lists.newArrayList();
- // We add the final property to the fwdObjs.
- for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
- ((Builder) ((Builder) fwdObjBuilder
- .fromApp(srManager.appId)
- .makePermanent())
- .withSelector(selector)
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY))
- .withFlag(ForwardingObjective.Flag.SPECIFIC);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("MPLS rule {} for SID {} populated in dev:{} ",
- objective.id(), segmentId, targetSwId),
- (objective, error) ->
- log.warn("Failed to populate MPLS rule {} for SID {}: {} in dev:{}",
- objective.id(), segmentId, error, targetSwId));
-
- ForwardingObjective fob = fwdObjBuilder.add(context);
- fwdObjs.add(fob);
- }
-
- return fwdObjs;
- }
-
- /**
- * Returns a Forwarding Objective builder for the MPLS rule that references
- * the desired Next Objective. Creates a DestinationSet that allows the
- * groupHandler to create or find the required next objective.
- *
- * @param targetSw the target sw
- * @param nextHops the set of next hops
- * @param phpRequired true if penultimate-hop-popping is required
- * @param isBos true if matched label is bottom-of-stack
- * @param meta metadata for creating next objective
- * @param routerIp the router ip representing the destination switch
- * @param destSw the destination sw
- * @return the mpls forwarding objective builder
- */
- private ForwardingObjective.Builder getMplsForwardingObjective(
- DeviceId targetSw,
- Set<DeviceId> nextHops,
- boolean phpRequired,
- boolean isBos,
- TrafficSelector meta,
- IpAddress routerIp,
- int segmentId,
- DeviceId destSw) {
-
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
-
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- DestinationSet ds = null;
- DestinationSet.DestinationSetType dstType = null;
- boolean simple = false;
- if (phpRequired) {
- // php case - pop should always be flow-action
- log.debug("getMplsForwardingObjective: php required");
- tbuilder.deferred().copyTtlIn();
- if (isBos) {
- if (routerIp.isIp4()) {
- tbuilder.deferred().popMpls(EthType.EtherType.IPV4.ethType());
- } else {
- tbuilder.deferred().popMpls(EthType.EtherType.IPV6.ethType());
- }
- tbuilder.decNwTtl();
- // standard case -> BoS == True; pop results in IP packet and forwarding
- // is via an ECMP group
- ds = DestinationSet.createTypePopBos(destSw);
- } else {
- tbuilder.deferred().popMpls(EthType.EtherType.MPLS_UNICAST.ethType())
- .decMplsTtl();
- // double-label case -> BoS == False, pop results in MPLS packet
- // depending on configuration we can ECMP this packet or choose one output
- ds = DestinationSet.createTypePopNotBos(destSw);
- if (!srManager.getMplsEcmp()) {
- simple = true;
- }
- }
- } else {
- // swap with self case - SR CONTINUE
- log.debug("getMplsForwardingObjective: swap with self");
- tbuilder.deferred().decMplsTtl();
- // swap results in MPLS packet with same BoS bit regardless of bit value
- // depending on configuration we can ECMP this packet or choose one output
- // differentiate here between swap with not bos or swap with bos
- ds = isBos ? DestinationSet.createTypeSwapBos(segmentId, destSw) :
- DestinationSet.createTypeSwapNotBos(segmentId, destSw);
- if (!srManager.getMplsEcmp()) {
- simple = true;
- }
- }
-
- fwdBuilder.withTreatment(tbuilder.build());
- log.debug("Trying to get a nextObjId for mpls rule on device:{} to ds:{}",
- targetSw, ds);
- DefaultGroupHandler gh = srManager.getGroupHandler(targetSw);
- if (gh == null) {
- log.warn("getNextObjectiveId query - groupHandler for device {} "
- + "not found", targetSw);
- return null;
- }
-
- Map<DeviceId, Set<DeviceId>> dstNextHops = new HashMap<>();
- dstNextHops.put(destSw, nextHops);
- int nextId = gh.getNextObjectiveId(ds, dstNextHops, meta, simple);
- if (nextId <= 0) {
- log.warn("No next objective in {} for ds: {}", targetSw, ds);
- return null;
- } else {
- log.debug("nextObjId found:{} for mpls rule on device:{} to ds:{}",
- nextId, targetSw, ds);
- }
-
- fwdBuilder.nextStep(nextId);
- return fwdBuilder;
- }
-
- /**
- * Creates a filtering objective to permit all untagged packets with a
- * dstMac corresponding to the router's MAC address. For those pipelines
- * that need to internally assign vlans to untagged packets, this method
- * provides per-subnet vlan-ids as metadata.
- * <p>
- * 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
- */
- PortFilterInfo populateVlanMacFilters(DeviceId deviceId) {
- log.debug("Installing per-port filtering objective for untagged "
- + "packets in device {}", deviceId);
-
- 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, errorPorts = 0, filteredPorts = 0;
- for (Port port : devPorts) {
- if (!port.isEnabled()) {
- disabledPorts++;
- continue;
- }
- if (processSinglePortFilters(deviceId, port.number(), true)) {
- filteredPorts++;
- } else {
- errorPorts++;
- }
- }
- log.debug("Filtering on dev:{}, disabledPorts:{}, errorPorts:{}, filteredPorts:{}",
- deviceId, disabledPorts, errorPorts, filteredPorts);
- return new PortFilterInfo(disabledPorts, errorPorts, filteredPorts);
- }
-
- /**
- * Creates or 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 for port to be filtered
- * @param install true to install the filtering objective, false to remove
- * @return true if no errors occurred during the build of the filtering objective
- */
- boolean processSinglePortFilters(DeviceId deviceId, PortNumber portnum, boolean install) {
- ConnectPoint connectPoint = new ConnectPoint(deviceId, portnum);
- VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
- Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
- VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
- // Do not configure filter for edge ports where double-tagged hosts are connected.
- if (taggedVlans.size() != 0) {
- // Filter for tagged vlans
- if (!srManager.interfaceService.getTaggedVlanId(connectPoint).stream().allMatch(taggedVlanId ->
- processSinglePortFiltersInternal(deviceId, portnum, false, taggedVlanId, install))) {
- return false;
- }
- if (nativeVlan != null) {
- // Filter for native vlan
- if (!processSinglePortFiltersInternal(deviceId, portnum, true, nativeVlan, install)) {
- return false;
- }
- }
- } else if (untaggedVlan != null) {
- // Filter for untagged vlan
- if (!processSinglePortFiltersInternal(deviceId, portnum, true, untaggedVlan, install)) {
- return false;
- }
- } else if (!hasIPConfiguration(connectPoint)) {
- // Filter for unconfigured upstream port, using INTERNAL_VLAN
- if (!processSinglePortFiltersInternal(deviceId, portnum, true,
- srManager.getDefaultInternalVlan(),
- install)) {
- return false;
- }
- // Filter for receiveing pseudowire traffic
- if (!processSinglePortFiltersInternal(deviceId, portnum, false,
- srManager.getPwTransportVlan(),
- install)) {
- return false;
- }
- }
- 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) {
- boolean doTMAC = true;
-
- if (!pushVlan) {
- // Skip the tagged vlans belonging to an interface without an IP address
- Set<Interface> ifaces = srManager.interfaceService
- .getInterfacesByPort(new ConnectPoint(deviceId, portnum))
- .stream()
- .filter(intf -> intf.vlanTagged().contains(vlanId) && intf.ipAddressesList().isEmpty())
- .collect(Collectors.toSet());
- if (!ifaces.isEmpty()) {
- log.debug("processSinglePortFiltersInternal: skipping TMAC for vlan {} at {}/{} - no IP",
- vlanId, deviceId, portnum);
- doTMAC = false;
- }
- }
-
- FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum, pushVlan, vlanId, doTMAC);
- if (fob == null) {
- // error encountered during build
- return false;
- }
- log.debug("{} filtering objectives for dev/port: {}/{}",
- install ? "Installing" : "Removing", deviceId, portnum);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Filter for {}/{} {}", deviceId, portnum,
- install ? "installed" : "removed"),
- (objective, error) -> log.warn("Failed to {} filter for {}/{}: {}",
- install ? "install" : "remove", deviceId, portnum, error));
- if (install) {
- srManager.flowObjectiveService.filter(deviceId, fob.add(context));
- } else {
- srManager.flowObjectiveService.filter(deviceId, fob.remove(context));
- }
- return true;
- }
-
- private FilteringObjective.Builder buildFilteringObjective(DeviceId deviceId, PortNumber portnum,
- boolean pushVlan, VlanId vlanId, boolean doTMAC) {
- MacAddress deviceMac;
- try {
- deviceMac = config.getDeviceMac(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Processing SinglePortFilters aborted");
- return null;
- }
- FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
-
- if (doTMAC) {
- fob.withKey(Criteria.matchInPort(portnum))
- .addCondition(Criteria.matchEthDst(deviceMac))
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
- } else {
- fob.withKey(Criteria.matchInPort(portnum))
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
- }
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- if (pushVlan) {
- fob.addCondition(Criteria.matchVlanId(VlanId.NONE));
- tBuilder.pushVlan().setVlanId(vlanId);
- } else {
- fob.addCondition(Criteria.matchVlanId(vlanId));
- }
-
- // NOTE: Some switch hardware share the same filtering flow among different ports.
- // We use this metadata to let the driver know that there is no more enabled port
- // within the same VLAN on this device.
- if (noMoreEnabledPort(deviceId, vlanId)) {
- tBuilder.wipeDeferred();
- }
-
- fob.withMeta(tBuilder.build());
-
- fob.permit().fromApp(srManager.appId);
- return fob;
- }
-
- /**
- * Creates or removes filtering objectives for a double-tagged host on a port.
- *
- * @param deviceId device identifier
- * @param portNum port identifier for port to be filtered
- * @param outerVlan outer VLAN ID
- * @param innerVlan inner VLAN ID
- * @param install true to install the filtering objective, false to remove
- */
- void processDoubleTaggedFilter(DeviceId deviceId, PortNumber portNum, VlanId outerVlan,
- VlanId innerVlan, boolean install) {
- // We should trigger the removal of double tagged rules only when removing
- // the filtering objective and no other hosts are connected to the same device port.
- boolean cleanupDoubleTaggedRules = !anyDoubleTaggedHost(deviceId, portNum) && !install;
- FilteringObjective.Builder fob = buildDoubleTaggedFilteringObj(deviceId, portNum,
- outerVlan, innerVlan,
- cleanupDoubleTaggedRules);
- if (fob == null) {
- // error encountered during build
- return;
- }
- log.debug("{} double-tagged filtering objectives for dev/port: {}/{}",
- install ? "Installing" : "Removing", deviceId, portNum);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Filter for {}/{} {}", deviceId, portNum,
- install ? "installed" : "removed"),
- (objective, error) -> log.warn("Failed to {} filter for {}/{}: {}",
- install ? "install" : "remove", deviceId, portNum, error));
- if (install) {
- srManager.flowObjectiveService.filter(deviceId, fob.add(context));
- } else {
- srManager.flowObjectiveService.filter(deviceId, fob.remove(context));
- }
- }
-
- /**
- * Checks if there is any double tagged host attached to given location.
- * This method will match on the effective location of a host.
- * That is, it will match on auxLocations when auxLocations is not null. Otherwise, it will match on locations.
- *
- * @param deviceId device ID
- * @param portNum port number
- * @return true if there is any host attached to given location.
- */
- private boolean anyDoubleTaggedHost(DeviceId deviceId, PortNumber portNum) {
- ConnectPoint cp = new ConnectPoint(deviceId, portNum);
- Set<Host> connectedHosts = srManager.hostService.getConnectedHosts(cp, false);
- Set<Host> auxConnectedHosts = srManager.hostService.getConnectedHosts(cp, true);
- return !auxConnectedHosts.isEmpty() ||
- connectedHosts.stream().anyMatch(host -> host.auxLocations() == null);
- }
-
- private FilteringObjective.Builder buildDoubleTaggedFilteringObj(DeviceId deviceId, PortNumber portNum,
- VlanId outerVlan, VlanId innerVlan,
- boolean cleanupDoubleTaggedRules) {
- MacAddress deviceMac;
- try {
- deviceMac = config.getDeviceMac(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Processing DoubleTaggedFilters aborted");
- return null;
- }
- FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
- // Outer vlan id match should be appeared before inner vlan id match.
- fob.withKey(Criteria.matchInPort(portNum))
- .addCondition(Criteria.matchEthDst(deviceMac))
- .addCondition(Criteria.matchVlanId(outerVlan))
- .addCondition(Criteria.matchInnerVlanId(innerVlan))
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- // Pop outer vlan
- tBuilder.popVlan();
-
- // special metadata for driver
- if (cleanupDoubleTaggedRules) {
- tBuilder.writeMetadata(CLEANUP_DOUBLE_TAGGED_HOST_ENTRIES, DOUBLE_TAGGED_METADATA_MASK);
- } else {
- tBuilder.writeMetadata(0, DOUBLE_TAGGED_METADATA_MASK);
- }
-
- // NOTE: Some switch hardware share the same filtering flow among different ports.
- // We use this metadata to let the driver know that there is no more enabled port
- // within the same VLAN on this device.
- if (noMoreEnabledPort(deviceId, outerVlan)) {
- tBuilder.wipeDeferred();
- }
-
- fob.withMeta(tBuilder.build());
-
- fob.permit().fromApp(srManager.appId);
- return fob;
- }
-
- /**
- * Creates a forwarding objective to punt all IP packets, destined to the
- * router's port IP addresses, to the controller. Note that the input
- * port should not be matched on, as these packets can come from any input.
- * Furthermore, these are applied only by the master instance.
- *
- * @param deviceId the switch dpid for the router
- */
- void populateIpPunts(DeviceId deviceId) {
- Ip4Address routerIpv4, pairRouterIpv4 = null;
- Ip6Address routerIpv6, routerLinkLocalIpv6, pairRouterIpv6 = null;
- try {
- routerIpv4 = config.getRouterIpv4(deviceId);
- routerIpv6 = config.getRouterIpv6(deviceId);
- routerLinkLocalIpv6 = Ip6Address.valueOf(
- IPv6.getLinkLocalAddress(config.getDeviceMac(deviceId).toBytes()));
-
- if (config.isPairedEdge(deviceId)) {
- pairRouterIpv4 = config.getRouterIpv4(config.getPairDeviceId(deviceId));
- pairRouterIpv6 = config.getRouterIpv6(config.getPairDeviceId(deviceId));
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting populateIpPunts.");
- return;
- }
-
- if (!srManager.mastershipService.isLocalMaster(deviceId)) {
- log.debug("Not installing port-IP punts - not the master for dev:{} ",
- deviceId);
- return;
- }
- Set<IpAddress> allIps = new HashSet<>(config.getPortIPs(deviceId));
- allIps.add(routerIpv4);
- if (routerIpv6 != null) {
- allIps.add(routerIpv6);
- allIps.add(routerLinkLocalIpv6);
- }
- if (pairRouterIpv4 != null) {
- allIps.add(pairRouterIpv4);
- }
- if (pairRouterIpv6 != null) {
- allIps.add(pairRouterIpv6);
- }
- for (IpAddress ipaddr : allIps) {
- populateSingleIpPunts(deviceId, ipaddr);
- }
- }
-
- /**
- * 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");
- }
- }
-
- // Method for building an IPv4 selector
- private TrafficSelector.Builder buildIpv4Selector() {
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
- selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
- return selectorBuilder;
- }
-
- // Method for building an IPv6 selector
- private TrafficSelector.Builder buildIpv6Selector() {
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
- selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
- return selectorBuilder;
- }
-
- // Method for building an IPv4 or IPv6 selector from an IP address
- private TrafficSelector.Builder buildIpSelectorFromIpAddress(IpAddress addressToMatch) {
- return buildIpSelectorFromIpPrefix(addressToMatch.toIpPrefix());
- }
-
- // Method for building an IPv4 or IPv6 selector from an IP prefix
- private TrafficSelector.Builder buildIpSelectorFromIpPrefix(IpPrefix prefixToMatch) {
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
- // If the prefix is IPv4
- if (prefixToMatch.isIp4()) {
- selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
- selectorBuilder.matchIPDst(prefixToMatch.getIp4Prefix());
- return selectorBuilder;
- }
- // If the prefix is IPv6
- selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
- selectorBuilder.matchIPv6Dst(prefixToMatch.getIp6Prefix());
- return selectorBuilder;
- }
-
- /**
- * Creates forwarding objectives to punt ARP and NDP packets, to the controller.
- * Furthermore, these are applied only by the master instance. Deferred actions
- * are not cleared such that packets can be flooded in the cross connect use case
- *
- * @param deviceId the switch dpid for the router
- */
- void populateArpNdpPunts(DeviceId deviceId) {
- // We are not the master just skip.
- if (!srManager.mastershipService.isLocalMaster(deviceId)) {
- log.debug("Not installing ARP/NDP punts - not the master for dev:{} ",
- deviceId);
- return;
- }
-
- ForwardingObjective fwdObj;
- // We punt all ARP packets towards the controller.
- fwdObj = arpFwdObjective(null, true, ARP_NDP_PRIORITY)
- .add(new ObjectiveContext() {
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to install forwarding objective to punt ARP to {}: {}",
- deviceId, error);
- }
- });
- srManager.flowObjectiveService.forward(deviceId, fwdObj);
-
- if (isIpv6Configured(deviceId)) {
- // We punt all NDP packets towards the controller.
- ndpFwdObjective(null, true, ARP_NDP_PRIORITY).forEach(builder -> {
- ForwardingObjective obj = builder.add(new ObjectiveContext() {
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to install forwarding objective to punt NDP to {}: {}",
- deviceId, error);
- }
- });
- srManager.flowObjectiveService.forward(deviceId, obj);
- });
- }
-
- srManager.getPairLocalPort(deviceId).ifPresent(port -> {
- ForwardingObjective pairFwdObj;
- // Do not punt ARP packets from pair port
- pairFwdObj = arpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1)
- .add(new ObjectiveContext() {
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
- deviceId, error);
- }
- });
- srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
-
- if (isIpv6Configured(deviceId)) {
- // Do not punt NDP packets from pair port
- ndpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1).forEach(builder -> {
- ForwardingObjective obj = builder.add(new ObjectiveContext() {
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
- deviceId, error);
- }
- });
- srManager.flowObjectiveService.forward(deviceId, obj);
- });
-
- // Do not forward DAD packets from pair port
- pairFwdObj = dad6FwdObjective(port, PacketPriority.CONTROL.priorityValue() + 2)
- .add(new ObjectiveContext() {
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to install forwarding objective to drop DAD to {}: {}",
- deviceId, error);
- }
- });
- srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
- }
- });
- }
-
- private ForwardingObjective.Builder fwdObjBuilder(TrafficSelector selector,
- TrafficTreatment treatment, int priority) {
- return DefaultForwardingObjective.builder()
- .withPriority(priority)
- .withSelector(selector)
- .fromApp(srManager.appId)
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .withTreatment(treatment)
- .makePermanent();
- }
-
- private ForwardingObjective.Builder arpFwdObjective(PortNumber port, boolean punt, int priority) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- sBuilder.matchEthType(TYPE_ARP);
- if (port != null) {
- sBuilder.matchInPort(port);
- }
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (punt) {
- tBuilder.punt();
- }
- return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
- }
-
- private Set<ForwardingObjective.Builder> ndpFwdObjective(PortNumber port, boolean punt, int priority) {
- Set<ForwardingObjective.Builder> result = Sets.newHashSet();
-
- Lists.newArrayList(NEIGHBOR_SOLICITATION, NEIGHBOR_ADVERTISEMENT, ROUTER_SOLICITATION, ROUTER_ADVERTISEMENT)
- .forEach(type -> {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- sBuilder.matchEthType(TYPE_IPV6)
- .matchIPProtocol(PROTOCOL_ICMP6)
- .matchIcmpv6Type(type);
- if (port != null) {
- sBuilder.matchInPort(port);
- }
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (punt) {
- tBuilder.punt();
- }
-
- result.add(fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority));
- });
-
- return result;
- }
-
- private ForwardingObjective.Builder dad6FwdObjective(PortNumber port, int priority) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- sBuilder.matchEthType(TYPE_IPV6)
- .matchIPv6Src(Ip6Address.ZERO.toIpPrefix());
- // TODO CORD-1672 Fix this when OFDPA can distinguish ::/0 and ::/128 correctly
- // .matchIPProtocol(PROTOCOL_ICMP6)
- // .matchIcmpv6Type(NEIGHBOR_SOLICITATION);
- if (port != null) {
- sBuilder.matchInPort(port);
- }
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- tBuilder.wipeDeferred();
- return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
- }
-
- /**
- * Block given prefix in routing table.
- *
- * @param address the address to block
- * @param deviceId switch ID to set the rules
- */
- void populateDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address) {
- updateDefaultRouteBlackhole(deviceId, address, true);
- }
-
- /**
- * Unblock given prefix in routing table.
- *
- * @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.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) {
- srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
- 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) {
- if (!srManager.getVlanPortMap(deviceId).containsKey(vlanId) ||
- !srManager.getVlanPortMap(deviceId).get(vlanId).contains(portNumber)) {
- 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());
- }
- }
- }
- }
-
- /**
- * Checks if there is other enabled port within the given VLAN on the given device.
- *
- * @param deviceId device ID
- * @param vlanId VLAN ID
- * @return true if there is no more port enabled within the given VLAN on the given device
- */
- boolean noMoreEnabledPort(DeviceId deviceId, VlanId vlanId) {
- Set<ConnectPoint> enabledPorts = srManager.deviceService.getPorts(deviceId).stream()
- .filter(Port::isEnabled)
- .map(port -> new ConnectPoint(port.element().id(), port.number()))
- .collect(Collectors.toSet());
-
- return enabledPorts.stream().noneMatch(cp ->
- // Given vlanId is included in the vlan-tagged configuration
- srManager.interfaceService.getTaggedVlanId(cp).contains(vlanId) ||
- // Given vlanId is INTERNAL_VLAN or PSEUDOWIRE_VLAN and the interface is not configured
- (srManager.interfaceService.getTaggedVlanId(cp).isEmpty() && srManager.getInternalVlanId(cp) == null &&
- (vlanId.equals(srManager.getDefaultInternalVlan()) || vlanId.equals(srManager.getPwTransportVlan()))) ||
- // interface is configured and either vlan-untagged or vlan-native matches given vlanId
- (srManager.getInternalVlanId(cp) != null && srManager.getInternalVlanId(cp).equals(vlanId))
- );
- }
-
- /**
- * Returns a forwarding objective builder for egress forwarding rules.
- * <p>
- * The forwarding objective installs flow rules to egress pipeline to push
- * two vlan headers with given inner, outer vlan ids and outer tpid.
- *
- * @param portNumber port where the next hop attaches to
- * @param dummyVlanId vlan ID of the packet to match
- * @param innerVlan inner vlan ID of the next hop
- * @param outerVlan outer vlan ID of the next hop
- * @param outerTpid outer TPID of the next hop
- * @return forwarding objective builder
- */
- private ForwardingObjective.Builder egressFwdObjBuilder(PortNumber portNumber, VlanId dummyVlanId,
- VlanId innerVlan, VlanId outerVlan, EthType outerTpid) {
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- sbuilder.matchVlanId(dummyVlanId);
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.setOutput(portNumber).setVlanId(innerVlan);
-
- if (outerTpid.equals(EthType.EtherType.QINQ.ethType())) {
- tbuilder.pushVlan(outerTpid);
- } else {
- tbuilder.pushVlan();
- }
-
- tbuilder.setVlanId(outerVlan);
- return DefaultForwardingObjective.builder()
- .withSelector(sbuilder.build())
- .withTreatment(tbuilder.build())
- .fromApp(srManager.appId)
- .makePermanent()
- .withPriority(DEFAULT_PRIORITY)
- .withFlag(ForwardingObjective.Flag.EGRESS);
- }
-
- /**
- * Populates IP rules for a route that has double-tagged next hop.
- *
- * @param deviceId device ID of the device that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param innerVlan inner Vlan ID of the next hop
- * @param outerVlan outer Vlan ID of the next hop
- * @param outerTpid outer TPID of the next hop
- * @param outPort port where the next hop attaches to
- */
- void populateDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
- VlanId innerVlan, VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
- ForwardingObjective.Builder fwdBuilder;
- log.debug("Populate direct routing entry for double-tagged host route {} at {}:{}",
- prefix, deviceId, outPort);
-
- try {
- fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac, outerVlan, outPort, innerVlan, outerTpid,
- true, false);
- } catch (DeviceConfigNotFoundException e) {
- log.error(e.getMessage() + " Aborting populateDoubleTaggedRoute");
- return;
- }
- if (fwdBuilder == null) {
- log.error("Aborting double-tagged host routing table entry due to error for dev:{} route:{}",
- deviceId, prefix);
- return;
- }
-
- int nextId = fwdBuilder.add().nextId();
- DefaultObjectiveContext context = new DefaultObjectiveContext(objective -> {
- log.debug("Direct routing rule for double-tagged host route {} populated. nextId={}", prefix, nextId);
- }, (objective, error) ->
- log.warn("Failed to populate direct routing rule for double-tagged host route {}: {}", prefix, error)
- );
- srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
- rulePopulationCounter.incrementAndGet();
- }
-
- /**
- * Revokes IP rules for a route that has double-tagged next hop.
- *
- * @param deviceId device ID of the device that next hop attaches to
- * @param prefix IP prefix of the route
- * @param hostMac MAC address of the next hop
- * @param innerVlan inner Vlan ID of the next hop
- * @param outerVlan outer Vlan ID of the next hop
- * @param outerTpid outer TPID of the next hop
- * @param outPort port where the next hop attaches to
- */
- void revokeDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
- VlanId innerVlan, VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
- ForwardingObjective.Builder fwdBuilder;
- log.debug("Revoking direct routing entry for double-tagged host route {} at {}:{}",
- prefix, deviceId, outPort);
-
- try {
- fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac, outerVlan, outPort, innerVlan, outerTpid,
- true, true);
- } catch (DeviceConfigNotFoundException e) {
- log.error(e.getMessage() + " Aborting revokeDoubleTaggedRoute");
- return;
- }
- if (fwdBuilder == null) {
- log.error("Aborting double-tagged host routing table entry due to error for dev:{} route:{}",
- deviceId, prefix);
- return;
- }
-
- int nextId = fwdBuilder.remove().nextId();
- DefaultObjectiveContext context = new DefaultObjectiveContext(objective -> {
- log.debug("Direct routing rule for double-tagged host route {} revoked. nextId={}", prefix, nextId);
-
- // Try to remove next objective as well
- ImmutablePair<TrafficTreatment, TrafficSelector> treatmentAndMeta;
- try {
- treatmentAndMeta = getTreatmentAndMeta(deviceId, hostMac, outerVlan, outPort, innerVlan, outerTpid);
- } catch (DeviceConfigNotFoundException e) {
- log.error(e.getMessage() + " Aborting revokeDoubleTaggedRoute");
- return;
- }
-
- if (treatmentAndMeta == null) {
- // Warning log will come from getTreatmentAndMeta method
- return;
- }
-
- DefaultGroupHandler groupHandler = srManager.getGroupHandler(deviceId);
- if (groupHandler == null) {
- log.warn("Failed to revoke direct routing rule for double-tagged host route {}: " +
- "group handler not found for {}", prefix, deviceId);
- return;
- }
- groupHandler.removeGroupFromPort(outPort, treatmentAndMeta.getLeft(), treatmentAndMeta.getRight());
-
- }, (objective, error) ->
- log.warn("Failed to revoke direct routing rule for double-tagged host route {}: {}", prefix, error)
- );
- srManager.flowObjectiveService.forward(deviceId, fwdBuilder.remove(context));
- }
-
- /**
- * Checks whether the specified port has IP configuration or not.
- *
- * @param cp ConnectPoint to check the existance of IP configuration
- * @return true if the port has IP configuration; false otherwise.
- */
- private boolean hasIPConfiguration(ConnectPoint cp) {
- Set<Interface> interfaces = srManager.interfaceService.getInterfacesByPort(cp);
- return interfaces.stream().anyMatch(intf -> intf.ipAddressesList().size() > 0);
- }
-
- /**
- * Updates filtering rules for unconfigured ports on all devices for which
- * this controller instance is master.
- *
- * @param pushVlan true if the filtering rule requires a push vlan action
- * @param oldVlanId the vlanId to be removed
- * @param newVlanId the vlanId to be added
- */
- void updateSpecialVlanFilteringRules(boolean pushVlan, VlanId oldVlanId,
- VlanId newVlanId) {
- for (Device dev : srManager.deviceService.getAvailableDevices()) {
- if (srManager.mastershipService.isLocalMaster(dev.id())) {
- for (Port p : srManager.deviceService.getPorts(dev.id())) {
- if (!hasIPConfiguration(new ConnectPoint(dev.id(), p.number()))
- && p.isEnabled()) {
- updateSinglePortFilters(dev.id(), p.number(), pushVlan,
- oldVlanId, false);
- updateSinglePortFilters(dev.id(), p.number(), pushVlan,
- newVlanId, true);
- }
- }
- }
- }
- }
-
- private boolean isIpv6Configured(DeviceId deviceId) {
- boolean isIpv6Configured;
- try {
- isIpv6Configured = (config.getRouterIpv6(deviceId) != null);
- } catch (DeviceConfigNotFoundException e) {
- isIpv6Configured = false;
- }
- return isIpv6Configured;
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SRLinkWeigher.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SRLinkWeigher.java
deleted file mode 100644
index 01e07a7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SRLinkWeigher.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.graph.DefaultEdgeWeigher;
-import org.onlab.graph.ScalarWeight;
-import org.onlab.graph.Weight;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.topology.LinkWeigher;
-import org.onosproject.net.topology.TopologyEdge;
-import org.onosproject.net.topology.TopologyVertex;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-
-import java.util.Set;
-
-/**
- * Link weigher for multicast related path computations.
- */
-public final class SRLinkWeigher
- extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
- implements LinkWeigher {
-
- private final SegmentRoutingManager srManager;
- private final DeviceId srcPath;
- private final Set<Link> linksToEnforce;
-
- // Weight for the link to avoids. The high level idea is to build
- // a constrained shortest path computation. 100 should provide a good
- // threshold
- public static final ScalarWeight LINK_TO_AVOID_WEIGHT = new ScalarWeight(HOP_WEIGHT_VALUE + 100);
-
- /**
- * Creates a SRLinkWeigher object.
- *
- * @param srManager SegmentRoutingManager object
- * @param srcPath the source of the paths
- * @param linksToEnforce links to be enforced by the path computation
- */
- public SRLinkWeigher(SegmentRoutingManager srManager, DeviceId srcPath,
- Set<Link> linksToEnforce) {
- this.srManager = srManager;
- this.srcPath = srcPath;
- this.linksToEnforce = linksToEnforce;
- }
-
- @Override
- public Weight weight(TopologyEdge edge) {
- // 1) We need to avoid some particular paths like leaf-spine-leaf-*
- // 2) Properly handle the pair links
-
- // If the link is a pair link just return infinite value
- if (isPairLink(edge.link())) {
- return ScalarWeight.NON_VIABLE_WEIGHT;
- }
-
- // To avoid that the paths go through other leaves we need to influence
- // the path computation to return infinite value for all other links having
- // as a src a leaf different from the source we are passing to the weigher
- DeviceId srcDeviceLink = edge.link().src().deviceId();
- // Identify the link as leaf-spine link
- boolean isLeafSpine;
- try {
- isLeafSpine = srManager.deviceConfiguration().isEdgeDevice(srcDeviceLink);
- } catch (DeviceConfigNotFoundException e) {
- isLeafSpine = false;
- }
- // If it is not the source just return infinite value
- if (isLeafSpine && !srcDeviceLink.equals(srcPath)) {
- return ScalarWeight.NON_VIABLE_WEIGHT;
- }
-
- // If the links are not in the list of the links to be enforce
- if (!linksToEnforce.isEmpty() && !linksToEnforce.contains(edge.link())) {
- // 100 should be a good confidence threshold
- return LINK_TO_AVOID_WEIGHT;
- }
-
- // All other cases we return
- return new ScalarWeight(HOP_WEIGHT_VALUE);
- }
-
- // Utility method to verify is a link is a pair-link
- private boolean isPairLink(Link link) {
- // Take src id, src port, dst id and dst port
- final DeviceId srcId = link.src().deviceId();
- final PortNumber srcPort = link.src().port();
- final DeviceId dstId = link.dst().deviceId();
- final PortNumber dstPort = link.dst().port();
- // init as true
- boolean isPairLink = true;
- try {
- // If one of this condition is not true; it is not a pair link
- if (!(srManager.deviceConfiguration().isEdgeDevice(srcId) &&
- srManager.deviceConfiguration().isEdgeDevice(dstId) &&
- srManager.deviceConfiguration().getPairDeviceId(srcId).equals(dstId) &&
- srManager.deviceConfiguration().getPairLocalPort(srcId).equals(srcPort) &&
- srManager.deviceConfiguration().getPairLocalPort(dstId).equals(dstPort))) {
- isPairLink = false;
- }
- } catch (DeviceConfigNotFoundException e) {
- // Configuration not provided
- isPairLink = false;
- }
- return isPairLink;
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
deleted file mode 100644
index 5f11501..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ /dev/null
@@ -1,2397 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onlab.util.Tools;
-import org.onosproject.cfg.ComponentConfigService;
-import org.onosproject.cluster.ClusterEvent;
-import org.onosproject.cluster.ClusterEventListener;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.LeadershipService;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.event.Event;
-import org.onosproject.mastership.MastershipEvent;
-import org.onosproject.mastership.MastershipListener;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.mcast.api.McastEvent;
-import org.onosproject.mcast.api.McastListener;
-import org.onosproject.mcast.api.MulticastRouteService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.ConfigException;
-import org.onosproject.net.config.ConfigFactory;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.config.basics.McastConfig;
-import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.net.device.DeviceAdminService;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostProbingService;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intent.WorkPartitionService;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.net.link.LinkEvent;
-import org.onosproject.net.link.LinkListener;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.net.neighbour.NeighbourResolutionService;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.topology.TopologyEvent;
-import org.onosproject.net.topology.TopologyListener;
-import org.onosproject.net.topology.TopologyService;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteEvent;
-import org.onosproject.routeservice.RouteListener;
-import org.onosproject.routeservice.RouteService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
-import org.onosproject.segmentrouting.mcast.McastFilteringObjStoreKey;
-import org.onosproject.segmentrouting.mcast.McastHandler;
-import org.onosproject.segmentrouting.mcast.McastRole;
-import org.onosproject.segmentrouting.mcast.McastRoleStoreKey;
-import org.onosproject.segmentrouting.mcast.McastStoreKey;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.XConnectStoreKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.onosproject.store.service.EventuallyConsistentMapBuilder;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.WallClockTimestamp;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Modified;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.osgi.service.component.annotations.ReferencePolicy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkState;
-import static org.onlab.packet.Ethernet.TYPE_ARP;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_REGISTERED;
-import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UNREGISTERED;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.ACTIVE_PROBING_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.DEFAULT_INTERNAL_VLAN_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_ACTIVE_PROBING;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_DEFAULT_INTERNAL_VLAN;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_PW_TRANSPORT_VLAN;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_RESPOND_TO_UNKNOWN_HOSTS;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_ROUTE_DOUBLE_TAGGED_HOSTS;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_ROUTE_SIMPLIFICATION;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_SINGLE_HOMED_DOWN;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PROP_SYMMETRIC_PROBING;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.PW_TRANSPORT_VLAN_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.RESPOND_TO_UNKNOWN_HOSTS_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.ROUTE_SIMPLIFICATION_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.SINGLE_HOMED_DOWN_DEFAULT;
-import static org.onosproject.segmentrouting.OsgiPropertyConstants.SYMMETRIC_PROBING_DEFAULT;
-
-/**
- * Segment routing manager.
- */
-@Component(
- immediate = true,
- service = SegmentRoutingService.class,
- property = {
- PROP_ACTIVE_PROBING + ":Boolean=" + ACTIVE_PROBING_DEFAULT,
- PROP_SINGLE_HOMED_DOWN + ":Boolean=" + SINGLE_HOMED_DOWN_DEFAULT,
- PROP_RESPOND_TO_UNKNOWN_HOSTS + ":Boolean=" + RESPOND_TO_UNKNOWN_HOSTS_DEFAULT,
- PROP_ROUTE_DOUBLE_TAGGED_HOSTS + ":Boolean=" + ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT,
- PROP_DEFAULT_INTERNAL_VLAN + ":Integer=" + DEFAULT_INTERNAL_VLAN_DEFAULT,
- PROP_PW_TRANSPORT_VLAN + ":Integer=" + PW_TRANSPORT_VLAN_DEFAULT,
- PROP_SYMMETRIC_PROBING + ":Boolean=" + SYMMETRIC_PROBING_DEFAULT,
- PROP_ROUTE_SIMPLIFICATION + ":Boolean=" + ROUTE_SIMPLIFICATION_DEFAULT
- }
-)
-public class SegmentRoutingManager implements SegmentRoutingService {
-
- private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
- private static final String NOT_MASTER = "Current instance is not the master of {}. Ignore.";
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private ComponentConfigService compCfgService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public NeighbourResolutionService neighbourResolutionService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- PacketService packetService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- HostService hostService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- HostProbingService probingService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public DeviceService deviceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- DeviceAdminService deviceAdminService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public FlowObjectiveService flowObjectiveService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public LinkService linkService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public MastershipService mastershipService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public StorageService storageService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public MulticastRouteService multicastRouteService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public TopologyService topologyService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public RouteService routeService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public NetworkConfigRegistry cfgService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public InterfaceService interfaceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public ClusterService clusterService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public WorkPartitionService workPartitionService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public LeadershipService leadershipService;
-
- @Reference(cardinality = ReferenceCardinality.OPTIONAL,
- policy = ReferencePolicy.DYNAMIC)
- public volatile XconnectService xconnectService;
-
- @Reference(cardinality = ReferenceCardinality.OPTIONAL,
- policy = ReferencePolicy.DYNAMIC)
- volatile PhasedRecoveryService phasedRecoveryService;
-
- /** Enable active probing to discover dual-homed hosts. */
- boolean activeProbing = ACTIVE_PROBING_DEFAULT;
-
- /** Enable only send probe on the same port number of the pair device. */
- boolean symmetricProbing = SYMMETRIC_PROBING_DEFAULT;
-
- /** Enable administratively taking down single-homed hosts. */
- boolean singleHomedDown = SINGLE_HOMED_DOWN_DEFAULT;
-
- /** Enable this to respond to ARP/NDP requests from unknown hosts. */
- boolean respondToUnknownHosts = RESPOND_TO_UNKNOWN_HOSTS_DEFAULT;
-
- /** Program flows and groups to pop and route double tagged hosts. */
- boolean routeDoubleTaggedHosts = ROUTE_DOUBLE_TAGGED_HOSTS_DEFAULT;
-
- /** internal vlan assigned by default to unconfigured ports. */
- private int defaultInternalVlan = DEFAULT_INTERNAL_VLAN_DEFAULT;
-
- /** vlan used for transport of pseudowires between switches. */
- private int pwTransportVlan = PW_TRANSPORT_VLAN_DEFAULT;
-
- /** Enabling route simplification. */
- boolean routeSimplification = ROUTE_SIMPLIFICATION_DEFAULT;
-
- ArpHandler arpHandler = null;
- IcmpHandler icmpHandler = null;
- IpHandler ipHandler = null;
- RoutingRulePopulator routingRulePopulator = null;
- ApplicationId appId;
- DeviceConfiguration deviceConfiguration = null;
-
- DefaultRoutingHandler defaultRoutingHandler = null;
- private TunnelHandler tunnelHandler = null;
- private PolicyHandler policyHandler = null;
- private InternalPacketProcessor processor = null;
- private InternalLinkListener linkListener = null;
- private InternalDeviceListener deviceListener = null;
- private AppConfigHandler appCfgHandler = null;
- McastHandler mcastHandler = null;
- HostHandler hostHandler = null;
- private RouteHandler routeHandler = null;
- LinkHandler linkHandler = null;
- private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
- private DefaultL2TunnelHandler l2TunnelHandler = null;
- private TopologyHandler topologyHandler = null;
- private final InternalHostListener hostListener = new InternalHostListener();
- private final InternalConfigListener cfgListener = new InternalConfigListener(this);
- private final InternalMcastListener mcastListener = new InternalMcastListener();
- private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
- private final InternalTopologyListener topologyListener = new InternalTopologyListener();
- private final InternalMastershipListener mastershipListener = new InternalMastershipListener();
- final InternalClusterListener clusterListener = new InternalClusterListener();
- //Completable future for network configuration process to buffer config events handling during activation
- private CompletableFuture<Boolean> networkConfigCompletion = null;
- private final Object networkConfigCompletionLock = new Object();
- private List<Event> queuedEvents = new CopyOnWriteArrayList<>();
-
- // Handles device, link, topology and network config events
- private ScheduledExecutorService mainEventExecutor;
-
- // Handles host, route and mcast events respectively
- private ScheduledExecutorService hostEventExecutor;
- private ScheduledExecutorService routeEventExecutor;
- private ScheduledExecutorService mcastEventExecutor;
- private ExecutorService packetExecutor;
- ExecutorService neighborExecutor;
-
- Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<>();
- /**
- * Per device next objective ID store with (device id + destination set) as key.
- * Used to keep track on MPLS group information.
- */
- private EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
- dsNextObjStore = null;
- /**
- * Per device next objective ID store with (device id + vlanid) as key.
- * Used to keep track on L2 flood group information.
- */
- private EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
- vlanNextObjStore = null;
- /**
- * Per device next objective ID store with (device id + port + treatment + meta) as key.
- * Used to keep track on L2 interface group and L3 unicast group information for direct hosts.
- */
- private EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
- portNextObjStore = null;
-
- /**
- * Per device next objective ID store with (device id + MAC address + vlan) as key.
- * Used to keep track of L3 unicast group for indirect hosts.
- */
- private EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer>
- macVlanNextObjStore = null;
-
- private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
- private EventuallyConsistentMap<String, Policy> policyStore = null;
-
- private AtomicBoolean programmingScheduled = new AtomicBoolean();
-
- private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory =
- new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(
- SubjectFactories.DEVICE_SUBJECT_FACTORY,
- SegmentRoutingDeviceConfig.class, "segmentrouting") {
- @Override
- public SegmentRoutingDeviceConfig createConfig() {
- return new SegmentRoutingDeviceConfig();
- }
- };
-
- private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory =
- new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(
- SubjectFactories.APP_SUBJECT_FACTORY,
- SegmentRoutingAppConfig.class, "segmentrouting") {
- @Override
- public SegmentRoutingAppConfig createConfig() {
- return new SegmentRoutingAppConfig();
- }
- };
-
- private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
- new ConfigFactory<ApplicationId, McastConfig>(
- SubjectFactories.APP_SUBJECT_FACTORY,
- McastConfig.class, "multicast") {
- @Override
- public McastConfig createConfig() {
- return new McastConfig();
- }
- };
-
- /**
- * Segment Routing App ID.
- */
- public static final String APP_NAME = "org.onosproject.segmentrouting";
-
- /**
- * Minumum and maximum value of dummy VLAN ID to be allocated.
- */
- public static final int MIN_DUMMY_VLAN_ID = 2;
- public static final int MAX_DUMMY_VLAN_ID = 4093;
-
- private static final int DEFAULT_POOL_SIZE = 32;
-
- Instant lastEdgePortEvent = Instant.EPOCH;
-
- @Activate
- protected void activate(ComponentContext context) {
- appId = coreService.registerApplication(APP_NAME);
-
- mainEventExecutor = Executors.newSingleThreadScheduledExecutor(
- groupedThreads("onos/sr", "event-main-%d", log));
- hostEventExecutor = Executors.newSingleThreadScheduledExecutor(
- groupedThreads("onos/sr", "event-host-%d", log));
- routeEventExecutor = Executors.newSingleThreadScheduledExecutor(
- groupedThreads("onos/sr", "event-route-%d", log));
- mcastEventExecutor = Executors.newSingleThreadScheduledExecutor(
- groupedThreads("onos/sr", "event-mcast-%d", log));
- packetExecutor = Executors.newSingleThreadExecutor(groupedThreads("onos/sr", "packet-%d", log));
- neighborExecutor = Executors.newFixedThreadPool(DEFAULT_POOL_SIZE,
- groupedThreads("onos/sr", "neighbor-%d", log));
-
- log.debug("Creating EC map nsnextobjectivestore");
- EventuallyConsistentMapBuilder<DestinationSetNextObjectiveStoreKey, NextNeighbors>
- nsNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
- dsNextObjStore = nsNextObjMapBuilder
- .withName("nsnextobjectivestore")
- .withSerializer(createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
- log.trace("Current size {}", dsNextObjStore.size());
-
- log.debug("Creating EC map vlannextobjectivestore");
- EventuallyConsistentMapBuilder<VlanNextObjectiveStoreKey, Integer>
- vlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
- vlanNextObjStore = vlanNextObjMapBuilder
- .withName("vlannextobjectivestore")
- .withSerializer(createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
-
- log.debug("Creating EC map macvlannextobjectivestore");
- EventuallyConsistentMapBuilder<MacVlanNextObjectiveStoreKey, Integer>
- macVlanNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
- macVlanNextObjStore = macVlanNextObjMapBuilder
- .withName("macvlannextobjectivestore")
- .withSerializer(createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
-
- log.debug("Creating EC map subnetnextobjectivestore");
- EventuallyConsistentMapBuilder<PortNextObjectiveStoreKey, Integer>
- portNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
- portNextObjStore = portNextObjMapBuilder
- .withName("portnextobjectivestore")
- .withSerializer(createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
-
- EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
- storageService.eventuallyConsistentMapBuilder();
- tunnelStore = tunnelMapBuilder
- .withName("tunnelstore")
- .withSerializer(createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
-
- EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
- storageService.eventuallyConsistentMapBuilder();
- policyStore = policyMapBuilder
- .withName("policystore")
- .withSerializer(createSerializer())
- .withTimestampProvider((k, v) -> new WallClockTimestamp())
- .build();
-
- processor = new InternalPacketProcessor();
- linkListener = new InternalLinkListener();
- deviceListener = new InternalDeviceListener();
- appCfgHandler = new AppConfigHandler(this);
- mcastHandler = new McastHandler(this);
- hostHandler = new HostHandler(this);
- linkHandler = new LinkHandler(this);
- routeHandler = new RouteHandler(this);
- neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
- l2TunnelHandler = new DefaultL2TunnelHandler(this);
- topologyHandler = new TopologyHandler(this);
-
- compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
- "requestInterceptsEnabled", "false", false);
- compCfgService.preSetProperty("org.onosproject.net.neighbour.impl.NeighbourResolutionManager",
- "requestInterceptsEnabled", "false", false);
- compCfgService.preSetProperty("org.onosproject.dhcprelay.DhcpRelayManager",
- "arpEnabled", "false", false);
- compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
- "greedyLearningIpv6", "true", false);
- compCfgService.preSetProperty("org.onosproject.routing.cpr.ControlPlaneRedirectManager",
- "forceUnprovision", "true", false);
- compCfgService.preSetProperty("org.onosproject.routeservice.store.RouteStoreImpl",
- "distributed", "true", false);
- compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
- "multihomingEnabled", "true", false);
- compCfgService.preSetProperty("org.onosproject.provider.lldp.impl.LldpLinkProvider",
- "staleLinkAge", "15000", false);
- compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
- "allowDuplicateIps", "false", false);
- // For P4 switches
- compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
- "fallbackFlowPollFrequency", "4", false);
- compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
- "fallbackGroupPollFrequency", "3", false);
- compCfgService.registerProperties(getClass());
- modified(context);
-
- cfgService.addListener(cfgListener);
- cfgService.registerConfigFactory(deviceConfigFactory);
- cfgService.registerConfigFactory(appConfigFactory);
- cfgService.registerConfigFactory(mcastConfigFactory);
- log.info("Configuring network before adding listeners");
-
- cfgListener.configureNetwork();
-
- hostService.addListener(hostListener);
- packetService.addProcessor(processor, PacketProcessor.director(2));
- linkService.addListener(linkListener);
- deviceService.addListener(deviceListener);
- multicastRouteService.addListener(mcastListener);
- routeService.addListener(routeListener);
- topologyService.addListener(topologyListener);
- mastershipService.addListener(mastershipListener);
- clusterService.addListener(clusterListener);
-
- linkHandler.init();
- l2TunnelHandler.init();
-
- synchronized (networkConfigCompletionLock) {
- networkConfigCompletion.whenComplete((value, ex) -> {
- //setting to null for easier fall through
- networkConfigCompletion = null;
- //process all queued events
- queuedEvents.forEach(event -> {
- mainEventExecutor.execute(new InternalEventHandler(event));
- });
- });
- }
-
- log.info("Started");
- }
-
- KryoNamespace.Builder createSerializer() {
- return new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(DestinationSetNextObjectiveStoreKey.class,
- VlanNextObjectiveStoreKey.class,
- DestinationSet.class,
- DestinationSet.DestinationSetType.class,
- NextNeighbors.class,
- Tunnel.class,
- DefaultTunnel.class,
- Policy.class,
- TunnelPolicy.class,
- Policy.Type.class,
- PortNextObjectiveStoreKey.class,
- XConnectStoreKey.class,
- L2Tunnel.class,
- L2TunnelPolicy.class,
- DefaultL2Tunnel.class,
- DefaultL2TunnelPolicy.class,
- MacVlanNextObjectiveStoreKey.class
- );
- }
-
- @Deactivate
- protected void deactivate() {
- mainEventExecutor.shutdown();
- hostEventExecutor.shutdown();
- routeEventExecutor.shutdown();
- mcastEventExecutor.shutdown();
- packetExecutor.shutdown();
- neighborExecutor.shutdown();
-
- mainEventExecutor = null;
- hostEventExecutor = null;
- routeEventExecutor = null;
- mcastEventExecutor = null;
- packetExecutor = null;
- neighborExecutor = null;
-
- cfgService.removeListener(cfgListener);
- cfgService.unregisterConfigFactory(deviceConfigFactory);
- cfgService.unregisterConfigFactory(appConfigFactory);
- cfgService.unregisterConfigFactory(mcastConfigFactory);
- compCfgService.unregisterProperties(getClass(), false);
-
- hostService.removeListener(hostListener);
- packetService.removeProcessor(processor);
- linkService.removeListener(linkListener);
- deviceService.removeListener(deviceListener);
- multicastRouteService.removeListener(mcastListener);
- routeService.removeListener(routeListener);
- topologyService.removeListener(topologyListener);
- mastershipService.removeListener(mastershipListener);
- clusterService.removeListener(clusterListener);
-
- neighbourResolutionService.unregisterNeighbourHandlers(appId);
-
- processor = null;
- linkListener = null;
- deviceListener = null;
- groupHandlerMap.forEach((k, v) -> v.shutdown());
- groupHandlerMap.clear();
- defaultRoutingHandler.shutdown();
-
- dsNextObjStore.destroy();
- vlanNextObjStore.destroy();
- macVlanNextObjStore.destroy();
- portNextObjStore.destroy();
- tunnelStore.destroy();
- policyStore.destroy();
-
- mcastHandler.terminate();
- hostHandler.terminate();
- log.info("Stopped");
- }
-
- @Modified
- private void modified(ComponentContext context) {
- Dictionary<?, ?> properties = context.getProperties();
- if (properties == null) {
- return;
- }
-
- String strActiveProbing = Tools.get(properties, PROP_ACTIVE_PROBING);
- boolean expectActiveProbing = Boolean.parseBoolean(strActiveProbing);
- if (expectActiveProbing != activeProbing) {
- activeProbing = expectActiveProbing;
- log.info("{} active probing", activeProbing ? "Enabling" : "Disabling");
- }
-
-
- String strSymmetricProbing = Tools.get(properties, PROP_SYMMETRIC_PROBING);
- boolean expectSymmetricProbing = Boolean.parseBoolean(strSymmetricProbing);
- if (expectSymmetricProbing != symmetricProbing) {
- symmetricProbing = expectSymmetricProbing;
- log.info("{} symmetric probing", symmetricProbing ? "Enabling" : "Disabling");
- }
-
- String strSingleHomedDown = Tools.get(properties, PROP_SINGLE_HOMED_DOWN);
- boolean expectSingleHomedDown = Boolean.parseBoolean(strSingleHomedDown);
- if (expectSingleHomedDown != singleHomedDown) {
- singleHomedDown = expectSingleHomedDown;
- log.info("{} downing of single homed hosts for lost uplinks",
- singleHomedDown ? "Enabling" : "Disabling");
- if (singleHomedDown && linkHandler != null) {
- hostService.getHosts().forEach(host -> host.locations()
- .forEach(loc -> {
- if (interfaceService.isConfigured(loc)) {
- linkHandler.checkUplinksForHost(loc);
- }
- }));
- } else {
- log.warn("Disabling singleHomedDown does not re-enable already "
- + "downed ports for single-homed hosts");
- }
- }
-
- String strRespondToUnknownHosts = Tools.get(properties, PROP_RESPOND_TO_UNKNOWN_HOSTS);
- boolean expectRespondToUnknownHosts = Boolean.parseBoolean(strRespondToUnknownHosts);
- if (expectRespondToUnknownHosts != respondToUnknownHosts) {
- respondToUnknownHosts = expectRespondToUnknownHosts;
- log.info("{} responding to ARPs/NDPs from unknown hosts", respondToUnknownHosts ? "Enabling" : "Disabling");
- }
-
- String strRouteDoubleTaggedHosts = Tools.get(properties, PROP_ROUTE_DOUBLE_TAGGED_HOSTS);
- boolean expectRouteDoubleTaggedHosts = Boolean.parseBoolean(strRouteDoubleTaggedHosts);
- if (expectRouteDoubleTaggedHosts != routeDoubleTaggedHosts) {
- routeDoubleTaggedHosts = expectRouteDoubleTaggedHosts;
- log.info("{} routing for double tagged hosts", routeDoubleTaggedHosts ? "Enabling" : "Disabling");
-
- if (routeDoubleTaggedHosts) {
- hostHandler.populateAllDoubleTaggedHost();
- } else {
- hostHandler.revokeAllDoubleTaggedHost();
- }
- }
-
- String strDefaultInternalVlan = Tools.get(properties, PROP_DEFAULT_INTERNAL_VLAN);
- int defIntVlan = Integer.parseInt(strDefaultInternalVlan);
- if (defIntVlan != defaultInternalVlan) {
- if (canUseVlanId(defIntVlan)) {
- log.warn("Default internal vlan value changed from {} to {}.. "
- + "re-programming filtering rules, but NOT any groups already "
- + "created with the former value", defaultInternalVlan, defIntVlan);
- VlanId oldDefIntVlan = VlanId.vlanId((short) defaultInternalVlan);
- defaultInternalVlan = defIntVlan;
- routingRulePopulator
- .updateSpecialVlanFilteringRules(true, oldDefIntVlan,
- VlanId.vlanId((short) defIntVlan));
- } else {
- log.warn("Cannot change default internal vlan to unusable "
- + "value {}", defIntVlan);
- }
- }
-
- String strPwTxpVlan = Tools.get(properties, PROP_PW_TRANSPORT_VLAN);
- int pwTxpVlan = Integer.parseInt(strPwTxpVlan);
- if (pwTxpVlan != pwTransportVlan) {
- if (canUseVlanId(pwTxpVlan)) {
- log.warn("Pseudowire transport vlan value changed from {} to {}.. "
- + "re-programming filtering rules, but NOT any groups already "
- + "created with the former value", pwTransportVlan,
- pwTxpVlan);
- VlanId oldPwTxpVlan = VlanId.vlanId((short) pwTransportVlan);
- pwTransportVlan = pwTxpVlan;
- routingRulePopulator
- .updateSpecialVlanFilteringRules(false, oldPwTxpVlan,
- VlanId.vlanId((short) pwTxpVlan));
- } else {
- log.warn("Cannot change pseudowire transport vlan to unusable "
- + "value {}", pwTxpVlan);
- }
- }
-
- String strRouteSimplification = Tools.get(properties, PROP_ROUTE_SIMPLIFICATION);
- boolean expectRouteSimplification = Boolean.parseBoolean(strRouteSimplification);
- if (expectRouteSimplification != routeSimplification) {
- routeSimplification = expectRouteSimplification;
- log.info("{} route simplification", routeSimplification ? "Enabling" : "Disabling");
- }
-
- }
-
- /**
- * Returns true if given vlan id is not being used in the system currently,
- * either as one of the default system wide vlans or as one of the
- * configured interface vlans.
- *
- * @param vlanId given vlan id
- * @return true if vlan is not currently in use
- */
- public boolean canUseVlanId(int vlanId) {
- if (vlanId >= 4095 || vlanId <= 1) {
- log.error("Vlan id {} value is not in valid range 2 <--> 4094",
- vlanId);
- return false;
- }
-
- VlanId vid = VlanId.vlanId((short) vlanId);
- if (getDefaultInternalVlan().equals(vid) || getPwTransportVlan().equals(vid)) {
- log.warn("Vlan id {} value is already in use system-wide. "
- + "DefaultInternalVlan:{} PwTransportVlan:{} ", vlanId,
- getDefaultInternalVlan(), getPwTransportVlan());
- return false;
- }
-
- if (interfaceService.inUse(vid)) {
- log.warn("Vlan id {} value is already in use on a configured "
- + "interface in the system", vlanId);
- return false;
- }
- return true;
- }
-
- /**
- * Returns the VlanId assigned internally by default to unconfigured ports.
- *
- * @return the default internal vlan id
- */
- public VlanId getDefaultInternalVlan() {
- return VlanId.vlanId((short) defaultInternalVlan);
- }
-
- /**
- * Returns the Vlan id used to transport pseudowire traffic across the
- * network.
- *
- * @return the pseudowire transport vlan id
- */
- public VlanId getPwTransportVlan() {
- return VlanId.vlanId((short) pwTransportVlan);
- }
-
- @Override
- public List<Tunnel> getTunnels() {
- return tunnelHandler.getTunnels();
- }
-
- @Override
- public TunnelHandler.Result createTunnel(Tunnel tunnel) {
- return tunnelHandler.createTunnel(tunnel);
- }
-
- @Override
- public TunnelHandler.Result removeTunnel(Tunnel tunnel) {
- for (Policy policy: policyHandler.getPolicies()) {
- if (policy.type() == Policy.Type.TUNNEL_FLOW) {
- TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
- if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
- log.warn("Cannot remove the tunnel used by a policy");
- return TunnelHandler.Result.TUNNEL_IN_USE;
- }
- }
- }
- return tunnelHandler.removeTunnel(tunnel);
- }
-
- @Override
- public PolicyHandler.Result removePolicy(Policy policy) {
- return policyHandler.removePolicy(policy);
- }
-
- @Override
- public PolicyHandler.Result createPolicy(Policy policy) {
- return policyHandler.createPolicy(policy);
- }
-
- @Override
- public List<Policy> getPolicies() {
- return policyHandler.getPolicies();
- }
-
- @Override
- public Set<L2TunnelDescription> getL2TunnelDescriptions(boolean pending) {
- return l2TunnelHandler.getL2Descriptions(pending);
- }
-
- @Override
- public List<L2Tunnel> getL2Tunnels() {
- return l2TunnelHandler.getL2Tunnels();
- }
-
- @Override
- public List<L2TunnelPolicy> getL2Policies() {
- return l2TunnelHandler.getL2Policies();
- }
-
- @Override
- @Deprecated
- public L2TunnelHandler.Result addPseudowiresBulk(List<DefaultL2TunnelDescription> bulkPseudowires) {
-
- // get both added and pending pseudowires
- List<L2TunnelDescription> pseudowires = new ArrayList<>();
- pseudowires.addAll(l2TunnelHandler.getL2Descriptions(false));
- pseudowires.addAll(l2TunnelHandler.getL2Descriptions(true));
- pseudowires.addAll(bulkPseudowires);
-
- Set<L2TunnelDescription> newPseudowires = new HashSet(bulkPseudowires);
-
- L2TunnelHandler.Result retRes = L2TunnelHandler.Result.SUCCESS;
- L2TunnelHandler.Result res;
- for (DefaultL2TunnelDescription pw : bulkPseudowires) {
- res = addPseudowire(pw);
- if (res != L2TunnelHandler.Result.SUCCESS) {
- log.error("Pseudowire with id {} can not be instantiated !", res);
- retRes = res;
- }
- }
-
- return retRes;
- }
-
- @Override
- public L2TunnelHandler.Result addPseudowire(L2TunnelDescription l2TunnelDescription) {
- return l2TunnelHandler.deployPseudowire(l2TunnelDescription);
- }
-
- @Override
- public L2TunnelHandler.Result removePseudowire(Integer pwId) {
- return l2TunnelHandler.tearDownPseudowire(pwId);
- }
-
- @Override
- public void rerouteNetwork() {
- cfgListener.configureNetwork();
- }
-
- @Override
- public Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap() {
- Map<DeviceId, Set<IpPrefix>> deviceSubnetMap = Maps.newHashMap();
- deviceConfiguration.getRouters().forEach(device ->
- deviceSubnetMap.put(device, deviceConfiguration.getSubnets(device)));
- return deviceSubnetMap;
- }
-
-
- @Override
- public ImmutableMap<DeviceId, EcmpShortestPathGraph> getCurrentEcmpSpg() {
- if (defaultRoutingHandler != null) {
- return defaultRoutingHandler.getCurrentEmcpSpgMap();
- } else {
- return null;
- }
- }
-
- @Override
- public ImmutableMap<DestinationSetNextObjectiveStoreKey, NextNeighbors> getDstNextObjStore() {
- if (dsNextObjStore != null) {
- return ImmutableMap.copyOf(dsNextObjStore.entrySet());
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public ImmutableMap<VlanNextObjectiveStoreKey, Integer> getVlanNextObjStore() {
- if (vlanNextObjStore != null) {
- return ImmutableMap.copyOf(vlanNextObjStore.entrySet());
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public ImmutableMap<MacVlanNextObjectiveStoreKey, Integer> getMacVlanNextObjStore() {
- if (macVlanNextObjStore != null) {
- return ImmutableMap.copyOf(macVlanNextObjStore.entrySet());
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public ImmutableMap<PortNextObjectiveStoreKey, Integer> getPortNextObjStore() {
- if (portNextObjStore != null) {
- return ImmutableMap.copyOf(portNextObjStore.entrySet());
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public ImmutableMap<String, NextObjective> getPwInitNext() {
- if (l2TunnelHandler != null) {
- return l2TunnelHandler.getInitNext();
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public ImmutableMap<String, NextObjective> getPwTermNext() {
- if (l2TunnelHandler != null) {
- return l2TunnelHandler.getTermNext();
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public void invalidateNextObj(int nextId) {
- if (dsNextObjStore != null) {
- dsNextObjStore.entrySet().forEach(e -> {
- if (e.getValue().nextId() == nextId) {
- dsNextObjStore.remove(e.getKey());
- }
- });
- }
- if (vlanNextObjStore != null) {
- vlanNextObjStore.entrySet().forEach(e -> {
- if (e.getValue() == nextId) {
- vlanNextObjStore.remove(e.getKey());
- }
- });
- }
- if (macVlanNextObjStore != null) {
- macVlanNextObjStore.entrySet().forEach(e -> {
- if (e.getValue() == nextId) {
- macVlanNextObjStore.remove(e.getKey());
- }
- });
- }
- if (portNextObjStore != null) {
- portNextObjStore.entrySet().forEach(e -> {
- if (e.getValue() == nextId) {
- portNextObjStore.remove(e.getKey());
- }
- });
- }
- if (mcastHandler != null) {
- mcastHandler.removeNextId(nextId);
- }
- if (l2TunnelHandler != null) {
- l2TunnelHandler.removeNextId(nextId);
- }
- if (xconnectService != null) {
- xconnectService.removeNextId(nextId);
- }
- }
-
- @Override
- public void verifyGroups(DeviceId id) {
- DefaultGroupHandler gh = groupHandlerMap.get(id);
- if (gh != null) {
- gh.triggerBucketCorrector();
- }
- }
-
- @Override
- public ImmutableMap<Link, Boolean> getSeenLinks() {
- return linkHandler.getSeenLinks();
- }
-
- @Override
- public ImmutableMap<DeviceId, Set<PortNumber>> getDownedPortState() {
- return linkHandler.getDownedPorts();
- }
-
- @Override
- public Map<McastStoreKey, Integer> getMcastNextIds(IpAddress mcastIp) {
- return mcastHandler.getNextIds(mcastIp);
- }
-
- @Override
- public Map<McastRoleStoreKey, McastRole> getMcastRoles(IpAddress mcastIp, ConnectPoint sourcecp) {
- return mcastHandler.getMcastRoles(mcastIp, sourcecp);
- }
-
- @Override
- public Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
- ConnectPoint sourcecp) {
- return mcastHandler.getMcastTrees(mcastIp, sourcecp);
- }
-
- @Override
- public Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp) {
- return mcastHandler.getMcastLeaders(mcastIp);
- }
-
- @Override
- public Map<DeviceId, List<McastFilteringObjStoreKey>> getMcastFilters() {
- return mcastHandler.getMcastFilters();
- }
-
- @Override
- public Map<Set<DeviceId>, NodeId> getShouldProgram() {
- return defaultRoutingHandler == null ? ImmutableMap.of() :
- ImmutableMap.copyOf(defaultRoutingHandler.shouldProgram);
- }
-
- @Override
- public Map<DeviceId, Boolean> getShouldProgramCache() {
- return defaultRoutingHandler == null ? ImmutableMap.of() :
- ImmutableMap.copyOf(defaultRoutingHandler.shouldProgramCache);
- }
-
- @Override
- public boolean shouldProgram(DeviceId deviceId) {
- return defaultRoutingHandler.shouldProgram(deviceId);
- }
-
- @Override
- public boolean isRoutingStable() {
- return defaultRoutingHandler.isRoutingStable();
- }
-
- @Override
- public void initHost(DeviceId deviceId) {
- hostEventExecutor.execute(() -> hostHandler.init(deviceId));
- }
-
- @Override
- public void initRoute(DeviceId deviceId) {
- routeEventExecutor.execute(() -> routeHandler.init(deviceId));
- }
-
- @Override
- public ApplicationId appId() {
- return appId;
- }
-
- /**
- * Returns the device configuration.
- *
- * @return device configuration
- */
- public DeviceConfiguration deviceConfiguration() {
- return deviceConfiguration;
- }
-
- /**
- * Per device next objective ID store with (device id + destination set) as key.
- * Used to keep track on MPLS group information.
- *
- * @return next objective ID store
- */
- public EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
- dsNextObjStore() {
- return dsNextObjStore;
- }
-
- /**
- * Per device next objective ID store with (device id + vlanid) as key.
- * Used to keep track on L2 flood group information.
- *
- * @return vlan next object store
- */
- public EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer> vlanNextObjStore() {
- return vlanNextObjStore;
- }
-
- /**
- * Per device next objective ID store with (device id + MAC address + vlan) as key.
- * Used to keep track on L3 Unicast group information for indirect hosts.
- *
- * @return mac vlan next object store
- */
- public EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer> macVlanNextObjStore() {
- return macVlanNextObjStore;
- }
-
- /**
- * Per device next objective ID store with (device id + port + treatment + meta) as key.
- * Used to keep track on L2 interface group and L3 unicast group information for direct hosts.
- *
- * @return port next object store.
- */
- public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer> portNextObjStore() {
- return portNextObjStore;
- }
-
- /**
- * Returns the MPLS-ECMP configuration which indicates whether ECMP on
- * labeled packets should be programmed or not.
- *
- * @return MPLS-ECMP value
- */
- public boolean getMplsEcmp() {
- SegmentRoutingAppConfig segmentRoutingAppConfig = cfgService
- .getConfig(this.appId, SegmentRoutingAppConfig.class);
- return segmentRoutingAppConfig != null && segmentRoutingAppConfig.mplsEcmp();
- }
-
- /**
- * Returns the tunnel object with the tunnel ID.
- *
- * @param tunnelId Tunnel ID
- * @return Tunnel reference
- */
- public Tunnel getTunnel(String tunnelId) {
- return tunnelHandler.getTunnel(tunnelId);
- }
-
- @Override
- public VlanId getInternalVlanId(ConnectPoint connectPoint) {
- VlanId untaggedVlanId = interfaceService.getUntaggedVlanId(connectPoint);
- VlanId nativeVlanId = interfaceService.getNativeVlanId(connectPoint);
- return untaggedVlanId != null ? untaggedVlanId : nativeVlanId;
- }
-
- @Override
- public Optional<DeviceId> getPairDeviceId(DeviceId deviceId) {
- SegmentRoutingDeviceConfig deviceConfig =
- cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
- return Optional.ofNullable(deviceConfig).map(SegmentRoutingDeviceConfig::pairDeviceId);
- }
-
- @Override
- public Optional<PortNumber> getPairLocalPort(DeviceId deviceId) {
- SegmentRoutingDeviceConfig deviceConfig =
- cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
- return Optional.ofNullable(deviceConfig).map(SegmentRoutingDeviceConfig::pairLocalPort);
- }
-
- @Override
- public Set<PortNumber> getInfraPorts(DeviceId deviceId) {
- return deviceService.getPorts(deviceId).stream()
- .map(port -> new ConnectPoint(port.element().id(), port.number()))
- .filter(cp -> interfaceService.getInterfacesByPort(cp).isEmpty())
- .map(ConnectPoint::port)
- .collect(Collectors.toSet());
- }
-
- @Override
- public Set<PortNumber> getEdgePorts(DeviceId deviceId) {
- return deviceService.getPorts(deviceId).stream()
- .map(port -> new ConnectPoint(port.element().id(), port.number()))
- .filter(cp -> !interfaceService.getInterfacesByPort(cp).isEmpty() &&
- !cp.port().equals(getPairLocalPort(deviceId).orElse(null)))
- .map(ConnectPoint::port)
- .collect(Collectors.toSet());
- }
-
- /**
- * Returns locations of given resolved route.
- *
- * @param resolvedRoute resolved route
- * @return locations of nexthop. Might be empty if next hop is not found
- */
- public Set<ConnectPoint> nextHopLocations(ResolvedRoute resolvedRoute) {
- HostId hostId = HostId.hostId(resolvedRoute.nextHopMac(), resolvedRoute.nextHopVlan());
- return Optional.ofNullable(hostService.getHost(hostId))
- .map(Host::locations).orElse(Sets.newHashSet())
- .stream().map(l -> (ConnectPoint) l).collect(Collectors.toSet());
- }
-
- /**
- * Returns vlan port map of given device.
- *
- * @param deviceId device id
- * @return vlan-port multimap
- */
- public Multimap<VlanId, PortNumber> getVlanPortMap(DeviceId deviceId) {
- HashMultimap<VlanId, PortNumber> vlanPortMap = HashMultimap.create();
-
- interfaceService.getInterfaces().stream()
- .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
- .forEach(intf -> {
- vlanPortMap.put(intf.vlanUntagged(), intf.connectPoint().port());
- intf.vlanTagged().forEach(vlanTagged ->
- vlanPortMap.put(vlanTagged, intf.connectPoint().port())
- );
- vlanPortMap.put(intf.vlanNative(), intf.connectPoint().port());
- });
- vlanPortMap.removeAll(VlanId.NONE);
-
- return vlanPortMap;
- }
-
- /**
- * Returns the next objective ID for the given vlan id. It is expected
- * that the next-objective has been pre-created from configuration.
- *
- * @param deviceId Device ID
- * @param vlanId VLAN ID
- * @return next objective ID or -1 if it was not found
- */
- int getVlanNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
- if (groupHandlerMap.get(deviceId) != null) {
- log.trace("getVlanNextObjectiveId query in device {}", deviceId);
- return groupHandlerMap.get(deviceId).getVlanNextObjectiveId(vlanId);
- } else {
- log.warn("getVlanNextObjectiveId query - groupHandler for "
- + "device {} not found", deviceId);
- return -1;
- }
- }
-
- /**
- * Returns the next objective ID for the given portNumber, given the treatment.
- * There could be multiple different treatments to the same outport, which
- * would result in different objectives. If the next object does not exist,
- * and should be created, a new one is created and its id is returned.
- *
- * @param deviceId Device ID
- * @param portNum port number on device for which NextObjective is queried
- * @param treatment the actions to apply on the packets (should include outport)
- * @param meta metadata passed into the creation of a Next Objective if necessary
- * @param createIfMissing true if a next object should be created if not found
- * @return next objective ID or -1 if an error occurred during retrieval or creation
- */
- public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
- TrafficTreatment treatment,
- TrafficSelector meta,
- boolean createIfMissing) {
- DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
- if (ghdlr != null) {
- return ghdlr.getPortNextObjectiveId(portNum, treatment, meta, createIfMissing);
- } else {
- log.warn("getPortNextObjectiveId query - groupHandler for device {}"
- + " not found", deviceId);
- return -1;
- }
- }
-
- /**
- * Returns the next Objective ID for the given mac and vlan, given the treatment.
- * There could be multiple different treatments to the same outport, which
- * would result in different objectives. If the next object does not exist,
- * and should be created, a new one is created and its id is returned.
- *
- * @param deviceId Device ID
- * @param macAddr mac of host for which Next ID is required.
- * @param vlanId vlan of host for which Next ID is required.
- * @param port port with which to create the Next Obj.
- * @param createIfMissing true if a next object should be created if not found
- * @return next objective ID or -1 if an error occurred during retrieval or creation
- */
- public int getMacVlanNextObjectiveId(DeviceId deviceId, MacAddress macAddr, VlanId vlanId,
- PortNumber port, boolean createIfMissing) {
- DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
- if (ghdlr != null) {
- return ghdlr.getMacVlanNextObjectiveId(macAddr, vlanId, port, createIfMissing);
- } else {
- log.warn("getMacVlanNextObjectiveId query - groupHandler for device {}"
- + " not found", deviceId);
- return -1;
- }
- }
-
- /**
- * Updates the next objective for the given nextId .
- *
- * @param deviceId Device ID
- * @param hostMac mac of host for which Next obj is to be updated.
- * @param hostVlanId vlan of host for which Next obj is to be updated.
- * @param port port with which to update the Next Obj.
- * @param nextId of Next Obj which needs to be updated.
- */
- public void updateMacVlanTreatment(DeviceId deviceId, MacAddress hostMac,
- VlanId hostVlanId, PortNumber port, int nextId) {
- // Check if we are the king of this device
- // just one instance should perform this update
- if (!defaultRoutingHandler.shouldProgram(deviceId)) {
- log.debug("This instance is not handling the routing towards the "
- + "device {}", deviceId);
- return;
- }
- // Get the handler and perform the update
- DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
- if (ghdlr != null) {
- ghdlr.updateL3UcastGroupBucket(hostMac, hostVlanId, port, nextId);
- } else {
- log.warn("updateL3UcastGroupBucket query - groupHandler for device {}"
- + " not found", deviceId);
- }
- }
-
-
- /**
- * Returns the group handler object for the specified device id.
- *
- * @param devId the device identifier
- * @return the groupHandler object for the device id, or null if not found
- */
- DefaultGroupHandler getGroupHandler(DeviceId devId) {
- return groupHandlerMap.get(devId);
- }
-
- /**
- * Returns the default routing handler object.
- *
- * @return the default routing handler object
- */
- public DefaultRoutingHandler getRoutingHandler() {
- return defaultRoutingHandler;
- }
-
- private class InternalPacketProcessor implements PacketProcessor {
- @Override
- public void process(PacketContext context) {
- packetExecutor.execute(() -> processPacketInternal(context));
- }
-
- private void processPacketInternal(PacketContext context) {
- if (context.isHandled()) {
- return;
- }
-
- InboundPacket pkt = context.inPacket();
- Ethernet ethernet = pkt.parsed();
-
- if (ethernet == null) {
- return;
- }
-
- log.trace("Rcvd pktin from {}: {}", context.inPacket().receivedFrom(),
- ethernet);
- if (ethernet.getEtherType() == TYPE_ARP) {
- log.warn("Received unexpected ARP packet on {}",
- context.inPacket().receivedFrom());
- log.trace("{}", ethernet);
- return;
- } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
- IPv4 ipv4Packet = (IPv4) ethernet.getPayload();
- //ipHandler.addToPacketBuffer(ipv4Packet);
- if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) {
- icmpHandler.processIcmp(ethernet, pkt.receivedFrom());
- } else {
- // NOTE: We don't support IP learning at this moment so this
- // is not necessary. Also it causes duplication of DHCP packets.
- // ipHandler.processPacketIn(ipv4Packet, pkt.receivedFrom());
- }
- } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV6) {
- IPv6 ipv6Packet = (IPv6) ethernet.getPayload();
- //ipHandler.addToPacketBuffer(ipv6Packet);
- // We deal with the packet only if the packet is a ICMP6 ECHO/REPLY
- if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
- ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
- if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST ||
- icmp6Packet.getIcmpType() == ICMP6.ECHO_REPLY) {
- icmpHandler.processIcmpv6(ethernet, pkt.receivedFrom());
- } else {
- log.trace("Received ICMPv6 0x{} - not handled",
- Integer.toHexString(icmp6Packet.getIcmpType() & 0xff));
- }
- } else {
- // NOTE: We don't support IP learning at this moment so this
- // is not necessary. Also it causes duplication of DHCPv6 packets.
- // ipHandler.processPacketIn(ipv6Packet, pkt.receivedFrom());
- }
- }
- }
- }
-
- private class InternalEventHandler implements Runnable {
- private Event event;
-
- InternalEventHandler(Event event) {
- this.event = event;
- }
-
- @Override
- public void run() {
- try {
- // TODO We should also change SR routing and PW to listen to TopologyEvents
- if (event.type() == LinkEvent.Type.LINK_ADDED ||
- event.type() == LinkEvent.Type.LINK_UPDATED) {
- linkHandler.processLinkAdded((Link) event.subject());
- } else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
- linkHandler.processLinkRemoved((Link) event.subject());
- } else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
- event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
- event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
- DeviceId deviceId = ((Device) event.subject()).id();
- if (deviceService.isAvailable(deviceId)) {
- log.info("** DEVICE UP Processing device event {} "
- + "for available device {}",
- event.type(), ((Device) event.subject()).id());
- processDeviceAdded((Device) event.subject());
- } else {
- if (event.type() == DeviceEvent.Type.DEVICE_ADDED) {
- // Note: For p4 devices, the device will be added but unavailable at the beginning.
- // The device will later on being marked as available once the pipeline is pushed
- // to the device.
- log.info("** DEVICE ADDED but unavailable. Ignore");
- return;
- }
- log.info(" ** DEVICE DOWN Processing device event {}"
- + " for unavailable device {}",
- event.type(), ((Device) event.subject()).id());
- processDeviceRemoved((Device) event.subject());
- }
- } else if (event.type() == DeviceEvent.Type.PORT_ADDED) {
- // typically these calls come when device is added first time
- // so port filtering rules are handled at the device_added event.
- // port added calls represent all ports on the device,
- // enabled or not.
- log.trace("** PORT ADDED {}/{} -> {}",
- ((DeviceEvent) event).subject().id(),
- ((DeviceEvent) event).port().number(),
- event.type());
- } else if (event.type() == DeviceEvent.Type.PORT_UPDATED) {
- // these calls happen for every subsequent event
- // ports enabled, disabled, switch goes away, comes back
- log.info("** PORT UPDATED {}/{} -> {}",
- event.subject(),
- ((DeviceEvent) event).port(),
- event.type());
- processPortUpdatedInternal(((Device) event.subject()),
- ((DeviceEvent) event).port());
- mcastHandler.processPortUpdate(((Device) event.subject()),
- ((DeviceEvent) event).port());
- } else if (event.type() == TopologyEvent.Type.TOPOLOGY_CHANGED) {
- // Process topology event, needed for all modules relying on
- // topology service for path computation
- TopologyEvent topologyEvent = (TopologyEvent) event;
- log.info("Processing topology event {}, topology age {}, reasons {}",
- event.type(), topologyEvent.subject().time(),
- topologyEvent.reasons().size());
- topologyHandler.processTopologyChange(topologyEvent.reasons());
- } else if (event.type() == HostEvent.Type.HOST_ADDED) {
- hostHandler.processHostAddedEvent((HostEvent) event);
- } else if (event.type() == HostEvent.Type.HOST_MOVED) {
- hostHandler.processHostMovedEvent((HostEvent) event);
- routeHandler.processHostMovedEvent((HostEvent) event);
- } else if (event.type() == HostEvent.Type.HOST_AUX_MOVED) {
- hostHandler.processHostMovedEvent((HostEvent) event);
- // TODO RouteHandler also needs to process this event in order to
- // support nexthops that has auxLocations
- } else if (event.type() == HostEvent.Type.HOST_REMOVED) {
- hostHandler.processHostRemovedEvent((HostEvent) event);
- } else if (event.type() == HostEvent.Type.HOST_UPDATED) {
- hostHandler.processHostUpdatedEvent((HostEvent) event);
- } else if (event.type() == RouteEvent.Type.ROUTE_ADDED) {
- routeHandler.processRouteAdded((RouteEvent) event);
- } else if (event.type() == RouteEvent.Type.ROUTE_UPDATED) {
- routeHandler.processRouteUpdated((RouteEvent) event);
- } else if (event.type() == RouteEvent.Type.ROUTE_REMOVED) {
- routeHandler.processRouteRemoved((RouteEvent) event);
- } else if (event.type() == RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED) {
- routeHandler.processAlternativeRoutesChanged((RouteEvent) event);
- } else if (event.type() == McastEvent.Type.SOURCES_ADDED ||
- event.type() == McastEvent.Type.SOURCES_REMOVED ||
- event.type() == McastEvent.Type.SINKS_ADDED ||
- event.type() == McastEvent.Type.SINKS_REMOVED ||
- event.type() == McastEvent.Type.ROUTE_ADDED ||
- event.type() == McastEvent.Type.ROUTE_REMOVED) {
- mcastHandler.processMcastEvent((McastEvent) event);
- } else if (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
- NetworkConfigEvent netcfgEvent = (NetworkConfigEvent) event;
- Class configClass = netcfgEvent.configClass();
- if (configClass.equals(SegmentRoutingAppConfig.class)) {
- appCfgHandler.processAppConfigAdded(netcfgEvent);
- log.info("App config event .. configuring network");
- cfgListener.configureNetwork();
- } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
- log.info("Segment Routing Device Config added for {}", event.subject());
- cfgListener.configureNetwork();
- } else if (configClass.equals(InterfaceConfig.class)) {
- log.info("Interface Config added for {}", event.subject());
- cfgListener.configureNetwork();
- } else {
- log.error("Unhandled config class: {}", configClass);
- }
- } else if (event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) {
- NetworkConfigEvent netcfgEvent = (NetworkConfigEvent) event;
- Class configClass = netcfgEvent.configClass();
- if (configClass.equals(SegmentRoutingAppConfig.class)) {
- appCfgHandler.processAppConfigUpdated(netcfgEvent);
- log.info("App config event .. configuring network");
- cfgListener.configureNetwork();
- } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
- log.info("Segment Routing Device Config updated for {}", event.subject());
- createOrUpdateDeviceConfiguration();
- } else if (configClass.equals(InterfaceConfig.class)) {
- log.info("Interface Config updated for {}", event.subject());
- createOrUpdateDeviceConfiguration();
- updateInterface((InterfaceConfig) netcfgEvent.config().get(),
- (InterfaceConfig) netcfgEvent.prevConfig().get());
- } else {
- log.error("Unhandled config class: {}", configClass);
- }
- } else if (event.type() == NetworkConfigEvent.Type.CONFIG_REMOVED) {
- NetworkConfigEvent netcfgEvent = (NetworkConfigEvent) event;
- Class configClass = netcfgEvent.configClass();
- if (configClass.equals(SegmentRoutingAppConfig.class)) {
- appCfgHandler.processAppConfigRemoved(netcfgEvent);
- log.info("App config event .. configuring network");
- cfgListener.configureNetwork();
- } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
- // TODO Handle sr device config removal
- log.info("SegmentRoutingDeviceConfig removal is not handled in current implementation");
- } else if (configClass.equals(InterfaceConfig.class)) {
- // TODO Handle interface removal
- log.info("InterfaceConfig removal is not handled in current implementation");
- } else {
- log.error("Unhandled config class: {}", configClass);
- }
- } else if (event.type() == MastershipEvent.Type.MASTER_CHANGED) {
- MastershipEvent me = (MastershipEvent) event;
- DeviceId deviceId = me.subject();
- Optional<DeviceId> pairDeviceId = getPairDeviceId(deviceId);
- log.info(" ** MASTERSHIP CHANGED Invalidating shouldProgram cache"
- + " for {}/pair={} due to change", deviceId, pairDeviceId);
- defaultRoutingHandler.invalidateShouldProgramCache(deviceId);
- pairDeviceId.ifPresent(defaultRoutingHandler::invalidateShouldProgramCache);
- defaultRoutingHandler.checkFullRerouteForMasterChange(deviceId, me);
- } else {
- log.warn("Unhandled event type: {}", event.type());
- }
- } catch (Exception e) {
- log.error("SegmentRouting event handler thread thrown an exception: {}",
- e.getMessage(), e);
- }
- }
- }
-
- void processDeviceAdded(Device device) {
- log.info("** DEVICE ADDED with ID {}", device.id());
-
- // NOTE: Punt ARP/NDP even when the device is not configured.
- // Host learning without network config is required for CORD config generator.
- routingRulePopulator.populateIpPunts(device.id());
- routingRulePopulator.populateArpNdpPunts(device.id());
-
- if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
- log.warn("Device configuration unavailable. Device {} will be "
- + "processed after configuration.", device.id());
- return;
- }
- processDeviceAddedInternal(device.id());
- }
-
- private void processDeviceAddedInternal(DeviceId deviceId) {
- // Irrespective of whether the local is a MASTER or not for this device,
- // we need to create a SR-group-handler instance. This is because in a
- // multi-instance setup, any instance can initiate forwarding/next-objectives
- // for any switch (even if this instance is a SLAVE or not even connected
- // to the switch). To handle this, a default-group-handler instance is necessary
- // per switch.
- log.debug("Current groupHandlerMap devs: {}", groupHandlerMap.keySet());
- if (groupHandlerMap.get(deviceId) == null) {
- DefaultGroupHandler groupHandler;
- try {
- groupHandler = DefaultGroupHandler.
- createGroupHandler(deviceId,
- appId,
- deviceConfiguration,
- linkService,
- flowObjectiveService,
- this);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting processDeviceAdded.");
- return;
- }
- log.debug("updating groupHandlerMap with new grpHdlr for device: {}",
- deviceId);
- groupHandlerMap.put(deviceId, groupHandler);
- }
-
- if (mastershipService.isLocalMaster(deviceId)) {
- defaultRoutingHandler.populatePortAddressingRules(deviceId);
- defaultRoutingHandler.purgeSeenBeforeRoutes(deviceId);
- DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
- groupHandler.createGroupsFromVlanConfig();
- routingRulePopulator.populateSubnetBroadcastRule(deviceId);
- phasedRecoveryService.init(deviceId);
- }
-
- appCfgHandler.init(deviceId);
- }
-
- private void processDeviceRemoved(Device device) {
- dsNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(device.id()))
- .forEach(entry -> dsNextObjStore.remove(entry.getKey()));
- vlanNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(device.id()))
- .forEach(entry -> vlanNextObjStore.remove(entry.getKey()));
- macVlanNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(device.id()))
- .forEach(entry -> macVlanNextObjStore.remove(entry.getKey()));
- portNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(device.id()))
- .forEach(entry -> portNextObjStore.remove(entry.getKey()));
- linkHandler.processDeviceRemoved(device);
-
- DefaultGroupHandler gh = groupHandlerMap.remove(device.id());
- if (gh != null) {
- gh.shutdown();
- }
- // Note that a switch going down is associated with all of its links
- // going down as well, but it is treated as a single switch down event
- // while the link-downs are ignored. We cannot rely on the ordering of
- // events - i.e we cannot expect all link-downs to come before the
- // switch down - so we purge all seen-links for the switch before
- // handling route-path changes for the switch-down
- defaultRoutingHandler
- .populateRoutingRulesForLinkStatusChange(null, null, device.id(), true);
- defaultRoutingHandler.purgeEcmpGraph(device.id());
-
- // Cleanup all internal groupHandler stores for this device. Should be
- // done after all rerouting or rehashing has been completed
- groupHandlerMap.entrySet()
- .forEach(entry -> entry.getValue().cleanUpForNeighborDown(device.id()));
-
- phasedRecoveryService.reset(device.id());
- }
-
- /**
- * Purge the destinationSet nextObjective store of entries with this device
- * as key. Erases app-level knowledge of hashed groups in this device.
- *
- * @param devId the device identifier
- */
- void purgeHashedNextObjectiveStore(DeviceId devId) {
- log.debug("Purging hashed next-obj store for dev:{}", devId);
- dsNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(devId))
- .forEach(entry -> dsNextObjStore.remove(entry.getKey()));
- }
-
- private void processPortUpdatedInternal(Device device, Port port) {
- if (deviceConfiguration == null || !deviceConfiguration.isConfigured(device.id())) {
- log.warn("Device configuration uploading. Not handling port event for"
- + "dev: {} port: {}", device.id(), port.number());
- return;
- }
-
- if (interfaceService.isConfigured(new ConnectPoint(device.id(), port.number()))) {
- lastEdgePortEvent = Instant.now();
- }
-
- if (!mastershipService.isLocalMaster(device.id())) {
- log.debug("Not master for dev:{} .. not handling port updated event"
- + "for port {}", device.id(), port.number());
- return;
- }
- processPortUpdated(device.id(), port);
- }
-
- /**
- * Adds or remove filtering rules for the given switchport. If switchport is
- * an edge facing port, additionally handles host probing and broadcast
- * rules. Must be called by local master of device.
- *
- * @param deviceId the device identifier
- * @param port the port to update
- */
- void processPortUpdated(DeviceId deviceId, Port port) {
- // first we handle filtering rules associated with the port
- if (port.isEnabled()) {
- log.info("Switchport {}/{} enabled..programming filters",
- deviceId, port.number());
- routingRulePopulator.processSinglePortFilters(deviceId, port.number(), true);
- } else {
- log.info("Switchport {}/{} disabled..removing filters",
- deviceId, port.number());
- routingRulePopulator.processSinglePortFilters(deviceId, port.number(), false);
- }
-
- // portUpdated calls are for ports that have gone down or up. For switch
- // to switch ports, link-events should take care of any re-routing or
- // group editing necessary for port up/down. Here we only process edge ports
- // that are already configured.
- ConnectPoint cp = new ConnectPoint(deviceId, port.number());
- VlanId untaggedVlan = interfaceService.getUntaggedVlanId(cp);
- VlanId nativeVlan = interfaceService.getNativeVlanId(cp);
- Set<VlanId> taggedVlans = interfaceService.getTaggedVlanId(cp);
-
- if (untaggedVlan == null && nativeVlan == null && taggedVlans.isEmpty()) {
- log.debug("Not handling port updated event for non-edge port (unconfigured) "
- + "dev/port: {}/{}", deviceId, port.number());
- return;
- }
- if (untaggedVlan != null) {
- processEdgePort(deviceId, port, untaggedVlan, true);
- }
- if (nativeVlan != null) {
- processEdgePort(deviceId, port, nativeVlan, true);
- }
- if (!taggedVlans.isEmpty()) {
- taggedVlans.forEach(tag -> processEdgePort(deviceId, port, tag, false));
- }
- }
-
- private void processEdgePort(DeviceId deviceId, Port port, VlanId vlanId,
- boolean popVlan) {
- boolean portUp = port.isEnabled();
- if (portUp) {
- log.info("Device:EdgePort {}:{} is enabled in vlan: {}", deviceId,
- port.number(), vlanId);
- hostEventExecutor.execute(() -> hostHandler.processPortUp(new ConnectPoint(deviceId, port.number())));
- } else {
- log.info("Device:EdgePort {}:{} is disabled in vlan: {}", deviceId,
- port.number(), vlanId);
- }
-
- DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
- if (groupHandler != null) {
- groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
- } else {
- log.warn("Group handler not found for dev:{}. Not handling edge port"
- + " {} event for port:{}", deviceId,
- (portUp) ? "UP" : "DOWN", port.number());
- }
- }
-
- private void createOrUpdateDeviceConfiguration() {
- if (deviceConfiguration == null) {
- log.info("Creating new DeviceConfiguration");
- deviceConfiguration = new DeviceConfiguration(this);
- } else {
- log.info("Updating DeviceConfiguration");
- deviceConfiguration.updateConfig();
- }
- }
-
- private void createOrUpdateDefaultRoutingHandler() {
- if (defaultRoutingHandler == null) {
- log.info("Creating new DefaultRoutingHandler");
- defaultRoutingHandler = new DefaultRoutingHandler(this);
- } else {
- log.info("Updating DefaultRoutingHandler");
- defaultRoutingHandler.update(this);
- }
- }
-
- /**
- * Registers the given connect point with the NRS, this is necessary
- * to receive the NDP and ARP packets from the NRS.
- *
- * @param portToRegister connect point to register
- */
- public void registerConnectPoint(ConnectPoint portToRegister) {
- neighbourResolutionService.registerNeighbourHandler(
- portToRegister,
- neighbourHandler,
- appId
- );
- }
-
- private class InternalConfigListener implements NetworkConfigListener {
- private static final long PROGRAM_DELAY = 2;
- SegmentRoutingManager srManager;
-
- /**
- * Constructs the internal network config listener.
- *
- * @param srManager segment routing manager
- */
- InternalConfigListener(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- }
-
- /**
- * Reads network config and initializes related data structure accordingly.
- */
- void configureNetwork() {
- log.info("Configuring network ...");
-
- // Setting handling of network configuration events completable future
- // The completable future is needed because of the async behaviour of the configureNetwork,
- // listener registration and event arrival
- // Enables us to buffer the events and execute them when the configure network is done.
- synchronized (networkConfigCompletionLock) {
- networkConfigCompletion = new CompletableFuture<>();
-
- // add a small delay to absorb multiple network config added notifications
- if (!programmingScheduled.get()) {
- log.info("Buffering config calls for {} secs", PROGRAM_DELAY);
- programmingScheduled.set(true);
- mainEventExecutor.schedule(new ConfigChange(), PROGRAM_DELAY, TimeUnit.SECONDS);
- }
-
- createOrUpdateDeviceConfiguration();
-
- arpHandler = new ArpHandler(srManager);
- icmpHandler = new IcmpHandler(srManager);
- ipHandler = new IpHandler(srManager);
- routingRulePopulator = new RoutingRulePopulator(srManager);
- createOrUpdateDefaultRoutingHandler();
-
- tunnelHandler = new TunnelHandler(linkService, deviceConfiguration,
- groupHandlerMap, tunnelStore);
- policyHandler = new PolicyHandler(appId, deviceConfiguration,
- flowObjectiveService,
- tunnelHandler, policyStore);
- networkConfigCompletion.complete(true);
- }
-
- mcastHandler.init();
-
- }
-
- @Override
- public void event(NetworkConfigEvent event) {
- if (mainEventExecutor == null) {
- return;
- }
- checkState(appCfgHandler != null, "NetworkConfigEventHandler is not initialized");
- switch (event.type()) {
- case CONFIG_ADDED:
- case CONFIG_UPDATED:
- case CONFIG_REMOVED:
- log.trace("Schedule Network Config event {}", event);
- if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
- mainEventExecutor.execute(new InternalEventHandler(event));
- } else {
- queuedEvents.add(event);
- }
- break;
- default:
- break;
- }
- }
-
- @Override
- public boolean isRelevant(NetworkConfigEvent event) {
- if (event.type() == CONFIG_REGISTERED ||
- event.type() == CONFIG_UNREGISTERED) {
- log.debug("Ignore event {} due to type mismatch", event);
- return false;
- }
-
- if (!event.configClass().equals(SegmentRoutingDeviceConfig.class) &&
- !event.configClass().equals(SegmentRoutingAppConfig.class) &&
- !event.configClass().equals(InterfaceConfig.class)) {
- log.debug("Ignore event {} due to class mismatch", event);
- return false;
- }
-
- return true;
- }
-
- private final class ConfigChange implements Runnable {
- @Override
- public void run() {
- programmingScheduled.set(false);
- log.info("Reacting to config changes after buffer delay");
- for (Device device : deviceService.getDevices()) {
- processDeviceAdded(device);
- }
- defaultRoutingHandler.startPopulationProcess();
- }
- }
- }
-
- private class InternalLinkListener implements LinkListener {
- @Override
- public void event(LinkEvent event) {
- if (mainEventExecutor == null) {
- return;
- }
- if (event.type() == LinkEvent.Type.LINK_ADDED ||
- event.type() == LinkEvent.Type.LINK_UPDATED ||
- event.type() == LinkEvent.Type.LINK_REMOVED) {
- log.trace("Schedule Link event {}", event);
- if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
- mainEventExecutor.execute(new InternalEventHandler(event));
- } else {
- queuedEvents.add(event);
- }
- }
- }
- }
-
- private class InternalDeviceListener implements DeviceListener {
- @Override
- public void event(DeviceEvent event) {
- if (mainEventExecutor == null) {
- return;
- }
- switch (event.type()) {
- case DEVICE_ADDED:
- case PORT_UPDATED:
- case PORT_ADDED:
- case DEVICE_UPDATED:
- case DEVICE_AVAILABILITY_CHANGED:
- log.trace("Schedule Device event {}", event);
- if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
- mainEventExecutor.execute(new InternalEventHandler(event));
- } else {
- queuedEvents.add(event);
- }
- break;
- default:
- }
- }
- }
-
- private class InternalTopologyListener implements TopologyListener {
- @Override
- public void event(TopologyEvent event) {
- if (mainEventExecutor == null) {
- return;
- }
- switch (event.type()) {
- case TOPOLOGY_CHANGED:
- log.trace("Schedule Topology event {}", event);
- if (networkConfigCompletion == null || networkConfigCompletion.isDone()) {
- mainEventExecutor.execute(new InternalEventHandler(event));
- } else {
- queuedEvents.add(event);
- }
- break;
- default:
- }
- }
- }
-
- private class InternalHostListener implements HostListener {
- @Override
- public void event(HostEvent event) {
- if (hostEventExecutor == null) {
- return;
- }
- switch (event.type()) {
- case HOST_ADDED:
- case HOST_MOVED:
- case HOST_REMOVED:
- case HOST_UPDATED:
- log.trace("Schedule Host event {}", event);
- hostEventExecutor.execute(new InternalEventHandler(event));
- break;
- default:
- log.warn("Unsupported host event type: {}", event.type());
- break;
- }
- }
- }
-
- private class InternalMcastListener implements McastListener {
- @Override
- public void event(McastEvent event) {
- if (mcastEventExecutor == null) {
- return;
- }
- switch (event.type()) {
- case SOURCES_ADDED:
- case SOURCES_REMOVED:
- case SINKS_ADDED:
- case SINKS_REMOVED:
- case ROUTE_REMOVED:
- case ROUTE_ADDED:
- log.trace("Schedule Mcast event {}", event);
- mcastEventExecutor.execute(new InternalEventHandler(event));
- break;
- default:
- log.warn("Unsupported mcast event type: {}", event.type());
- break;
- }
- }
- }
-
- private class InternalRouteEventListener implements RouteListener {
- @Override
- public void event(RouteEvent event) {
- if (routeEventExecutor == null) {
- return;
- }
- switch (event.type()) {
- case ROUTE_ADDED:
- case ROUTE_UPDATED:
- case ROUTE_REMOVED:
- case ALTERNATIVE_ROUTES_CHANGED:
- log.trace("Schedule Route event {}", event);
- routeEventExecutor.execute(new InternalEventHandler(event));
- break;
- default:
- log.warn("Unsupported route event type: {}", event.type());
- break;
- }
- }
- }
-
- private class InternalMastershipListener implements MastershipListener {
- @Override
- public void event(MastershipEvent event) {
- if (mainEventExecutor == null) {
- return;
- }
- switch (event.type()) {
- case MASTER_CHANGED:
- log.debug("Mastership event: {}/{}", event.subject(),
- event.roleInfo());
- mainEventExecutor.execute(new InternalEventHandler(event));
- break;
- case BACKUPS_CHANGED:
- case SUSPENDED:
- default:
- log.debug("Mastership event type {} not handled", event.type());
- break;
- }
- }
- }
-
- class InternalClusterListener implements ClusterEventListener {
- private Instant lastClusterEvent = Instant.EPOCH;
-
- long timeSinceLastClusterEvent() {
- return Instant.now().toEpochMilli() - lastClusterEvent.toEpochMilli();
- }
-
- @Override
- public void event(ClusterEvent event) {
- switch (event.type()) {
- case INSTANCE_ACTIVATED:
- case INSTANCE_ADDED:
- case INSTANCE_READY:
- log.debug("Cluster event {} ignored", event.type());
- break;
- case INSTANCE_DEACTIVATED:
- case INSTANCE_REMOVED:
- log.info("** Cluster event {}", event.type());
- lastClusterEvent = Instant.now();
- break;
- default:
- break;
- }
-
- }
-
- }
-
- private void updateInterface(InterfaceConfig conf, InterfaceConfig prevConf) {
- try {
- Set<Interface> intfs = conf.getInterfaces();
- Set<Interface> prevIntfs = prevConf.getInterfaces();
-
- // Now we only handle one interface config at each port.
- if (intfs.size() != 1 || prevIntfs.size() != 1) {
- log.warn("Interface update aborted - one at a time is allowed, " +
- "but {} / {}(prev) received.", intfs.size(), prevIntfs.size());
- return;
- }
-
- //The system is in an incoherent state, abort
- if (defaultRoutingHandler == null) {
- log.warn("Interface update aborted, defaultRoutingHandler is null");
- return;
- }
-
- Interface intf = intfs.stream().findFirst().get();
- Interface prevIntf = prevIntfs.stream().findFirst().get();
-
- DeviceId deviceId = intf.connectPoint().deviceId();
- PortNumber portNum = intf.connectPoint().port();
-
- removeSubnetConfig(prevIntf.connectPoint(),
- Sets.difference(new HashSet<>(prevIntf.ipAddressesList()),
- new HashSet<>(intf.ipAddressesList())));
-
- if (!prevIntf.vlanNative().equals(VlanId.NONE)
- && !prevIntf.vlanNative().equals(intf.vlanUntagged())
- && !prevIntf.vlanNative().equals(intf.vlanNative())) {
- if (intf.vlanTagged().contains(prevIntf.vlanNative())) {
- // Update filtering objective and L2IG group bucket
- updatePortVlanTreatment(deviceId, portNum, prevIntf.vlanNative(), false);
- } else {
- // RemoveVlanNative
- updateVlanConfigInternal(deviceId, portNum, prevIntf.vlanNative(), true, false);
- }
- }
-
- if (!prevIntf.vlanUntagged().equals(VlanId.NONE)
- && !prevIntf.vlanUntagged().equals(intf.vlanUntagged())
- && !prevIntf.vlanUntagged().equals(intf.vlanNative())) {
- if (intf.vlanTagged().contains(prevIntf.vlanUntagged())) {
- // Update filtering objective and L2IG group bucket
- updatePortVlanTreatment(deviceId, portNum, prevIntf.vlanUntagged(), false);
- } else {
- // RemoveVlanUntagged
- updateVlanConfigInternal(deviceId, portNum, prevIntf.vlanUntagged(), true, false);
- }
- }
-
- if (!prevIntf.vlanTagged().isEmpty() && !intf.vlanTagged().equals(prevIntf.vlanTagged())) {
- // RemoveVlanTagged
- Sets.difference(prevIntf.vlanTagged(), intf.vlanTagged()).stream()
- .filter(i -> !intf.vlanUntagged().equals(i))
- .filter(i -> !intf.vlanNative().equals(i))
- .forEach(vlanId -> updateVlanConfigInternal(
- deviceId, portNum, vlanId, false, false));
- }
-
- if (!intf.vlanNative().equals(VlanId.NONE)
- && !prevIntf.vlanNative().equals(intf.vlanNative())
- && !prevIntf.vlanUntagged().equals(intf.vlanNative())) {
- if (prevIntf.vlanTagged().contains(intf.vlanNative())) {
- // Update filtering objective and L2IG group bucket
- updatePortVlanTreatment(deviceId, portNum, intf.vlanNative(), true);
- } else {
- // AddVlanNative
- updateVlanConfigInternal(deviceId, portNum, intf.vlanNative(), true, true);
- }
- }
-
- if (!intf.vlanTagged().isEmpty() && !intf.vlanTagged().equals(prevIntf.vlanTagged())) {
- // AddVlanTagged
- Sets.difference(intf.vlanTagged(), prevIntf.vlanTagged()).stream()
- .filter(i -> !prevIntf.vlanUntagged().equals(i))
- .filter(i -> !prevIntf.vlanNative().equals(i))
- .forEach(vlanId -> updateVlanConfigInternal(
- deviceId, portNum, vlanId, false, true)
- );
- }
-
- if (!intf.vlanUntagged().equals(VlanId.NONE)
- && !prevIntf.vlanUntagged().equals(intf.vlanUntagged())
- && !prevIntf.vlanNative().equals(intf.vlanUntagged())) {
- if (prevIntf.vlanTagged().contains(intf.vlanUntagged())) {
- // Update filtering objective and L2IG group bucket
- updatePortVlanTreatment(deviceId, portNum, intf.vlanUntagged(), true);
- } else {
- // AddVlanUntagged
- updateVlanConfigInternal(deviceId, portNum, intf.vlanUntagged(), true, true);
- }
- }
- addSubnetConfig(prevIntf.connectPoint(),
- Sets.difference(new HashSet<>(intf.ipAddressesList()),
- new HashSet<>(prevIntf.ipAddressesList())));
- } catch (ConfigException e) {
- log.error("Error in configuration");
- }
- }
-
- private void updatePortVlanTreatment(DeviceId deviceId, PortNumber portNum,
- VlanId vlanId, boolean pushVlan) {
- DefaultGroupHandler grpHandler = getGroupHandler(deviceId);
- if (grpHandler == null) {
- log.warn("Failed to retrieve group handler for device {}", deviceId);
- return;
- }
-
- // Update filtering objective for a single port
- routingRulePopulator.updateSinglePortFilters(deviceId, portNum, !pushVlan, vlanId, false);
- routingRulePopulator.updateSinglePortFilters(deviceId, portNum, pushVlan, vlanId, true);
-
- if (getVlanNextObjectiveId(deviceId, vlanId) != -1) {
- // Update L2IG bucket of the port
- grpHandler.updateL2InterfaceGroupBucket(portNum, vlanId, pushVlan);
- // Update bridging and unicast routing rule for each host
- hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
- vlanId, !pushVlan, false));
- hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
- vlanId, pushVlan, true));
- } else {
- log.warn("Failed to retrieve next objective for vlan {} in device {}:{}", vlanId, deviceId, portNum);
- }
- }
-
- private void updateVlanConfigInternal(DeviceId deviceId, PortNumber portNum,
- VlanId vlanId, boolean pushVlan, boolean install) {
- DefaultGroupHandler grpHandler = getGroupHandler(deviceId);
- if (grpHandler == null) {
- log.warn("Failed to retrieve group handler for device {}", deviceId);
- return;
- }
-
- // Update filtering objective for a single port
- routingRulePopulator.updateSinglePortFilters(deviceId, portNum, pushVlan, vlanId, install);
-
- // Update filtering objective for multicast ingress port
- mcastHandler.updateFilterToDevice(deviceId, portNum, vlanId, install);
-
- int nextId = getVlanNextObjectiveId(deviceId, vlanId);
-
- if (nextId != -1 && !install) {
- // Remove L2 Bridging rule and L3 Unicast rule to the host
- hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
- vlanId, pushVlan, install));
- // Remove broadcast forwarding rule and corresponding L2FG for VLAN
- // only if there is no port configured on that VLAN ID
- if (!getVlanPortMap(deviceId).containsKey(vlanId)) {
- // Remove broadcast forwarding rule for the VLAN
- routingRulePopulator.updateSubnetBroadcastRule(deviceId, vlanId, install);
- // Remove L2FG for VLAN
- grpHandler.removeBcastGroupFromVlan(deviceId, portNum, vlanId, pushVlan);
- } else {
- // Remove a single port from L2FG
- grpHandler.updateGroupFromVlanConfiguration(vlanId, portNum, nextId, install);
- }
- // Remove L2IG of the port
- grpHandler.removePortNextObjective(deviceId, portNum, vlanId, pushVlan);
- } else if (install) {
- // Create L2IG of the port
- grpHandler.createPortNextObjective(deviceId, portNum, vlanId, pushVlan);
- // Create L2 Bridging rule and L3 Unicast rule to the host
- hostEventExecutor.execute(() -> hostHandler.processIntfVlanUpdatedEvent(deviceId, portNum,
- vlanId, pushVlan, install));
- if (nextId != -1) {
- // Add a single port to L2FG
- grpHandler.updateGroupFromVlanConfiguration(vlanId, portNum, nextId, install);
- } else {
- // Create L2FG for VLAN
- grpHandler.createBcastGroupFromVlan(vlanId, Collections.singleton(portNum));
- routingRulePopulator.updateSubnetBroadcastRule(deviceId, vlanId, install);
- }
- } else {
- log.warn("Failed to retrieve next objective for vlan {} in device {}:{}", vlanId, deviceId, portNum);
- }
- }
-
- private void removeSubnetConfig(ConnectPoint cp, Set<InterfaceIpAddress> ipAddressSet) {
- Set<IpPrefix> ipPrefixSet = ipAddressSet.stream().
- map(InterfaceIpAddress::subnetAddress).collect(Collectors.toSet());
-
- Set<InterfaceIpAddress> deviceIntfIpAddrs = interfaceService.getInterfaces().stream()
- .filter(intf -> intf.connectPoint().deviceId().equals(cp.deviceId()))
- .filter(intf -> !intf.connectPoint().equals(cp))
- .flatMap(intf -> intf.ipAddressesList().stream())
- .collect(Collectors.toSet());
- // 1. Partial subnet population
- // Remove routing rules for removed subnet from previous configuration,
- // which does not also exist in other interfaces in the same device
- Set<IpPrefix> deviceIpPrefixSet = deviceIntfIpAddrs.stream()
- .map(InterfaceIpAddress::subnetAddress)
- .collect(Collectors.toSet());
-
- Set<IpPrefix> subnetsToBeRevoked = ipPrefixSet.stream()
- .filter(ipPrefix -> !deviceIpPrefixSet.contains(ipPrefix))
- .collect(Collectors.toSet());
-
- // Check if any of the subnets to be revoked is configured in the pairDevice.
- // If any, repopulate the subnet with pairDevice connectPoint instead of revoking.
- Optional<DeviceId> pairDevice = getPairDeviceId(cp.deviceId());
- if (pairDevice.isPresent()) {
- Set<IpPrefix> pairDeviceIpPrefix = getDeviceSubnetMap().get(pairDevice.get());
-
- Set<IpPrefix> subnetsExistingInPairDevice = subnetsToBeRevoked.stream()
- .filter(ipPrefix -> pairDeviceIpPrefix.contains(ipPrefix))
- .collect(Collectors.toSet());
-
- // Update the subnets existing in pair device with pair device connect point.
- if (!subnetsExistingInPairDevice.isEmpty()) {
- // PortNumber of connect point is not relevant in populate subnet and hence providing as ANY.
- ConnectPoint pairDeviceCp = new ConnectPoint(pairDevice.get(), PortNumber.ANY);
- log.debug("Updating the subnets: {} with pairDevice connectPoint as it exists in the Pair device: {}",
- subnetsExistingInPairDevice, pairDeviceCp);
- defaultRoutingHandler.populateSubnet(Collections.singleton(pairDeviceCp), subnetsExistingInPairDevice);
- }
-
- // Remove only the subnets that are not configured in the pairDevice.
- subnetsToBeRevoked = Sets.difference(subnetsToBeRevoked, subnetsExistingInPairDevice);
- }
-
- if (!subnetsToBeRevoked.isEmpty()) {
- log.debug("Removing subnets for connectPoint: {}, subnets: {}", cp, subnetsToBeRevoked);
- defaultRoutingHandler.revokeSubnet(subnetsToBeRevoked);
- }
-
- // 2. Interface IP punts
- // Remove IP punts for old Intf address
- Set<IpAddress> deviceIpAddrs = deviceIntfIpAddrs.stream()
- .map(InterfaceIpAddress::ipAddress)
- .collect(Collectors.toSet());
- ipAddressSet.stream()
- .map(InterfaceIpAddress::ipAddress)
- .filter(interfaceIpAddress -> !deviceIpAddrs.contains(interfaceIpAddress))
- .forEach(interfaceIpAddress ->
- routingRulePopulator.revokeSingleIpPunts(
- cp.deviceId(), interfaceIpAddress));
-
- // 3. Host unicast routing rule
- // Remove unicast routing rule
- hostEventExecutor.execute(() -> hostHandler.processIntfIpUpdatedEvent(cp, ipPrefixSet, false));
- }
-
- private void addSubnetConfig(ConnectPoint cp, Set<InterfaceIpAddress> ipAddressSet) {
- Set<IpPrefix> ipPrefixSet = ipAddressSet.stream().
- map(InterfaceIpAddress::subnetAddress).collect(Collectors.toSet());
-
- Set<InterfaceIpAddress> deviceIntfIpAddrs = interfaceService.getInterfaces().stream()
- .filter(intf -> intf.connectPoint().deviceId().equals(cp.deviceId()))
- .filter(intf -> !intf.connectPoint().equals(cp))
- .flatMap(intf -> intf.ipAddressesList().stream())
- .collect(Collectors.toSet());
- // 1. Partial subnet population
- // Add routing rules for newly added subnet, which does not also exist in
- // other interfaces in the same device
- Set<IpPrefix> deviceIpPrefixSet = deviceIntfIpAddrs.stream()
- .map(InterfaceIpAddress::subnetAddress)
- .collect(Collectors.toSet());
- Set<IpPrefix> subnetsToBePopulated = ipPrefixSet.stream()
- .filter(ipPrefix -> !deviceIpPrefixSet.contains(ipPrefix))
- .collect(Collectors.toSet());
-
- if (!subnetsToBePopulated.isEmpty()) {
- log.debug("Adding subnets for connectPoint: {}, subnets: {}", cp, subnetsToBePopulated);
-
- // check if pair-device has the same subnet configured?
- Optional<DeviceId> pairDevice = getPairDeviceId(cp.deviceId());
- if (pairDevice.isPresent()) {
- Set<IpPrefix> pairDeviceIpPrefix = getDeviceSubnetMap().get(pairDevice.get());
-
- Set<IpPrefix> subnetsToBePopulatedAsDualHomed = subnetsToBePopulated.stream()
- .filter(ipPrefix -> pairDeviceIpPrefix.contains(ipPrefix))
- .collect(Collectors.toSet());
- Set<IpPrefix> subnetsToBePopulatedAsSingleHomed = Sets.difference(subnetsToBePopulated,
- subnetsToBePopulatedAsDualHomed);
-
- if (!subnetsToBePopulatedAsSingleHomed.isEmpty()) {
- defaultRoutingHandler.populateSubnet(
- Collections.singleton(cp),
- subnetsToBePopulatedAsSingleHomed);
- }
-
- if (!subnetsToBePopulatedAsDualHomed.isEmpty()) {
- Set<ConnectPoint> cpts = new HashSet<>();
- cpts.add(cp);
- // As Subnets is DualHomed adding the pairDevice also as ConnectPoint.
- // PortNumber of connect point is not relevant in populate subnet and hence providing as ANY.
- ConnectPoint pairCp = new ConnectPoint(pairDevice.get(), PortNumber.ANY);
- cpts.add(pairCp);
-
- log.debug("Adding DualHomed subnets for connectPoint: {} and its pair device: {}, subnets: {}",
- cp, pairCp, subnetsToBePopulatedAsDualHomed);
-
- // populating the subnets as DualHomed
- defaultRoutingHandler.populateSubnet(
- cpts,
- subnetsToBePopulated);
-
- // revoking the subnets populated in the device as it is now Dualhomed.
- defaultRoutingHandler.revokeSubnet(Collections.singleton(cp.deviceId()),
- subnetsToBePopulatedAsDualHomed);
- }
- } else {
- defaultRoutingHandler.populateSubnet(
- Collections.singleton(cp),
- subnetsToBePopulated);
- }
- }
-
- // 2. Interface IP punts
- // Add IP punts for new Intf address
- Set<IpAddress> deviceIpAddrs = deviceIntfIpAddrs.stream()
- .map(InterfaceIpAddress::ipAddress)
- .collect(Collectors.toSet());
- ipAddressSet.stream()
- .map(InterfaceIpAddress::ipAddress)
- .filter(interfaceIpAddress -> !deviceIpAddrs.contains(interfaceIpAddress))
- .forEach(interfaceIpAddress ->
- routingRulePopulator.populateSingleIpPunts(
- cp.deviceId(), interfaceIpAddress));
-
- // 3. Host unicast routing rule
- // Add unicast routing rule
- hostEventExecutor.execute(() -> hostHandler.processIntfIpUpdatedEvent(cp, ipPrefixSet, true));
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java
deleted file mode 100644
index 3cf0e32..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.neighbour.NeighbourMessageHandler;
-import org.onosproject.net.host.HostService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This handler dispatches to the appropriate handlers the
- * neighbour discovery protocols.
- */
-public class SegmentRoutingNeighbourDispatcher implements NeighbourMessageHandler {
-
- private static Logger log = LoggerFactory.getLogger(SegmentRoutingNeighbourDispatcher.class);
- private SegmentRoutingManager manager;
-
- /**
- * Create a segment routing neighbour dispatcher.
- *
- * @param segmentRoutingManager the segment routing manager
- */
- public SegmentRoutingNeighbourDispatcher(SegmentRoutingManager segmentRoutingManager) {
- this.manager = segmentRoutingManager;
- }
-
- @Override
- public void handleMessage(NeighbourMessageContext context, HostService hostService) {
- manager.neighborExecutor.execute(() -> handleMessageInternal(context, hostService));
- }
-
- private void handleMessageInternal(NeighbourMessageContext context, HostService hostService) {
- log.trace("Received {} packet on {}: {}", context.protocol(),
- context.inPort(), context.packet());
- switch (context.protocol()) {
- case ARP:
- if (this.manager.arpHandler != null) {
- this.manager.arpHandler.processPacketIn(context, hostService);
- }
- break;
- case NDP:
- if (this.manager.icmpHandler != null) {
- this.manager.icmpHandler.processPacketIn(context, hostService);
- }
- break;
- default:
- log.warn("Unknown protocol", context.protocol());
- }
- }
-
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java
deleted file mode 100644
index 8ef8e7e..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourHandler.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.neighbour.NeighbourMessageContext;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * This handler provides provides useful functions to the
- * neighbour handlers (ARP, NDP).
- */
-public class SegmentRoutingNeighbourHandler {
-
- private static Logger log = LoggerFactory.getLogger(SegmentRoutingNeighbourHandler.class);
-
- protected SegmentRoutingManager srManager;
- protected DeviceConfiguration config;
-
- /**
- * Creates an SegmentRoutingNeighbourHandler object.
- *
- * @param srManager SegmentRoutingManager object
- */
- public SegmentRoutingNeighbourHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- this.config = checkNotNull(srManager.deviceConfiguration);
- }
-
- /**
- * Creates an SegmentRoutingNeighbourHandler object.
- */
- public SegmentRoutingNeighbourHandler() {
- this.srManager = null;
- this.config = null;
- }
-
- /**
- * Retrieve router (device) info.
- *
- * @param mac where to copy the mac
- * @param ip where to copy the ip
- * @param deviceId the device id
- * @param targetAddress the target address
- * @return true if it was possible to get the necessary info.
- * False for errors
- */
- protected boolean getSenderInfo(byte[] mac,
- byte[] ip,
- DeviceId deviceId,
- IpAddress targetAddress) {
- byte[] senderMacAddress;
- byte[] senderIpAddress;
- IpAddress sender;
- try {
- senderMacAddress = config.getDeviceMac(deviceId).toBytes();
- if (targetAddress.isIp4()) {
- sender = config.getRouterIpAddressForASubnetHost(targetAddress.getIp4Address());
- } else {
- sender = config.getRouterIpAddressForASubnetHost(targetAddress.getIp6Address());
- }
- // If sender is null we abort.
- if (sender == null) {
- log.warn("Sender ip is null. Aborting getSenderInfo");
- return false;
- }
- senderIpAddress = sender.toOctets();
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting getSenderInfo");
- return false;
- }
- System.arraycopy(senderMacAddress, 0, mac, 0, senderMacAddress.length);
- System.arraycopy(senderIpAddress, 0, ip, 0, senderIpAddress.length);
- return true;
- }
-
- /**
- * Reads the boolean configuration for responding to unknown hosts.
- *
- * @return respondToUnknownHosts boolean.
- */
- protected boolean respondToUnknownHosts() {
- return srManager.respondToUnknownHosts;
- }
-
- /**
- * Utility to send a ND reply using the supplied information.
- *
- * @param pkt the request
- * @param targetMac the target mac
- * @param hostService the host service
- * @param isRouter true if this reply is sent on behalf of a router
- */
- protected void sendResponse(NeighbourMessageContext pkt, MacAddress targetMac, HostService hostService,
- boolean isRouter) {
- // if this is false, check if host exists in the store
- if (!respondToUnknownHosts()) {
- short vlanId = pkt.packet().getQinQVID();
- HostId dstId = HostId.hostId(pkt.srcMac(), vlanId == Ethernet.VLAN_UNTAGGED
- ? pkt.vlan() : VlanId.vlanId(vlanId));
- Host dst = hostService.getHost(dstId);
- if (dst == null) {
- log.warn("Cannot send {} response to host {} - does not exist in the store",
- pkt.protocol(), dstId);
- return;
- }
- }
- pkt.setIsRouter(isRouter);
- pkt.reply(targetMac);
- }
-
- /**
- * Flood to all ports in the same subnet.
- *
- * @param packet packet to be flooded
- * @param inPort where the packet comes from
- * @param targetAddress the target address
- */
- protected void flood(Ethernet packet, ConnectPoint inPort, IpAddress targetAddress) {
- try {
- srManager.deviceConfiguration
- .getSubnetPortsMap(inPort.deviceId()).forEach((subnet, ports) -> {
- if (subnet.contains(targetAddress)) {
- ports.stream()
- .filter(port -> port != inPort.port())
- .forEach(port -> {
- forward(packet, new ConnectPoint(inPort.deviceId(), port));
- });
- }
- });
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Cannot flood in subnet as device config not available"
- + " for device: " + inPort.deviceId());
- }
- }
-
- /*
- * Floods only on the port which have been configured with the subnet
- * of the target address. The in port is excluded.
- *
- * @param pkt the ndp/arp packet and context information
- */
- protected void flood(NeighbourMessageContext pkt) {
- try {
- srManager.deviceConfiguration
- .getSubnetPortsMap(pkt.inPort().deviceId()).forEach((subnet, ports) -> {
- if (subnet.contains(pkt.target())) {
- ports.stream()
- .filter(port -> port != pkt.inPort().port())
- .forEach(port -> {
- ConnectPoint outPoint = new ConnectPoint(
- pkt.inPort().deviceId(),
- port
- );
- pkt.forward(outPoint);
- });
- }
- });
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Cannot flood in subnet as device config not available"
- + " for device: " + pkt.inPort().deviceId());
- }
- }
-
- /**
- * Packet out to given port.
- *
- * Note: In current implementation, we expect all communication with
- * end hosts within a subnet to be untagged.
- * <p>
- * For those pipelines that internally assigns a VLAN, the VLAN tag will be
- * removed before egress.
- * <p>
- * For those pipelines that do not assign internal VLAN, the packet remains
- * untagged.
- *
- * @param packet packet to be forwarded
- * @param outPort where the packet should be forwarded
- */
- private void forward(Ethernet packet, ConnectPoint outPort) {
- ByteBuffer buf = ByteBuffer.wrap(packet.serialize());
-
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.setOutput(outPort.port());
- srManager.packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
- tbuilder.build(), buf));
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
deleted file mode 100644
index 3bfd88b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Multimap;
-import org.apache.commons.lang3.NotImplementedException;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
-import org.onosproject.segmentrouting.mcast.McastFilteringObjStoreKey;
-import org.onosproject.segmentrouting.mcast.McastRole;
-import org.onosproject.segmentrouting.mcast.McastRoleStoreKey;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.segmentrouting.mcast.McastStoreKey;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * Segment Routing Service for REST API.
- */
-public interface SegmentRoutingService {
- /**
- * VLAN cross-connect ACL priority.
- *
- * @deprecated in ONOS 1.12. Replaced by {@link org.onosproject.segmentrouting.xconnect.api.XconnectService}
- */
- @Deprecated
- int XCONNECT_ACL_PRIORITY = 60000;
-
- /**
- * VLAN cross-connect Bridging priority.
- *
- * @deprecated in ONOS 1.12. Replaced by {@link org.onosproject.segmentrouting.xconnect.api.XconnectService}
- */
- @Deprecated
- int XCONNECT_PRIORITY = 1000;
-
- /**
- * Default flow priority.
- */
- int DEFAULT_PRIORITY = 100;
-
- /**
- * Minimum IP priority.
- *
- * Should < 0 such that priority of /0 will not conflict with lowest
- * priority default entries.
- */
- int MIN_IP_PRIORITY = 10;
-
- /**
- * Subnet flooding flow priority.
- */
- int FLOOD_PRIORITY = 5;
-
- /**
- * Returns all tunnels.
- *
- * @return list of tunnels
- */
- List<Tunnel> getTunnels();
-
- /**
- * Creates a tunnel.
- *
- * @param tunnel tunnel reference to create
- * @return WRONG_PATH if the tunnel path is wrong, ID_EXISTS if the tunnel ID
- * exists already, TUNNEL_EXISTS if the same tunnel exists, INTERNAL_ERROR
- * if the tunnel creation failed internally, SUCCESS if the tunnel is created
- * successfully
- */
- TunnelHandler.Result createTunnel(Tunnel tunnel);
-
- /**
- * Returns all policies.
- *
- * @return list of policy
- */
- List<Policy> getPolicies();
-
- /**
- * Returns the l2 tunnel descriptions.
- *
- * @param pending if true fetch pending pseudowires, else fetch installed
- * @return set of l2 tunnel descriptions.
- */
- Set<L2TunnelDescription> getL2TunnelDescriptions(boolean pending);
-
- /**
- * Returns all l2 tunnels of pseudowires.
- *
- * @return list of l2 tunnels
- */
- List<L2Tunnel> getL2Tunnels();
-
- /**
- * Returns all l2 policie of pseudowires.
- *
- * @return list of l2 policies.
- */
- List<L2TunnelPolicy> getL2Policies();
-
- /**
- * Removes pseudowire.
- *
- * @param pwId The id of the pseudowire.
- * @return SUCCESS if operation successful or a descriptive error otherwise.
- */
- L2TunnelHandler.Result removePseudowire(Integer pwId);
-
- /**
- * Adds a Pseudowire to the system.
- *
- * @param tunnel The pseudowire tunnel.
- * @return SUCCESS if operation is successful or a descriptive error otherwise.
- */
- L2TunnelHandler.Result addPseudowire(L2TunnelDescription tunnel);
-
- /**
- * Adds a set of pseudowires.
- *
- *
- * @param l2TunnelDescriptions The pseudowires to add.
- * @return SUCCESS if ALL pseudowires can be instantiated and are deployed, or a
- * a descriptive error otherwise, without deploying any pseudowire.
- * @deprecated onos-1.12 use addPseudowire instead
- */
- @Deprecated
- L2TunnelHandler.Result addPseudowiresBulk(List<DefaultL2TunnelDescription> l2TunnelDescriptions);
-
- /**
- * Creates a policy.
- *
- * @param policy policy reference to create
- * @return ID_EXISTS if the same policy ID exists,
- * POLICY_EXISTS if the same policy exists, TUNNEL_NOT_FOUND if the tunnel
- * does not exists, UNSUPPORTED_TYPE if the policy type is not supported,
- * SUCCESS if the policy is created successfully.
- */
- PolicyHandler.Result createPolicy(Policy policy);
-
- /**
- * Removes a tunnel.
- *
- * @param tunnel tunnel reference to remove
- * @return TUNNEL_NOT_FOUND if the tunnel to remove does not exists,
- * INTERNAL_ERROR if the tunnel creation failed internally, SUCCESS
- * if the tunnel is created successfully.
- */
- TunnelHandler.Result removeTunnel(Tunnel tunnel);
-
- /**
- * Removes a policy.
- *
- * @param policy policy reference to remove
- * @return POLICY_NOT_FOUND if the policy to remove does not exists,
- * SUCCESS if it is removed successfully
- */
- PolicyHandler.Result removePolicy(Policy policy);
-
- /**
- * Use current state of the network to repopulate forwarding rules.
- *
- */
- void rerouteNetwork();
-
- /**
- * Returns device-subnet mapping.
- *
- * @return device-subnet mapping
- */
- Map<DeviceId, Set<IpPrefix>> getDeviceSubnetMap();
-
- /**
- * Returns the current ECMP shortest path graph in this controller instance.
- *
- * @return ECMP shortest path graph
- */
- ImmutableMap<DeviceId, EcmpShortestPathGraph> getCurrentEcmpSpg();
-
- /**
- * Returns the destinatiomSet-NextObjective store contents.
- *
- * @return current contents of the dstNextObjStore
- */
- ImmutableMap<DestinationSetNextObjectiveStoreKey, NextNeighbors> getDstNextObjStore();
-
- /**
- * Returns the VLAN next objective store.
- *
- * @return current contents of the vlanNextObjStore
- */
- ImmutableMap<VlanNextObjectiveStoreKey, Integer> getVlanNextObjStore();
-
- /**
- * Returns the Mac Vlan next objective store.
- *
- * @return current contents of the macVlanNextObjStore
- */
- ImmutableMap<MacVlanNextObjectiveStoreKey, Integer> getMacVlanNextObjStore();
-
- /**
- * Returns the port next objective store.
- *
- * @return current contents of the portNextObjStore
- */
- ImmutableMap<PortNextObjectiveStoreKey, Integer> getPortNextObjStore();
-
- /**
- * Returns the associated next ids to the mcast groups or to the single
- * group if mcastIp is present.
- *
- * @param mcastIp the group ip
- * @return the mapping mcastIp-device to next id
- */
- Map<McastStoreKey, Integer> getMcastNextIds(IpAddress mcastIp);
-
- /**
- * Returns the PW init next objective store.
- *
- * @return current contents of the l2InitiationNextObjStore
- */
- ImmutableMap<String, NextObjective> getPwInitNext();
-
- /**
- * Returns the PW termination next objective store.
- *
- * @return current contents of the l2TerminationNextObjStore
- */
- ImmutableMap<String, NextObjective> getPwTermNext();
-
- /**
- * Removes all entries in dst/vlan/port/mcast NextObjectiveStore that are associated with the given nextId.
- *
- * @param nextId nextId
- */
- void invalidateNextObj(int nextId);
-
- /**
- * Triggers the verification of all ECMP groups in the specified device.
- * Adjusts the group buckets if verification finds that there are more or less
- * buckets than what should be there.
- *
- * @param id the device identifier
- */
- void verifyGroups(DeviceId id);
-
- /**
- * Returns the internal link state as seen by this instance of the
- * controller.
- *
- * @return the internal link state
- */
- ImmutableMap<Link, Boolean> getSeenLinks();
-
- /**
- * Returns the ports administratively disabled by the controller.
- *
- * @return a map of devices and port numbers for administratively disabled
- * ports. Does not include ports manually disabled by the operator.
- */
- ImmutableMap<DeviceId, Set<PortNumber>> getDownedPortState();
-
- /**
- * Returns the associated roles to the mcast groups.
- *
- * @param mcastIp the group ip
- * @param sourcecp the source connect point
- * @return the mapping mcastIp-device to mcast role
- */
- Map<McastRoleStoreKey, McastRole> getMcastRoles(IpAddress mcastIp,
- ConnectPoint sourcecp);
-
- /**
- * Returns the associated trees to the mcast group.
- *
- * @param mcastIp the group ip
- * @param sourcecp the source connect point
- * @return the mapping egress point to mcast path
- */
- Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
- ConnectPoint sourcecp);
-
- /**
- * Return the leaders of the mcast groups.
- *
- * @param mcastIp the group ip
- * @return the mapping group-node
- */
- Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp);
-
- /**
- * Returns shouldProgram map.
- *
- * @return shouldProgram map
- */
- Map<Set<DeviceId>, NodeId> getShouldProgram();
-
- /**
- * Returns shouldProgram local cache.
- *
- * @return shouldProgram local cache
- */
- Map<DeviceId, Boolean> getShouldProgramCache();
-
- /**
- * Returns whether instance should program device or not.
- *
- * @param deviceId .
- * @return boolean status saying instance should program device or not.
- */
- boolean shouldProgram(DeviceId deviceId);
-
- /**
- * Returns the mcast filtering obj.
- *
- * @return the mapping group-node
- */
- Map<DeviceId, List<McastFilteringObjStoreKey>> getMcastFilters();
-
- /**
- * Determines if routing in the network has been stable in the last
- * STABILITY_THRESHOLD seconds, by comparing the current time to the last
- * routing change timestamp.
- *
- * @return true if stable
- */
- boolean isRoutingStable();
-
- /**
- * Invoke hostHandler.init() for given device.
- *
- * @param deviceId device ID
- */
- void initHost(DeviceId deviceId);
-
- /**
- * Invoke routeHandler.init() for given device.
- *
- * @param deviceId device ID
- */
- void initRoute(DeviceId deviceId);
-
- /**
- * Gets application id.
- *
- * @return application id
- */
- default ApplicationId appId() {
- throw new NotImplementedException("appId not implemented");
- }
-
- /**
- * Returns internal VLAN for untagged hosts on given connect point.
- * <p>
- * The internal VLAN is either vlan-untagged for an access port,
- * or vlan-native for a trunk port.
- *
- * @param connectPoint connect point
- * @return internal VLAN or null if both vlan-untagged and vlan-native are undefined
- */
- default VlanId getInternalVlanId(ConnectPoint connectPoint) {
- throw new NotImplementedException("getInternalVlanId not implemented");
- }
-
- /**
- * Returns optional pair device ID of given device.
- *
- * @param deviceId device ID
- * @return optional pair device ID. Might be empty if pair device is not configured
- */
- default Optional<DeviceId> getPairDeviceId(DeviceId deviceId) {
- throw new NotImplementedException("getPairDeviceId not implemented");
- }
-
- /**
- * Returns optional pair device local port of given device.
- *
- * @param deviceId device ID
- * @return optional pair device ID. Might be empty if pair device is not configured
- */
- default Optional<PortNumber> getPairLocalPort(DeviceId deviceId) {
- throw new NotImplementedException("getPairLocalPort not implemented");
- }
-
- /**
- * Returns a set of infrastructure ports on the given device.
- *
- * @param deviceId device ID
- * @return a set of ports that does not have interface configuration
- */
- default Set<PortNumber> getInfraPorts(DeviceId deviceId) {
- throw new NotImplementedException("getInfraPorts not implemented");
- }
-
- /**
- * Returns a set of edge ports on the given device.
- *
- * @param deviceId device ID
- * @return a set of ports that has interface configuration
- */
- default Set<PortNumber> getEdgePorts(DeviceId deviceId) {
- throw new NotImplementedException("getEdgePorts not implemented");
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TopologyHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TopologyHandler.java
deleted file mode 100644
index 72b1a70..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TopologyHandler.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Maps;
-import org.onosproject.event.Event;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.link.LinkEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * Handler for topology events.
- */
-class TopologyHandler {
-
- // Logging instance
- private static final Logger log = LoggerFactory.getLogger(TopologyHandler.class);
- // Internal reference for SR manager and its services
- private final SegmentRoutingManager srManager;
-
- /**
- * Constructs the TopologyHandler.
- *
- * @param srManager Segment Routing manager
- */
- TopologyHandler(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- }
-
- // Check if the link event is valid
- private boolean isValid(LinkEvent linkEvent) {
- Link link = linkEvent.subject();
- // Verify if the link is valid with the link handler
- if (!srManager.linkHandler.isLinkValid(link)) {
- log.debug("Link {} ignored by the LinkHandler", link);
- return false;
- }
- // Processing for LINK_REMOVED
- if (linkEvent.type() == LinkEvent.Type.LINK_REMOVED) {
- // device availability check helps to ensure that multiple link-removed
- // events are actually treated as a single switch removed event.
- // purgeSeenLink is necessary so we do rerouting (instead of rehashing)
- // when switch comes back.
- if (link.src().elementId() instanceof DeviceId
- && !srManager.deviceService.isAvailable(link.src().deviceId())) {
- log.debug("Link {} ignored device {} is down", link, link.src().deviceId());
- return false;
- }
- if (link.dst().elementId() instanceof DeviceId
- && !srManager.deviceService.isAvailable(link.dst().deviceId())) {
- log.debug("Link {} ignored device {} is down", link, link.dst().deviceId());
- return false;
- }
- // LINK_REMOVED is ok
- return true;
- }
- // Processing for LINK_ADDED and LINK_UPDATED
- // Verify if source device is configured
- if (srManager.deviceConfiguration == null ||
- !srManager.deviceConfiguration.isConfigured(link.src().deviceId())) {
- // Source device is not configured, not valid for us
- log.warn("Source device of this link is not configured.. "
- + "not processing further");
- return false;
- }
- // LINK_ADDED/LINK_UPDATED is ok
- return true;
- }
-
- // Check if the device event is valid
- private boolean isValid(DeviceEvent deviceEvent) {
- Device device = deviceEvent.subject();
- // We don't process the event if the device is available
- return !srManager.deviceService.isAvailable(device.id());
- }
-
- /**
- * Process the TOPOLOGY_CHANGE event. An initial optimization
- * is performed to avoid the processing of not relevant events.
- *
- * @param reasons list of events that triggered topology change
- */
- void processTopologyChange(List<Event> reasons) {
- // Store temporary in the map all the link events,
- // events having the same subject will be automatically
- // overridden.
- Map<Link, LinkEvent> linkEvents = Maps.newHashMap();
- // Store temporary in the map all the device events,
- // events having the same subject will be automatically
- // overridden.
- Map<DeviceId, DeviceEvent> deviceEvents = Maps.newHashMap();
- // Pre-process all the events putting them in the right map
- reasons.forEach(reason -> {
- // Relevant events for devices
- if (reason.type() == DeviceEvent.Type.DEVICE_ADDED ||
- reason.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
- reason.type() == DeviceEvent.Type.DEVICE_UPDATED) {
- // Take the event and save in the map
- DeviceEvent deviceEvent = (DeviceEvent) reason;
- deviceEvents.put(deviceEvent.subject().id(), deviceEvent);
- /// Relevant events for links
- } else if (reason.type() == LinkEvent.Type.LINK_ADDED ||
- reason.type() == LinkEvent.Type.LINK_UPDATED ||
- reason.type() == LinkEvent.Type.LINK_REMOVED) {
- // Take the event and store the link in the map
- LinkEvent linkEvent = (LinkEvent) reason;
- linkEvents.put(linkEvent.subject(), linkEvent);
- // Other events are not relevant
- } else {
- log.debug("Unhandled event type: {}", reason.type());
- }
- });
- // Verify if the link events are valid
- // before sent for mcast handling
- List<LinkEvent> toProcessLinkEvent = linkEvents.values()
- .stream()
- .filter(this::isValid)
- .collect(Collectors.toList());
- // Verify if the device events are valid
- // before sent for mcast handling
- List<DeviceEvent> toProcessDeviceEvent = deviceEvents.values()
- .stream()
- .filter(this::isValid)
- .collect(Collectors.toList());
-
- // Processing part of the received events
- // We don't need to process all LINK_ADDED
- boolean isLinkAdded = false;
- // Iterate on link events
- for (LinkEvent linkEvent : toProcessLinkEvent) {
- // We process just the first one
- if (linkEvent.type() == LinkEvent.Type.LINK_ADDED ||
- linkEvent.type() == LinkEvent.Type.LINK_UPDATED) {
- // Other ones are skipped
- if (isLinkAdded) {
- continue;
- }
- log.info("Processing - Event: {}", linkEvent);
- // First time, let's process it
- isLinkAdded = true;
- // McastHandler, reroute all the mcast tree
- srManager.mcastHandler.init();
- } else {
- log.info("Processing - Event: {}", linkEvent);
- // We compute each time a LINK_DOWN event
- srManager.mcastHandler.processLinkDown(linkEvent.subject());
- }
- }
- // Process all the device events
- toProcessDeviceEvent.forEach(deviceEvent -> {
- log.info("Processing - Event: {}", deviceEvent);
- srManager.mcastHandler.processDeviceDown(deviceEvent.subject().id());
- });
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Tunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Tunnel.java
deleted file mode 100644
index 470662f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/Tunnel.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import java.util.List;
-
-/**
- * Tunnel interface.
- */
-public interface Tunnel {
-
- /**
- * Returns the tunnel ID.
- *
- * @return tunnel ID
- */
- String id();
-
- /**
- * Returns Segment IDs for the tunnel including source and destination.
- *
- * @return List of Node ID
- */
- List<Integer> labelIds();
-
- /**
- * Returns the group ID for the tunnel.
- *
- * @return group ID
- */
- int groupId();
-
- /**
- * Sets group ID for the tunnel.
- *
- * @param groupId group identifier
- */
- void setGroupId(int groupId);
-
- /**
- * Sets the flag to allow to remove the group or not.
- *
- * @param ok the flag; true - allow to remove
- */
- void allowToRemoveGroup(boolean ok);
-
- /**
- * Checks if it is allowed to remove the group for the tunnel.
- *
- * @return true if allowed, false otherwise
- */
- boolean isAllowedToRemoveGroup();
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
deleted file mode 100644
index 7031507..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.slf4j.Logger;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Tunnel Handler.
- */
-public class TunnelHandler {
- protected final Logger log = getLogger(getClass());
-
- private final DeviceConfiguration config;
- private final EventuallyConsistentMap<String, Tunnel> tunnelStore;
- private Map<DeviceId, DefaultGroupHandler> groupHandlerMap;
- private LinkService linkService;
-
- /**
- * Result of tunnel creation or removal.
- */
- public enum Result {
- /**
- * Success.
- */
- SUCCESS,
-
- /**
- * More than one router needs to specified to created a tunnel.
- */
- WRONG_PATH,
-
- /**
- * The same tunnel exists already.
- */
- TUNNEL_EXISTS,
-
- /**
- * The same tunnel ID exists already.
- */
- ID_EXISTS,
-
- /**
- * Tunnel not found.
- */
- TUNNEL_NOT_FOUND,
-
- /**
- * Cannot remove the tunnel used by a policy.
- */
- TUNNEL_IN_USE,
-
- /**
- * Failed to create/remove groups for the tunnel.
- */
- INTERNAL_ERROR
- }
-
- /**
- * Constructs tunnel handler.
- *
- * @param linkService link service
- * @param deviceConfiguration device configuration
- * @param groupHandlerMap group handler map
- * @param tunnelStore tunnel store
- */
- public TunnelHandler(LinkService linkService,
- DeviceConfiguration deviceConfiguration,
- Map<DeviceId, DefaultGroupHandler> groupHandlerMap,
- EventuallyConsistentMap<String, Tunnel> tunnelStore) {
- this.linkService = linkService;
- this.config = deviceConfiguration;
- this.groupHandlerMap = groupHandlerMap;
- this.tunnelStore = tunnelStore;
- }
-
- /**
- * Creates a tunnel.
- *
- * @param tunnel tunnel reference to create a tunnel
- * @return WRONG_PATH if the tunnel path is wrong, ID_EXISTS if the tunnel ID
- * exists already, TUNNEL_EXISTS if the same tunnel exists, INTERNAL_ERROR
- * if the tunnel creation failed internally, SUCCESS if the tunnel is created
- * successfully
- */
- public Result createTunnel(Tunnel tunnel) {
-
- if (tunnel.labelIds().isEmpty() || tunnel.labelIds().size() < 3) {
- log.error("More than one router needs to specified to created a tunnel");
- return Result.WRONG_PATH;
- }
-
- if (tunnelStore.containsKey(tunnel.id())) {
- log.warn("The same tunnel ID exists already");
- return Result.ID_EXISTS;
- }
-
- if (tunnelStore.containsValue(tunnel)) {
- log.warn("The same tunnel exists already");
- return Result.TUNNEL_EXISTS;
- }
-
- int groupId = createGroupsForTunnel(tunnel);
- if (groupId < 0) {
- log.error("Failed to create groups for the tunnel");
- return Result.INTERNAL_ERROR;
- }
-
- tunnel.setGroupId(groupId);
- tunnelStore.put(tunnel.id(), tunnel);
-
- return Result.SUCCESS;
- }
-
- /**
- * Removes the tunnel with the tunnel ID given.
- *
- * @param tunnelInfo tunnel information to delete tunnels
- * @return TUNNEL_NOT_FOUND if the tunnel to remove does not exists,
- * INTERNAL_ERROR if the tunnel creation failed internally, SUCCESS
- * if the tunnel is created successfully.
- */
- public Result removeTunnel(Tunnel tunnelInfo) {
-
- Tunnel tunnel = tunnelStore.get(tunnelInfo.id());
- if (tunnel != null) {
- DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
- if (tunnel.isAllowedToRemoveGroup()) {
- if (groupHandlerMap.get(deviceId).removeGroup(tunnel.groupId())) {
- tunnelStore.remove(tunnel.id());
- } else {
- log.error("Failed to remove the tunnel {}", tunnelInfo.id());
- return Result.INTERNAL_ERROR;
- }
- } else {
- log.debug("The group is not removed because it is being used.");
- tunnelStore.remove(tunnel.id());
- }
- } else {
- log.error("No tunnel found for tunnel ID {}", tunnelInfo.id());
- return Result.TUNNEL_NOT_FOUND;
- }
-
- return Result.SUCCESS;
- }
-
- /**
- * Returns the tunnel with the tunnel ID given.
- *
- * @param tid Tunnel ID
- * @return Tunnel reference
- */
- public Tunnel getTunnel(String tid) {
- return tunnelStore.get(tid);
- }
-
- /**
- * Returns all tunnels.
- *
- * @return list of Tunnels
- */
- public List<Tunnel> getTunnels() {
- List<Tunnel> tunnels = new ArrayList<>();
- tunnelStore.values().forEach(tunnel -> tunnels.add(
- new DefaultTunnel((DefaultTunnel) tunnel)));
-
- return tunnels;
- }
-
- private int createGroupsForTunnel(Tunnel tunnel) {
-
- Set<Integer> portNumbers;
- final int groupError = -1;
-
- DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
- if (deviceId == null) {
- log.warn("No device found for SID {}", tunnel.labelIds().get(0));
- return groupError;
- } else if (groupHandlerMap.get(deviceId) == null) {
- log.warn("group handler not found for {}", deviceId);
- return groupError;
- }
- Set<DeviceId> deviceIds = new HashSet<>();
- int sid = tunnel.labelIds().get(1);
- if (config.isAdjacencySid(deviceId, sid)) {
- portNumbers = config.getPortsForAdjacencySid(deviceId, sid);
- for (Link link: linkService.getDeviceEgressLinks(deviceId)) {
- for (Integer port: portNumbers) {
- if (link.src().port().toLong() == port) {
- deviceIds.add(link.dst().deviceId());
- }
- }
- }
- } else {
- deviceIds.add(config.getDeviceId(sid));
- }
- // For these NeighborSet isMpls is meaningless.
- // TODO : Revisit this, the code and also the type
- DestinationSet ns = DestinationSet.createTypePushBos(
- tunnel.labelIds().get(2),
- DeviceId.NONE);
-
- // If the tunnel reuses any existing groups, then tunnel handler
- // should not remove the group.
- if (groupHandlerMap.get(deviceId).hasNextObjectiveId(ns)) {
- tunnel.allowToRemoveGroup(false);
- } else {
- tunnel.allowToRemoveGroup(true);
- }
-
- return groupHandlerMap.get(deviceId).getNextObjectiveId(ns, null, null, true);
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
deleted file mode 100644
index 5df82af..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Tunnel Policy.
- */
-public final class TunnelPolicy implements Policy {
-
- private final Type type;
- private final String id;
- private final int priority;
- private final String tunnelId;
- private String dstIp;
- private String srcIp;
- private String ipProto;
- private short srcPort;
- private short dstPort;
-
- private TunnelPolicy(String policyId, Type type, int priority, String tunnelId, String srcIp,
- String dstIp, String ipProto, short srcPort, short dstPort) {
- this.id = checkNotNull(policyId);
- this.type = type;
- this.tunnelId = tunnelId;
- this.priority = priority;
- this.dstIp = dstIp;
- this.srcIp = srcIp;
- this.ipProto = ipProto;
- this.srcPort = srcPort;
- this.dstPort = dstPort;
-
- }
-
- /**
- * Creates a TunnelPolicy reference.
- *
- * @param p TunnelPolicy reference
- */
- public TunnelPolicy(TunnelPolicy p) {
- this.id = p.id;
- this.type = p.type;
- this.tunnelId = p.tunnelId;
- this.priority = p.priority;
- this.srcIp = p.srcIp;
- this.dstIp = p.dstIp;
- this.ipProto = p.ipProto;
- this.srcPort = p.srcPort;
- this.dstPort = p.dstPort;
- }
-
- /**
- * Returns the TunnelPolicy builder reference.
- *
- * @return TunnelPolicy builder
- */
- public static TunnelPolicy.Builder builder() {
- return new Builder();
- }
-
- @Override
- public String id() {
- return this.id;
- }
-
- @Override
- public int priority() {
- return priority;
- }
-
- @Override
- public Type type() {
- return type;
- }
-
- @Override
- public String srcIp() {
- return srcIp;
- }
-
- @Override
- public String dstIp() {
- return dstIp;
- }
-
- @Override
- public String ipProto() {
- return ipProto;
- }
-
- @Override
- public short srcPort() {
- return srcPort;
- }
-
- @Override
- public short dstPort() {
- return dstPort;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o instanceof TunnelPolicy) {
- TunnelPolicy that = (TunnelPolicy) o;
- // We do not compare the policy ID
- if (this.type.equals(that.type) &&
- this.tunnelId.equals(that.tunnelId) &&
- this.priority == that.priority &&
- this.srcIp.equals(that.srcIp) &&
- this.dstIp.equals(that.dstIp) &&
- this.srcPort == that.srcPort &&
- this.dstPort == that.dstPort &&
- this.ipProto.equals(that.ipProto)) {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(type, tunnelId, srcIp, dstIp, ipProto,
- srcPort, dstPort, priority);
- }
-
- /**
- * Returns the tunnel ID of the policy.
- *
- * @return Tunnel ID
- */
- public String tunnelId() {
- return this.tunnelId;
- }
-
-
- /**
- * Tunnel Policy Builder.
- */
- public static final class Builder {
-
- private String id;
- private Type type;
- private int priority;
- private String tunnelId;
- private String dstIp;
- private String srcIp;
- private String ipProto;
- private short srcPort;
- private short dstPort;
-
- /**
- * Sets the policy Id.
- *
- * @param id policy Id
- * @return Builder object
- */
- public Builder setPolicyId(String id) {
- this.id = id;
-
- return this;
- }
-
- /**
- * Sets the policy type.
- *
- * @param type policy type
- * @return Builder object
- */
- public Builder setType(Type type) {
- this.type = type;
-
- return this;
- }
-
- /**
- * Sets the source IP address.
- *
- * @param srcIp source IP address
- * @return Builder object
- */
- public Builder setSrcIp(String srcIp) {
- this.srcIp = srcIp;
-
- return this;
- }
-
- /**
- * Sets the destination IP address.
- *
- * @param dstIp destination IP address
- * @return Builder object
- */
- public Builder setDstIp(String dstIp) {
- this.dstIp = dstIp;
-
- return this;
- }
-
- /**
- * Sets the IP protocol.
- *
- * @param proto IP protocol
- * @return Builder object
- */
- public Builder setIpProto(String proto) {
- this.ipProto = proto;
-
- return this;
- }
-
- /**
- * Sets the source port.
- *
- * @param srcPort source port
- * @return Builder object
- */
- public Builder setSrcPort(short srcPort) {
- this.srcPort = srcPort;
-
- return this;
- }
-
- /**
- * Sets the destination port.
- *
- * @param dstPort destination port
- * @return Builder object
- */
- public Builder setDstPort(short dstPort) {
- this.dstPort = dstPort;
-
- return this;
- }
-
- /**
- * Sets the priority of the policy.
- *
- * @param p priority
- * @return Builder object
- */
- public Builder setPriority(int p) {
- this.priority = p;
-
- return this;
- }
-
- /**
- * Sets the tunnel Id.
- *
- * @param tunnelId tunnel Id
- * @return Builder object
- */
- public Builder setTunnelId(String tunnelId) {
- this.tunnelId = tunnelId;
-
- return this;
- }
-
- /**
- * Builds the policy.
- *
- * @return Tunnel Policy reference
- */
- public Policy build() {
- return new TunnelPolicy(id, type, priority, tunnelId, srcIp, dstIp,
- ipProto, srcPort, dstPort);
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/BlackHoleCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/BlackHoleCommand.java
deleted file mode 100644
index c45ff8e..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/BlackHoleCommand.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Sets;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-
-import java.util.Set;
-
-/**
- * CLI command for managing black hole routes.
- */
-@Service
-@Command(scope = "onos", name = "sr-blackhole",
- description = "Manage black hole routes")
-public class BlackHoleCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "op",
- description = "list, add or remove",
- required = true, multiValued = false)
- private String op;
-
- @Argument(index = 1, name = "prefix",
- description = "IP prefix",
- required = false, multiValued = false)
- private String prefix;
-
- @Override
- protected void doExecute() {
- SegmentRoutingService srService = AbstractShellCommand.get(SegmentRoutingService.class);
- NetworkConfigService netcfgService = AbstractShellCommand.get(NetworkConfigService.class);
-
- SegmentRoutingAppConfig appConfig = netcfgService.getConfig(srService.appId(), SegmentRoutingAppConfig.class);
- if (appConfig == null) {
- JsonNode jsonNode = new ObjectMapper().createObjectNode();
- netcfgService.applyConfig(srService.appId(), SegmentRoutingAppConfig.class, jsonNode);
- appConfig = netcfgService.getConfig(srService.appId(), SegmentRoutingAppConfig.class);
- }
-
- Set<IpPrefix> blackHoleIps;
- switch (op) {
- case "list":
- appConfig.blackholeIPs().forEach(prefix -> print(prefix.toString()));
- break;
- case "add":
- blackHoleIps = Sets.newConcurrentHashSet(appConfig.blackholeIPs());
- blackHoleIps.add(IpPrefix.valueOf(prefix));
- appConfig.setBalckholeIps(blackHoleIps);
- break;
- case "remove":
- blackHoleIps = Sets.newConcurrentHashSet(appConfig.blackholeIPs());
- blackHoleIps.remove(IpPrefix.valueOf(prefix));
- appConfig.setBalckholeIps(blackHoleIps);
- break;
- default:
- throw new UnsupportedOperationException("Unknown operation " + op);
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java
deleted file mode 100644
index 8f706b0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/DeviceSubnetListCommand.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Command to list device-subnet mapping in Segment Routing.
- */
-@Service
-@Command(scope = "onos", name = "sr-device-subnets",
- description = "List device-subnet mapping in Segment Routing")
-public class DeviceSubnetListCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- printDeviceSubnetMap(srService.getDeviceSubnetMap());
- }
-
- private void printDeviceSubnetMap(Map<DeviceId, Set<IpPrefix>> deviceSubnetMap) {
- deviceSubnetMap.forEach(((deviceId, ipPrefices) -> {
- print("%s", deviceId);
- ipPrefices.forEach(ipPrefix -> print(" %s", ipPrefix));
- }));
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/EcmpGraphCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/EcmpGraphCommand.java
deleted file mode 100644
index 269134d..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/EcmpGraphCommand.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.EcmpShortestPathGraph;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Command to read the current state of the ECMP shortest-path graph.
- *
- */
-@Service
-@Command(scope = "onos", name = "sr-ecmp-spg",
- description = "Displays the current ecmp shortest-path-graph in this "
- + "controller instance")
-public class EcmpGraphCommand extends AbstractShellCommand {
-
- private static final String FORMAT_MAPPING = " %s";
-
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- printEcmpGraph(srService.getCurrentEcmpSpg());
- }
-
- private void printEcmpGraph(Map<DeviceId, EcmpShortestPathGraph> currentEcmpSpg) {
- if (currentEcmpSpg == null) {
- print(FORMAT_MAPPING, "No ECMP graph found");
- return;
- }
- StringBuilder ecmp = new StringBuilder();
- currentEcmpSpg.forEach((key, value) -> {
- ecmp.append("\n\nRoot Device: " + key + " ECMP Paths: " + value);
- });
- print(FORMAT_MAPPING, ecmp.toString());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/InvalidateNextCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/InvalidateNextCommand.java
deleted file mode 100644
index 094bea9..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/InvalidateNextCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.osgi.ServiceNotFoundException;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Command to invalidate next id from SR internal stores.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-invalidate",
- description = "Invalidate given next id from SR internal stores")
-public class InvalidateNextCommand extends AbstractShellCommand {
-
- private static final String CONFIRM_PHRASE = "please";
-
- @Argument(name = "nextId", description = "Next ID", index = 0)
- private String nextId = null;
-
- @Argument(name = "confirm", description = "Confirmation phrase", index = 1)
- private String please = null;
-
- @Override
- protected void doExecute() {
- if (please == null || !please.equals(CONFIRM_PHRASE)) {
- print("WARNING: System may enter an unpredictable state if the next ID is force invalidated." +
- "Enter confirmation phrase to continue.");
- return;
- }
-
- try {
- SegmentRoutingService srService = AbstractShellCommand.get(SegmentRoutingService.class);
- srService.invalidateNextObj(Integer.parseInt(nextId));
- } catch (ServiceNotFoundException e) {
- print("SegmentRoutingService unavailable");
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/LinkStateCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/LinkStateCommand.java
deleted file mode 100644
index 9d7147b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/LinkStateCommand.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-
-/**
- * Command to read the current state of the DestinationSetNextObjectiveStore.
- *
- */
-@Service
-@Command(scope = "onos", name = "sr-link-state", description = "Displays the current internal link state "
- + "noted by this instance of the controller")
-public class LinkStateCommand extends AbstractShellCommand {
- private static final String FORMAT_MAPPING = " %s";
-
- @Override
- protected void doExecute() {
- SegmentRoutingService srService = AbstractShellCommand
- .get(SegmentRoutingService.class);
- printLinkState(srService.getSeenLinks(),
- srService.getDownedPortState());
- }
-
- private void printLinkState(ImmutableMap<Link, Boolean> seenLinks,
- ImmutableMap<DeviceId, Set<PortNumber>> downedPortState) {
- List<Link> a = Lists.newArrayList();
- a.addAll(seenLinks.keySet());
- a.sort(new CompLinks());
-
- StringBuilder slbldr = new StringBuilder();
- slbldr.append("\n Seen Links: ");
- for (int i = 0; i < a.size(); i++) {
- slbldr.append("\n "
- + (seenLinks.get(a.get(i)) == Boolean.TRUE ? " up : "
- : "down : "));
- slbldr.append(a.get(i).src() + " --> " + a.get(i).dst());
- }
- print(FORMAT_MAPPING, slbldr.toString());
-
- StringBuilder dpbldr = new StringBuilder();
- dpbldr.append("\n\n Administratively Disabled Ports: ");
- downedPortState.entrySet().forEach(entry -> dpbldr
- .append("\n " + entry.getKey() + entry.getValue()));
- print(FORMAT_MAPPING, dpbldr.toString());
- }
-
- static class CompLinks implements Comparator<Link> {
-
- @Override
- public int compare(Link o1, Link o2) {
- int res = o1.src().deviceId().toString()
- .compareTo(o2.src().deviceId().toString());
- if (res < 0) {
- return -1;
- } else if (res > 0) {
- return +1;
- }
- if (o1.src().port().toLong() < o2.src().port().toLong()) {
- return -1;
- }
- return +1;
- }
-
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastFilterListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastFilterListCommand.java
deleted file mode 100644
index bc1eb42..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastFilterListCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.mcast.McastFilteringObjStoreKey;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Command to show the list of mcast filtering obj.
- */
-@Service
-@Command(scope = "onos", name = "sr-filt-mcast",
- description = "Lists all mcast filtering objs")
-public class McastFilterListCommand extends AbstractShellCommand {
-
- private static final String FORMAT_HEADER = "device=%s";
- private static final String FILTER_HEADER = "\t%s,%s,%s";
-
- @Override
- protected void doExecute() {
- // Get SR service
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- // Get the filt objs
- Map<DeviceId, List<McastFilteringObjStoreKey>> filteringObjKeys = srService.getMcastFilters();
- filteringObjKeys.forEach(this::printMcastFilter);
- }
-
- private void printMcastFilter(DeviceId deviceId, List<McastFilteringObjStoreKey> filteringObjs) {
- print(FORMAT_HEADER, deviceId);
- filteringObjs.forEach(filteringObj -> print(FILTER_HEADER, filteringObj.ingressCP(),
- filteringObj.isIpv4() ? "IPv4" : "IPv6",
- filteringObj.vlanId()));
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastLeaderListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastLeaderListCommand.java
deleted file mode 100644
index 633745c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastLeaderListCommand.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.Map;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the mcast leaders of the groups.
- */
-@Service
-@Command(scope = "onos", name = "sr-mcast-leader",
- description = "Lists all mcast leaders")
-public class McastLeaderListCommand extends AbstractShellCommand {
-
- // OSGi workaround to introduce package dependency
- McastGroupCompleter completer;
-
- // Format for group line
- private static final String G_FORMAT_MAPPING = "group=%s, leader=%s";
-
- @Option(name = "-gAddr", aliases = "--groupAddress",
- description = "IP Address of the multicast group",
- valueToShowInHelp = "224.0.0.0",
- required = false, multiValued = false)
- @Completion(McastGroupCompleter.class)
- String gAddr = null;
-
- @Override
- protected void doExecute() {
- // Verify mcast group
- IpAddress mcastGroup = null;
- if (!isNullOrEmpty(gAddr)) {
- mcastGroup = IpAddress.valueOf(gAddr);
- }
- // Get SR service
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- // Get the mapping
- Map<IpAddress, NodeId> keyToRole = srService.getMcastLeaders(mcastGroup);
- // And print local cache
- keyToRole.forEach(this::printMcastLeder);
- }
-
- private void printMcastLeder(IpAddress mcastGroup,
- NodeId nodeId) {
- print(G_FORMAT_MAPPING, mcastGroup, nodeId);
- }
-
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java
deleted file mode 100644
index 7dd6fd3..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import com.google.common.collect.Maps;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.mcast.McastStoreKey;
-import org.apache.commons.lang3.tuple.Pair;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the list of mcast nextids.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-mcast",
- description = "Lists all mcast nextids")
-public class McastNextListCommand extends AbstractShellCommand {
-
- // OSGi workaround to introduce package dependency
- McastGroupCompleter completer;
-
- // Format for group line
- private static final String FORMAT_MAPPING = "group=%s, deviceIds-nextIds=%s";
-
- @Option(name = "-gAddr", aliases = "--groupAddress",
- description = "IP Address of the multicast group",
- valueToShowInHelp = "224.0.0.0",
- required = false, multiValued = false)
- @Completion(McastGroupCompleter.class)
- String gAddr = null;
-
- @Override
- protected void doExecute() {
- // Verify mcast group
- IpAddress mcastGroup = null;
- if (!isNullOrEmpty(gAddr)) {
- mcastGroup = IpAddress.valueOf(gAddr);
- }
- // Get SR service
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- // Get the mapping
- Map<McastStoreKey, Integer> keyToNextId = srService.getMcastNextIds(mcastGroup);
- // Reduce to the set of mcast groups
- Set<IpAddress> mcastGroups = keyToNextId.keySet().stream()
- .map(McastStoreKey::mcastIp)
- .collect(Collectors.toSet());
- // Print the nextids for each group
- mcastGroups.forEach(group -> {
- // Create a new map for the group
- Map<Pair<DeviceId, VlanId>, Integer> deviceIdNextMap = Maps.newHashMap();
- keyToNextId.entrySet()
- .stream()
- // Filter only the elements related to this group
- .filter(entry -> entry.getKey().mcastIp().equals(group))
- // For each create a new entry in the group related map
- .forEach(entry -> deviceIdNextMap.put(Pair.of(entry.getKey().deviceId(),
- entry.getKey().vlanId()), entry.getValue()));
- // Print the map
- printMcastNext(group, deviceIdNextMap);
- });
- }
-
- private void printMcastNext(IpAddress mcastGroup, Map<Pair<DeviceId, VlanId>, Integer> deviceIdNextMap) {
- print(FORMAT_MAPPING, mcastGroup, deviceIdNextMap);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastRoleListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastRoleListCommand.java
deleted file mode 100644
index 2b22c67..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastRoleListCommand.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.ConnectPointCompleter;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.mcast.McastRole;
-import org.onosproject.segmentrouting.mcast.McastRoleStoreKey;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the list of mcast roles.
- */
-@Service
-@Command(scope = "onos", name = "sr-mcast-role",
- description = "Lists all mcast roles")
-public class McastRoleListCommand extends AbstractShellCommand {
-
- // OSGi workaround to introduce package dependency
- McastGroupCompleter completer;
-
- // Format for group line
- private static final String FORMAT_MAPPING = "%s,%s ingress=%s\ttransit=%s\tegress=%s";
-
- @Option(name = "-gAddr", aliases = "--groupAddress",
- description = "IP Address of the multicast group",
- valueToShowInHelp = "224.0.0.0",
- required = false, multiValued = false)
- @Completion(McastGroupCompleter.class)
- String gAddr = null;
-
- @Option(name = "-src", aliases = "--connectPoint",
- description = "Source port of:XXXXXXXXXX/XX",
- valueToShowInHelp = "of:0000000000000001/1",
- required = false, multiValued = false)
- @Completion(ConnectPointCompleter.class)
- String source = null;
-
- @Override
- protected void doExecute() {
- // Verify mcast group
- IpAddress mcastGroup = null;
- // We want to use source cp only for a specific group
- ConnectPoint sourcecp = null;
- if (!isNullOrEmpty(gAddr)) {
- mcastGroup = IpAddress.valueOf(gAddr);
- if (!isNullOrEmpty(source)) {
- sourcecp = ConnectPoint.deviceConnectPoint(source);
- }
- }
- // Get SR service, the roles and the groups
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Map<McastRoleStoreKey, McastRole> keyToRole = srService.getMcastRoles(mcastGroup, sourcecp);
- Set<IpAddress> mcastGroups = keyToRole.keySet().stream()
- .map(McastRoleStoreKey::mcastIp)
- .collect(Collectors.toSet());
- // Print the trees for each group
- mcastGroups.forEach(group -> {
- // Create a new map for the group
- Map<ConnectPoint, Multimap<McastRole, DeviceId>> roleDeviceIdMap = Maps.newHashMap();
- keyToRole.entrySet()
- .stream()
- .filter(entry -> entry.getKey().mcastIp().equals(group))
- .forEach(entry -> roleDeviceIdMap.compute(entry.getKey().source(), (gsource, map) -> {
- map = map == null ? ArrayListMultimap.create() : map;
- map.put(entry.getValue(), entry.getKey().deviceId());
- return map;
- }));
- roleDeviceIdMap.forEach((gsource, map) -> {
- // Print the map
- printMcastRole(group, gsource,
- map.get(McastRole.INGRESS),
- map.get(McastRole.TRANSIT),
- map.get(McastRole.EGRESS));
- });
- });
- }
-
- private void printMcastRole(IpAddress mcastGroup, ConnectPoint source,
- Collection<DeviceId> ingress,
- Collection<DeviceId> transit,
- Collection<DeviceId> egress) {
- print(FORMAT_MAPPING, mcastGroup, source, ingress, transit, egress);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java
deleted file mode 100644
index 09c795c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.ConnectPointCompleter;
-import org.onosproject.mcast.cli.McastGroupCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Command to show the list of mcast trees.
- */
-@Service
-@Command(scope = "onos", name = "sr-mcast-tree",
- description = "Lists all mcast trees")
-public class McastTreeListCommand extends AbstractShellCommand {
-
- // OSGi workaround to introduce package dependency
- McastGroupCompleter completer;
-
- // Format for group line
- private static final String G_FORMAT_MAPPING = "group=%s";
- // Format for sink line
- private static final String S_FORMAT_MAPPING = " sink=%s\tpath=%s";
-
- @Option(name = "-gAddr", aliases = "--groupAddress",
- description = "IP Address of the multicast group",
- valueToShowInHelp = "224.0.0.0",
- required = false, multiValued = false)
- @Completion(McastGroupCompleter.class)
- String gAddr = null;
-
- @Option(name = "-src", aliases = "--connectPoint",
- description = "Source port of:XXXXXXXXXX/XX",
- valueToShowInHelp = "of:0000000000000001/1",
- required = false, multiValued = false)
- @Completion(ConnectPointCompleter.class)
- String source = null;
-
- @Override
- protected void doExecute() {
- // Get SR service and the handled mcast groups
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Set<IpAddress> mcastGroups = ImmutableSet.copyOf(srService.getMcastLeaders(null)
- .keySet());
-
- if (!isNullOrEmpty(gAddr)) {
- mcastGroups = mcastGroups.stream()
- .filter(mcastIp -> mcastIp.equals(IpAddress.valueOf(gAddr)))
- .collect(Collectors.toSet());
- }
-
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode root = mapper.createObjectNode();
-
- // Print the trees for each group or build json objects
- mcastGroups.forEach(group -> {
- // We want to use source cp only for a specific group
- ConnectPoint sourcecp = null;
- if (!isNullOrEmpty(source) &&
- !isNullOrEmpty(gAddr)) {
- sourcecp = ConnectPoint.deviceConnectPoint(source);
- }
- Multimap<ConnectPoint, List<ConnectPoint>> mcastTree = srService.getMcastTrees(group,
- sourcecp);
- if (!mcastTree.isEmpty()) {
- // Build a json object for each group
- if (outputJson()) {
- root.putPOJO(group.toString(), json(mcastTree));
- } else {
- // Banner and then the trees
- printMcastGroup(group);
- mcastTree.forEach(this::printMcastSink);
- }
- }
- });
-
- // Print the json object at the end
- if (outputJson()) {
- print("%s", root);
- }
-
- }
-
- private void printMcastGroup(IpAddress mcastGroup) {
- print(G_FORMAT_MAPPING, mcastGroup);
- }
-
- private void printMcastSink(ConnectPoint sink, List<ConnectPoint> path) {
- print(S_FORMAT_MAPPING, sink, path);
- }
-
- private ObjectNode json(Multimap<ConnectPoint, List<ConnectPoint>> mcastTree) {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode jsonSinks = mapper.createObjectNode();
- mcastTree.asMap().forEach((sink, paths) -> {
- ArrayNode jsonPaths = mapper.createArrayNode();
- paths.forEach(path -> {
- ArrayNode jsonPath = mapper.createArrayNode();
- path.forEach(connectPoint -> jsonPath.add(connectPoint.toString()));
- jsonPaths.addPOJO(jsonPath);
- });
- jsonSinks.putPOJO(sink.toString(), jsonPaths);
- });
- return jsonSinks;
- }
-
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextDstCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextDstCommand.java
deleted file mode 100644
index e6da695..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextDstCommand.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-
-/**
- * Command to read the current state of the DestinationSetNextObjectiveStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-dst",
- description = "Displays the current next-hops seen by each switch "
- + "towards a set of destinations and the next-id it maps to")
-public class NextDstCommand extends AbstractShellCommand {
-
- private static final String FORMAT_MAPPING = " %s";
-
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- printDestinationSet(srService.getDstNextObjStore());
- }
-
- private void printDestinationSet(Map<DestinationSetNextObjectiveStoreKey,
- NextNeighbors> ds) {
- ArrayList<DestinationSetNextObjectiveStoreKey> a = new ArrayList<>();
- ds.keySet().forEach(key -> a.add(key));
- a.sort(new Comp());
-
- StringBuilder dsbldr = new StringBuilder();
- for (int i = 0; i < a.size(); i++) {
- dsbldr.append("\n " + a.get(i));
- dsbldr.append(" --> via: " + ds.get(a.get(i)));
- }
- print(FORMAT_MAPPING, dsbldr.toString());
- }
-
- static class Comp implements Comparator<DestinationSetNextObjectiveStoreKey> {
-
- @Override
- public int compare(DestinationSetNextObjectiveStoreKey o1,
- DestinationSetNextObjectiveStoreKey o2) {
- int res = o1.deviceId().toString().compareTo(o2.deviceId().toString());
- if (res < 0) {
- return -1;
- } else if (res > 0) {
- return +1;
- }
- return 0;
- }
-
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextMacVlanCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextMacVlanCommand.java
deleted file mode 100644
index e31e693..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextMacVlanCommand.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the macVlanNextObjStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-mac-vlan",
- description = "Displays the current next-hop / next-id it mapping")
-public class NextMacVlanCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- print(srService.getMacVlanNextObjStore());
- }
-
- private void print(Map<MacVlanNextObjectiveStoreKey, Integer> macVlanNextObjStore) {
- ArrayList<MacVlanNextObjectiveStoreKey> a = new ArrayList<>(macVlanNextObjStore.keySet());
- a.sort(Comparator
- .comparing((MacVlanNextObjectiveStoreKey o) -> o.deviceId().toString())
- .thenComparing((MacVlanNextObjectiveStoreKey o) -> o.vlanId().toString())
- .thenComparing((MacVlanNextObjectiveStoreKey o) -> o.macAddr().toString()));
-
- StringBuilder builder = new StringBuilder();
- a.forEach(k ->
- builder.append("\n")
- .append(k)
- .append(" --> ")
- .append(macVlanNextObjStore.get(k))
- );
- print(builder.toString());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextPortCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextPortCommand.java
deleted file mode 100644
index fddc1d7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextPortCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the portNextObjStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-port",
- description = "Displays the current port / next-id it mapping")
-public class NextPortCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- print(srService.getPortNextObjStore());
- }
-
- private void print(Map<PortNextObjectiveStoreKey, Integer> portNextObjStore) {
- ArrayList<PortNextObjectiveStoreKey> a = new ArrayList<>(portNextObjStore.keySet());
- a.sort(Comparator
- .comparing((PortNextObjectiveStoreKey o) -> o.deviceId().toString())
- .thenComparing((PortNextObjectiveStoreKey o) -> o.portNumber().toLong()));
-
- StringBuilder builder = new StringBuilder();
- a.forEach(k ->
- builder.append("\n")
- .append(k)
- .append(" --> ")
- .append(portNextObjStore.get(k))
- );
- print(builder.toString());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextVlanCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextVlanCommand.java
deleted file mode 100644
index 8518a5f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/NextVlanCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the vlanNextObjStore.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-vlan",
- description = "Displays the current vlan / next-id it mapping")
-public class NextVlanCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- print(srService.getVlanNextObjStore());
- }
-
- private void print(Map<VlanNextObjectiveStoreKey, Integer> vlanNextObjStore) {
- ArrayList<VlanNextObjectiveStoreKey> a = new ArrayList<>(vlanNextObjStore.keySet());
- a.sort(Comparator
- .comparing((VlanNextObjectiveStoreKey o) -> o.deviceId().toString())
- .thenComparing((VlanNextObjectiveStoreKey o) -> o.vlanId().toShort()));
-
- StringBuilder builder = new StringBuilder();
- a.forEach(k ->
- builder.append("\n")
- .append(k)
- .append(" --> ")
- .append(vlanNextObjStore.get(k))
- );
- print(builder.toString());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhaseCompleter.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhaseCompleter.java
deleted file mode 100644
index bd16068..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhaseCompleter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2014-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import com.google.common.collect.Lists;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractChoicesCompleter;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Phase completer.
- */
-@Service
-public class PhaseCompleter extends AbstractChoicesCompleter {
- @Override
- protected List<String> choices() {
- return Lists.newArrayList(Phase.values()).stream().map(Enum::toString).collect(Collectors.toList());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoveryListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoveryListCommand.java
deleted file mode 100644
index 6efdaaa..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoveryListCommand.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-
-@Service
-@Command(scope = "onos", name = "sr-pr-list", description = "List current recovery phase of each device")
-
-public class PhasedRecoveryListCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- PhasedRecoveryService prService = get(PhasedRecoveryService.class);
- print(prService.getPhases().toString());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoverySetCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoverySetCommand.java
deleted file mode 100644
index 50e3bc6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PhasedRecoverySetCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-
-@Service
-@Command(scope = "onos", name = "sr-pr-set", description = "Set recovery phase of given device")
-
-public class PhasedRecoverySetCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "deviceId",
- description = "Device ID",
- required = true, multiValued = false)
- @Completion(DeviceIdCompleter.class)
- private String deviceIdStr;
-
- @Argument(index = 1, name = "phase",
- description = "Recovery phase",
- required = true, multiValued = false)
- @Completion(PhaseCompleter.class)
- private String phaseStr;
-
- @Override
- protected void doExecute() {
- DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
- Phase newPhase = Phase.valueOf(phaseStr);
-
- PhasedRecoveryService prService = get(PhasedRecoveryService.class);
- prService.setPhase(deviceId, newPhase);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyAddCommand.java
deleted file mode 100644
index 1f75317..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyAddCommand.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.PolicyHandler;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Command to add a new policy.
- */
-@Service
-@Command(scope = "onos", name = "sr-policy-add",
- description = "Create a new policy")
-public class PolicyAddCommand extends AbstractShellCommand {
-
- // TODO: Need to support skipping some parameters
-
- @Argument(index = 0, name = "ID",
- description = "policy ID",
- required = true, multiValued = false)
- String policyId;
-
- @Argument(index = 1, name = "priority",
- description = "priority",
- required = true, multiValued = false)
- int priority;
-
- @Argument(index = 2, name = "src_IP",
- description = "src IP",
- required = false, multiValued = false)
- String srcIp;
-
- @Argument(index = 3, name = "src_port",
- description = "src port",
- required = false, multiValued = false)
- short srcPort;
-
- @Argument(index = 4, name = "dst_IP",
- description = "dst IP",
- required = false, multiValued = false)
- String dstIp;
-
- @Argument(index = 5, name = "dst_port",
- description = "dst port",
- required = false, multiValued = false)
- short dstPort;
-
- @Argument(index = 6, name = "proto",
- description = "IP protocol",
- required = false, multiValued = false)
- String proto;
-
- @Argument(index = 7, name = "policy_type",
- description = "policy type",
- required = true, multiValued = false)
- String policyType;
-
- @Argument(index = 8, name = "tunnel_ID",
- description = "tunnel ID",
- required = false, multiValued = false)
- String tunnelId;
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(policyId);
- tpb.setPriority(priority);
- tpb.setType(Policy.Type.valueOf(policyType));
-
- if (srcIp != null) {
- tpb.setSrcIp(srcIp);
- }
- if (dstIp != null) {
- tpb.setDstIp(dstIp);
- }
- if (srcPort != 0) {
- tpb.setSrcPort(srcPort);
- }
- if (dstPort != 0) {
- tpb.setDstPort(dstPort);
- }
- if (!"ip".equals(proto)) {
- tpb.setIpProto(proto);
- }
- if (Policy.Type.valueOf(policyType) == Policy.Type.TUNNEL_FLOW) {
- if (tunnelId == null) {
- error("tunnel ID must be specified for TUNNEL_FLOW policy");
- return;
- }
- tpb.setTunnelId(tunnelId);
- }
- PolicyHandler.Result result = srService.createPolicy(tpb.build());
-
- switch (result) {
- case POLICY_EXISTS:
- error("the same policy exists");
- break;
- case ID_EXISTS:
- error("the same policy ID exists");
- break;
- case TUNNEL_NOT_FOUND:
- error("the tunnel is not found");
- break;
- case UNSUPPORTED_TYPE:
- error("the policy type specified is not supported");
- break;
- default:
- break;
- }
-
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyListCommand.java
deleted file mode 100644
index 3520fba..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyListCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Command to show the list of policies.
- */
-@Service
-@Command(scope = "onos", name = "sr-policy-list",
- description = "Lists all policies")
-public class PolicyListCommand extends AbstractShellCommand {
-
- private static final String FORMAT_MAPPING_TUNNEL =
- " id=%s, type=%s, prio=%d, src=%s, port=%d, dst=%s, port=%d, proto=%s, tunnel=%s";
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- srService.getPolicies().forEach(policy -> printPolicy(policy));
- }
-
- private void printPolicy(Policy policy) {
- if (policy.type() == Policy.Type.TUNNEL_FLOW) {
- print(FORMAT_MAPPING_TUNNEL, policy.id(), policy.type(), policy.priority(),
- policy.srcIp(), policy.srcPort(), policy.dstIp(), policy.dstPort(),
- (policy.ipProto() == null) ? "" : policy.ipProto(),
- ((TunnelPolicy) policy).tunnelId());
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyRemoveCommand.java
deleted file mode 100644
index 575d35f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PolicyRemoveCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.PolicyHandler;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Command to remove a policy.
- */
-@Service
-@Command(scope = "onos", name = "sr-policy-remove",
- description = "Remove a policy")
-public class PolicyRemoveCommand extends AbstractShellCommand {
-
- @Argument(index = 0, name = "policy ID",
- description = "policy ID",
- required = true, multiValued = false)
- String policyId;
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(policyId);
- PolicyHandler.Result result = srService.removePolicy(tpb.build());
- if (result == PolicyHandler.Result.POLICY_NOT_FOUND) {
- print("ERROR: the policy is not found");
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PortsCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PortsCommand.java
deleted file mode 100644
index f24d28f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PortsCommand.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-@Service
-@Command(scope = "onos", name = "sr-ports", description = "Enable/Disable group of ports on a specific device")
-
-public class PortsCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "deviceId",
- description = "Device ID",
- required = true, multiValued = false)
- @Completion(DeviceIdCompleter.class)
- private String deviceIdStr;
-
- @Argument(index = 1, name = "ports",
- description = "Ports to be enabled/disabled: ALL, PAIR, INFRA, EDGE",
- required = true, multiValued = false)
- @Completion(PlaceholderCompleter.class)
- private String portsStr;
-
- @Argument(index = 2, name = "action",
- description = "Action: ENABLE, DISABLE",
- required = true, multiValued = false)
- @Completion(PlaceholderCompleter.class)
- private String actionStr;
-
- @Override
- protected void doExecute() {
- PhasedRecoveryService prService = get(PhasedRecoveryService.class);
-
- DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
-
- boolean enabled;
- switch (actionStr.toUpperCase()) {
- case "ENABLE":
- enabled = true;
- break;
- case "DISABLE":
- enabled = false;
- break;
- default:
- print("Action should be either ENABLE or DISABLE");
- return;
- }
-
- Set<PortNumber> portsChanged;
- switch (portsStr.toUpperCase()) {
- case "ALL":
- portsChanged = prService.changeAllPorts(deviceId, enabled);
- break;
- case "PAIR":
- portsChanged = prService.changePairPort(deviceId, enabled);
- break;
- case "INFRA":
- portsChanged = prService.changeInfraPorts(deviceId, enabled);
- break;
- case "EDGE":
- portsChanged = prService.changeEdgePorts(deviceId, enabled);
- break;
- default:
- print("Ports should be ALL, PAIR, INFRA, EDGE");
- return;
- }
- print("Ports set to %s: %s",
- enabled ? "enabled" : "disabled",
- portsChanged.stream().map(PortNumber::toLong).collect(Collectors.toSet()));
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java
deleted file mode 100644
index d595d5c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireAddCommand.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
-
-
-/**
- * Command to add a pseuwodire.
- */
-@Service
-@Command(scope = "onos", name = "sr-pw-add",
- description = "Add a pseudowire to the network configuration, if it already exists update it.")
-public class PseudowireAddCommand extends AbstractShellCommand {
-
- @Argument(index = 0, name = "pwId",
- description = "Pseudowire ID",
- required = true, multiValued = false)
- String pwId;
-
- @Argument(index = 1, name = "pwLabel",
- description = "Pseudowire Label",
- required = true, multiValued = false)
- String pwLabel;
-
- @Argument(index = 2, name = "mode",
- description = "Mode used for pseudowire",
- required = true, multiValued = false)
- String mode;
-
- @Argument(index = 3, name = "sDTag",
- description = "Service delimiting tag",
- required = true, multiValued = false)
- String sDTag;
-
- @Argument(index = 4, name = "cP1",
- description = "Connection Point 1",
- required = true, multiValued = false)
- String cP1;
-
- @Argument(index = 5, name = "cP1InnerVlan",
- description = "Inner Vlan of Connection Point 1",
- required = true, multiValued = false)
- String cP1InnerVlan;
-
- @Argument(index = 6, name = "cP1OuterVlan",
- description = "Outer Vlan of Connection Point 1",
- required = true, multiValued = false)
- String cP1OuterVlan;
-
- @Argument(index = 7, name = "cP2",
- description = "Connection Point 2",
- required = true, multiValued = false)
- String cP2;
-
- @Argument(index = 8, name = "cP2InnerVlan",
- description = "Inner Vlan of Connection Point 2",
- required = true, multiValued = false)
- String cP2InnerVlan;
-
- @Argument(index = 9, name = "cP2OuterVlan",
- description = "Outer Vlan of Connection Point 2",
- required = true, multiValued = false)
- String cP2OuterVlan;
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- L2Tunnel tun;
- L2TunnelPolicy policy;
-
- try {
- tun = new DefaultL2Tunnel(parseMode(mode), parseVlan(sDTag), parsePwId(pwId), parsePWLabel(pwLabel));
- } catch (IllegalArgumentException e) {
- log.error("Exception while parsing L2Tunnel : \n\t %s", e.getMessage());
- print("Exception while parsing L2Tunnel : \n\t %s", e.getMessage());
- return;
- }
-
- try {
- policy = new DefaultL2TunnelPolicy(parsePwId(pwId),
- ConnectPoint.deviceConnectPoint(cP1), parseVlan(cP1InnerVlan),
- parseVlan(cP1OuterVlan), ConnectPoint.deviceConnectPoint(cP2),
- parseVlan(cP2InnerVlan), parseVlan(cP2OuterVlan));
-
- } catch (IllegalArgumentException e) {
- log.error("Exception while parsing L2TunnelPolicy : \n\t %s", e.getMessage());
- print("Exception while parsing L2TunnelPolicy : \n\t %s", e.getMessage());
- return;
- }
-
- L2TunnelDescription pw = new DefaultL2TunnelDescription(tun, policy);
- L2TunnelHandler.Result res = srService.addPseudowire(pw);
- log.info("Deploying pseudowire {} via the command line.", pw);
- switch (res) {
- case WRONG_PARAMETERS:
- print("Pseudowire could not be added , error in the parameters : \n\t%s",
- res.getSpecificError());
- break;
- case CONFIGURATION_ERROR:
- print("Pseudowire could not be added, configuration error : \n\t%s",
- res.getSpecificError());
- break;
- case PATH_NOT_FOUND:
- print("Pseudowire path not found : \n\t%s",
- res.getSpecificError());
- break;
- case INTERNAL_ERROR:
- print("Pseudowire could not be added, internal error : \n\t%s",
- res.getSpecificError());
- break;
- case SUCCESS:
- break;
- default:
- break;
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireIdCompleter.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireIdCompleter.java
deleted file mode 100644
index abf0c0c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireIdCompleter.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2014-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.stream.Collectors;
-
-/**
- * Device ID completer.
- */
-@Service
-public class PseudowireIdCompleter implements Completer {
- @Override
- public int complete(Session session, CommandLine commandLine, List<String> candidates) {
- // Delegate string completer
- StringsCompleter delegate = new StringsCompleter();
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
-
- List<L2Tunnel> tunnels = srService.getL2Tunnels();
-
- // combine polices and tunnels to pseudowires
- Iterator<String> pseudowires = tunnels.stream()
- .map(l2Tunnel -> Long.toString(l2Tunnel.tunnelId()))
- .collect(Collectors.toList()).iterator();
-
- SortedSet<String> strings = delegate.getStrings();
- while (pseudowires.hasNext()) {
- strings.add(pseudowires.next());
- }
-
- // Now let the completer do the work for figuring out what to offer.
- return delegate.complete(session, commandLine, candidates);
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireListCommand.java
deleted file mode 100644
index 475ce26..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireListCommand.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-/**
- * Command to show the pseudowires.
- */
-@Service
-@Command(scope = "onos", name = "sr-pw-list",
- description = "Lists all pseudowires")
-public class PseudowireListCommand extends AbstractShellCommand {
-
- private static final String FORMAT_PSEUDOWIRE =
- "Pseudowire id = %s \n" +
- " mode : %s, sdTag : %s, pwLabel : %s \n" +
- " cP1 : %s , cP1OuterTag : %s, cP1InnerTag : %s \n" +
- " cP2 : %s , cP2OuterTag : %s, cP2InnerTag : %s \n" +
- " transportVlan : %s \n" +
- " pending = %s";
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- srService.getL2TunnelDescriptions(false)
- .forEach(pw -> printPseudowire(pw, false));
-
- srService.getL2TunnelDescriptions(true)
- .forEach(pw -> printPseudowire(pw, true));
- }
-
- private void printPseudowire(L2TunnelDescription pseudowire, boolean pending) {
- VlanId vlan = pseudowire.l2Tunnel().transportVlan().equals(VlanId.vlanId((short) 4094)) ?
- VlanId.NONE : pseudowire.l2Tunnel().transportVlan();
-
- print(FORMAT_PSEUDOWIRE, pseudowire.l2Tunnel().tunnelId(), pseudowire.l2Tunnel().pwMode(),
- pseudowire.l2Tunnel().sdTag(), pseudowire.l2Tunnel().pwLabel(),
- pseudowire.l2TunnelPolicy().cP1(), pseudowire.l2TunnelPolicy().cP1OuterTag(),
- pseudowire.l2TunnelPolicy().cP1InnerTag(), pseudowire.l2TunnelPolicy().cP2(),
- pseudowire.l2TunnelPolicy().cP2OuterTag(), pseudowire.l2TunnelPolicy().cP2InnerTag(),
- vlan, pending);
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireNextListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireNextListCommand.java
deleted file mode 100644
index f2b3e8d..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireNextListCommand.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the pseudowire next stores.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-pw",
- description = "Displays the current next-id for pseudowire")
-public class PseudowireNextListCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- print(srService.getPwInitNext());
- print(srService.getPwTermNext());
- }
-
- private void print(Map<String, NextObjective> nextStore) {
- ArrayList<String> a = new ArrayList<>(nextStore.keySet());
- a.sort(Comparator.comparing((String o) -> o));
-
- StringBuilder builder = new StringBuilder();
- a.forEach(k ->
- builder.append("\n")
- .append(k)
- .append(" --> ")
- .append(nextStore.get(k).id())
- );
- print(builder.toString());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java
deleted file mode 100644
index 2bb28b0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/PseudowireRemoveCommand.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.parsePwId;
-
-
-/**
- * Command to remove a pseudowire.
- */
-@Service
-@Command(scope = "onos", name = "sr-pw-remove",
- description = "Remove a pseudowire")
-public class PseudowireRemoveCommand extends AbstractShellCommand {
-
- @Argument(index = 0, name = "pwId",
- description = "pseudowire ID",
- required = true, multiValued = false)
- @Completion(PseudowireIdCompleter.class)
- String pwId;
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- // remove the pseudowire
- SegmentRoutingManager mngr = (SegmentRoutingManager) srService;
- int pwIntId;
- try {
- pwIntId = parsePwId(pwId);
- } catch (IllegalArgumentException e) {
- log.error("Exception while parsing pseudowire id : \n\t %s", e.getMessage());
- print("Exception while parsing pseudowire id : \n\t %s", e.getMessage());
- return;
- }
-
- log.info("Removing pseudowire {} from the command line.", pwIntId);
- L2TunnelHandler.Result res = mngr.removePseudowire(pwIntId);
- switch (res) {
- case WRONG_PARAMETERS:
- error("Pseudowire could not be removed , wrong parameters: \n\t %s\n",
- res.getSpecificError());
- break;
- case INTERNAL_ERROR:
- error("Pseudowire could not be removed, internal error : \n\t %s\n",
- res.getSpecificError());
- break;
- case SUCCESS:
- break;
- default:
- break;
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/RerouteNetworkCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/RerouteNetworkCommand.java
deleted file mode 100644
index 6e8d3e9..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/RerouteNetworkCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Command to manually trigger routing and rule-population in the network.
- *
- */
-@Service
-@Command(scope = "onos", name = "sr-reroute-network",
- description = "Repopulate routing rules given current network state")
-public class RerouteNetworkCommand extends AbstractShellCommand {
-
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
- srService.rerouteNetwork();
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/ShouldProgramCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/ShouldProgramCommand.java
deleted file mode 100644
index 250fb3b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/ShouldProgramCommand.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Display current shouldProgram map.
- */
-@Service
-@Command(scope = "onos", name = "sr-should-program",
- description = "Display current shouldProgram map")
-public class ShouldProgramCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- SegmentRoutingService srService = AbstractShellCommand.get(SegmentRoutingService.class);
- Map<Set<DeviceId>, NodeId> shouldProgram = srService.getShouldProgram();
- Map<DeviceId, Boolean> shouldProgramCache = srService.getShouldProgramCache();
-
- print("shouldProgram");
- shouldProgram.forEach((k, v) -> print("%s -> %s", k, v));
-
- print("shouldProgramCache");
- shouldProgramCache.forEach((k, v) -> print("%s -> %s", k, v));
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelAddCommand.java
deleted file mode 100644
index 0e487d0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelAddCommand.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.DefaultTunnel;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-import org.onosproject.segmentrouting.TunnelHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-/**
- * Command to add a new tunnel.
- */
-@Service
-@Command(scope = "onos", name = "sr-tunnel-add",
- description = "Create a new tunnel")
-public class TunnelAddCommand extends AbstractShellCommand {
-
- @Argument(index = 0, name = "tunnel ID",
- description = "tunnel ID",
- required = true, multiValued = false)
- String tunnelId;
-
- @Argument(index = 1, name = "label path",
- description = "label path",
- required = true, multiValued = false)
- String labels;
-
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- List<Integer> labelIds = new ArrayList<>();
- StringTokenizer strToken = new StringTokenizer(labels, ",");
- while (strToken.hasMoreTokens()) {
- labelIds.add(Integer.valueOf(strToken.nextToken()));
- }
- Tunnel tunnel = new DefaultTunnel(tunnelId, labelIds);
-
- TunnelHandler.Result result = srService.createTunnel(tunnel);
- switch (result) {
- case ID_EXISTS:
- print("ERROR: the same tunnel ID exists");
- break;
- case TUNNEL_EXISTS:
- print("ERROR: the same tunnel exists");
- break;
- case INTERNAL_ERROR:
- print("ERROR: internal tunnel creation error");
- break;
- case WRONG_PATH:
- print("ERROR: the tunnel path is wrong");
- break;
- default:
- break;
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelListCommand.java
deleted file mode 100644
index 6c5f33d..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelListCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-
-/**
- * Command to show the list of tunnels.
- */
-@Service
-@Command(scope = "onos", name = "sr-tunnel-list",
- description = "Lists all tunnels")
-public class TunnelListCommand extends AbstractShellCommand {
-
- private static final String FORMAT_MAPPING =
- " id=%s, path=%s";
-
- @Override
- protected void doExecute() {
-
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- srService.getTunnels().forEach(tunnel -> printTunnel(tunnel));
- }
-
- private void printTunnel(Tunnel tunnel) {
- print(FORMAT_MAPPING, tunnel.id(), tunnel.labelIds());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelRemoveCommand.java
deleted file mode 100644
index f5f0299..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/TunnelRemoveCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-
-import com.google.common.collect.Lists;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.DefaultTunnel;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-import org.onosproject.segmentrouting.TunnelHandler;
-
-/**
- * Command to remove a tunnel.
- */
-@Service
-@Command(scope = "onos", name = "sr-tunnel-remove",
- description = "Remove a tunnel")
-public class TunnelRemoveCommand extends AbstractShellCommand {
-
- @Argument(index = 0, name = "tunnel ID",
- description = "tunnel ID",
- required = true, multiValued = false)
- String tunnelId;
-
- @Override
- protected void doExecute() {
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- Tunnel tunnel = new DefaultTunnel(tunnelId, Lists.newArrayList());
- TunnelHandler.Result result = srService.removeTunnel(tunnel);
- switch (result) {
- case TUNNEL_IN_USE:
- print("ERROR: the tunnel is still in use");
- break;
- case TUNNEL_NOT_FOUND:
- print("ERROR: the tunnel is not found");
- break;
- default:
- break;
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/VerifyGroupsCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/VerifyGroupsCommand.java
deleted file mode 100644
index 385260e..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/VerifyGroupsCommand.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-/**
- * Triggers the verification of hashed group buckets in the specified device,
- * and corrects the buckets if necessary. Outcome can be viewed in the 'groups'
- * command.
- */
-@Service
-@Command(scope = "onos", name = "sr-verify-groups",
- description = "Triggers the verification of hashed groups in the specified "
- + "device. Does not return any output; users can query the results "
- + "in the 'groups' command")
-public class VerifyGroupsCommand extends AbstractShellCommand {
-
- @Argument(index = 0, name = "uri", description = "Device ID",
- required = true, multiValued = false)
- @Completion(DeviceIdCompleter.class)
- String uri = null;
-
- @Override
- protected void doExecute() {
- DeviceService deviceService = get(DeviceService.class);
- SegmentRoutingService srService =
- AbstractShellCommand.get(SegmentRoutingService.class);
-
- if (uri != null) {
- Device dev = deviceService.getDevice(DeviceId.deviceId(uri));
- if (dev != null) {
- srService.verifyGroups(dev.id());
- }
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectAddCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectAddCommand.java
deleted file mode 100644
index 22daeb5..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectAddCommand.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import com.google.common.collect.Sets;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.cli.net.PortNumberCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectPortEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-import java.util.Set;
-
-/**
- * Creates Xconnect.
- */
-@Service
-@Command(scope = "onos", name = "sr-xconnect-add", description = "Create Xconnect")
-public class XconnectAddCommand extends AbstractShellCommand {
- private static final String EP_DESC = "Can be a physical port number or a load balancer key. " +
- "Use integer to specify physical port number. " +
- "Use " + XconnectPortEndpoint.LB_KEYWORD + "key to specify load balancer key";
-
- @Argument(index = 0, name = "deviceId",
- description = "Device ID",
- required = true, multiValued = false)
- @Completion(DeviceIdCompleter.class)
- private String deviceIdStr;
-
- @Argument(index = 1, name = "vlanId",
- description = "VLAN ID",
- required = true, multiValued = false)
- @Completion(PlaceholderCompleter.class)
- private String vlanIdStr;
-
- @Argument(index = 2, name = "ep1",
- description = "First endpoint. " + EP_DESC,
- required = true, multiValued = false)
- @Completion(PortNumberCompleter.class)
- private String ep1Str;
-
- @Argument(index = 3, name = "ep2",
- description = "Second endpoint. " + EP_DESC,
- required = true, multiValued = false)
- @Completion(PortNumberCompleter.class)
- private String ep2Str;
-
- private static final String L2LB_PATTERN = "^(\\d*|L2LB\\(\\d*\\))$";
-
- @Override
- protected void doExecute() {
- DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
- VlanId vlanId = VlanId.vlanId(vlanIdStr);
-
- XconnectEndpoint ep1 = XconnectEndpoint.fromString(ep1Str);
- XconnectEndpoint ep2 = XconnectEndpoint.fromString(ep2Str);
-
- Set<XconnectEndpoint> endpoints = Sets.newHashSet(ep1, ep2);
-
- XconnectService xconnectService = get(XconnectService.class);
- xconnectService.addOrUpdateXconnect(deviceId, vlanId, endpoints);
- }
-
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectListCommand.java
deleted file mode 100644
index 44a7d37..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectListCommand.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-/**
- * Lists Xconnects.
- */
-@Service
-@Command(scope = "onos", name = "sr-xconnect", description = "Lists all Xconnects")
-public class XconnectListCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- XconnectService xconnectService = get(XconnectService.class);
- xconnectService.getXconnects().forEach(desc -> print("%s", desc));
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectNextListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectNextListCommand.java
deleted file mode 100644
index 0b81186..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectNextListCommand.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.segmentrouting.xconnect.api.XconnectKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Command to read the current state of the xconnect next stores.
- */
-@Service
-@Command(scope = "onos", name = "sr-next-xconnect",
- description = "Displays the current next-id for xconnect")
-public class XconnectNextListCommand extends AbstractShellCommand {
- @Override
- protected void doExecute() {
- XconnectService xconnectService =
- AbstractShellCommand.get(XconnectService.class);
- print(xconnectService.getNext());
- }
-
- private void print(Map<XconnectKey, Integer> nextStore) {
- ArrayList<XconnectKey> a = new ArrayList<>(nextStore.keySet());
- a.sort(Comparator
- .comparing((XconnectKey o) -> o.deviceId().toString())
- .thenComparing((XconnectKey o) -> o.vlanId().toShort()));
-
- StringBuilder builder = new StringBuilder();
- a.forEach(k ->
- builder.append("\n")
- .append(k)
- .append(" --> ")
- .append(nextStore.get(k))
- );
- print(builder.toString());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectRemoveCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectRemoveCommand.java
deleted file mode 100644
index e651338..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/XconnectRemoveCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.DeviceIdCompleter;
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-
-/**
- * Deletes Xconnect.
- */
-@Service
-@Command(scope = "onos", name = "sr-xconnect-remove", description = "Remove Xconnect")
-public class XconnectRemoveCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "deviceId",
- description = "Device ID",
- required = true, multiValued = false)
- @Completion(DeviceIdCompleter.class)
- private String deviceIdStr;
-
- @Argument(index = 1, name = "vlanId",
- description = "VLAN ID",
- required = true, multiValued = false)
- @Completion(PlaceholderCompleter.class)
- private String vlanIdStr;
-
- @Override
- protected void doExecute() {
- DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
- VlanId vlanId = VlanId.vlanId(vlanIdStr);
-
- XconnectService xconnectService = get(XconnectService.class);
- xconnectService.removeXonnect(deviceId, vlanId);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/package-info.java
deleted file mode 100644
index 0f2cea6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Segment routing application CLI handlers.
- */
-package org.onosproject.segmentrouting.cli;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/BlockedPortsConfig.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/BlockedPortsConfig.java
deleted file mode 100644
index a5c5557..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/BlockedPortsConfig.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.config.Config;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Network config to describe ports that should be blocked until authenticated.
- */
-public class BlockedPortsConfig extends Config<ApplicationId> {
-
- /**
- * Returns the top level keys to the config,
- * which should be device ID strings.
- *
- * @return this list of top level keys
- */
- public List<String> deviceIds() {
- List<String> devIds = new ArrayList<>();
- if (object != null) {
- Iterator<String> it = object.fieldNames();
- if (it != null) {
- it.forEachRemaining(devIds::add);
- }
- }
- return devIds;
- }
-
- /**
- * Returns the port range strings associated with the given device id key.
- *
- * @param deviceId the device id key
- * @return the associated port range strings
- */
- public List<String> portRanges(String deviceId) {
- List<String> portRanges = new ArrayList<>();
- if (object != null) {
- JsonNode jnode = object.get(deviceId);
- if (ArrayNode.class.isInstance(jnode)) {
- ArrayNode array = (ArrayNode) jnode;
- array.forEach(pr -> portRanges.add(pr.asText()));
- }
- }
- return portRanges;
- }
-
- /**
- * Returns an iterator over the port numbers defined by the port ranges
- * defined in the configuration, for the given device.
- *
- * @param deviceId the specific device
- * @return an iterator over the configured ports
- */
- public Iterator<Long> portIterator(String deviceId) {
- List<String> ranges = portRanges(deviceId);
- return new PortIterator(ranges);
- }
-
- /**
- * Private implementation of an iterator that aggregates several range
- * iterators into a single iterator.
- */
- class PortIterator implements Iterator<Long> {
- private final List<Range> ranges;
- private final int nRanges;
- private int currentRange = 0;
- private Iterator<Long> iterator;
-
- PortIterator(List<String> rangeSpecs) {
- nRanges = rangeSpecs.size();
- ranges = new ArrayList<>(nRanges);
- if (nRanges > 0) {
- for (String rs : rangeSpecs) {
- ranges.add(new Range(rs));
- }
- iterator = ranges.get(0).iterator();
- }
- }
-
- @Override
- public boolean hasNext() {
- return nRanges > 0 &&
- (currentRange < nRanges - 1 ||
- (currentRange < nRanges && iterator.hasNext()));
- }
-
- @Override
- public Long next() {
- if (nRanges == 0) {
- throw new NoSuchElementException();
- }
-
- Long value;
- if (iterator.hasNext()) {
- value = iterator.next();
- } else {
- currentRange++;
- if (currentRange < nRanges) {
- iterator = ranges.get(currentRange).iterator();
- value = iterator.next();
- } else {
- throw new NoSuchElementException();
- }
- }
- return value;
- }
- }
-
- /**
- * Private implementation of a "range" of long numbers, defined by a
- * string of the form {@code "<lo>-<hi>"}, for example, "17-32".
- */
- static final class Range {
- private static final Pattern RE_SINGLE = Pattern.compile("(\\d+)");
- private static final Pattern RE_RANGE = Pattern.compile("(\\d+)-(\\d+)");
- private static final String E_BAD_FORMAT = "Bad Range Format ";
-
- private final long lo;
- private final long hi;
-
- /**
- * Constructs a range from the given string definition.
- * For example:
- * <pre>
- * Range r = new Range("17-32");
- * </pre>
- *
- * @param s the string representation of the range
- * @throws IllegalArgumentException if the range string is malformed
- */
- Range(String s) {
- String lohi = s;
- Matcher m = RE_SINGLE.matcher(s);
- if (m.matches()) {
- lohi = s + "-" + s;
- }
- m = RE_RANGE.matcher(lohi);
- if (!m.matches()) {
- throw new IllegalArgumentException(E_BAD_FORMAT + s);
- }
- try {
- lo = Long.parseLong(m.group(1));
- hi = Long.parseLong(m.group(2));
-
- if (hi < lo) {
- throw new IllegalArgumentException(E_BAD_FORMAT + s);
- }
- } catch (NumberFormatException nfe) {
- // unlikely to be thrown, since the matcher will have failed first
- throw new IllegalArgumentException(E_BAD_FORMAT + s, nfe);
- }
- }
-
-
- /**
- * Returns an iterator over this range, starting from the lowest value
- * and iterating up to the highest value (inclusive).
- *
- * @return an iterator over this range
- */
- Iterator<Long> iterator() {
- return new RangeIterator();
- }
-
- /**
- * Private implementation of an iterator over the range.
- */
- class RangeIterator implements Iterator<Long> {
- long current;
-
- RangeIterator() {
- current = lo - 1;
- }
-
- @Override
- public boolean hasNext() {
- return current < hi;
- }
-
- @Override
- public Long next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return ++current;
- }
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java
deleted file mode 100644
index 773c7f6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfigNotFoundException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-/**
- * Signals that an error occurred during reading device configuration.
- */
-public class DeviceConfigNotFoundException extends Exception {
-
- /**
- * Creates a new ConfigNotFoundException with the given message.
- *
- * @param message exception message
- */
- public DeviceConfigNotFoundException(String message) {
- super(message);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
deleted file mode 100644
index d161f63..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.HostId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.ConfigException;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.routeservice.Route;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Segment Routing configuration component that reads the
- * segment routing related configuration from Network Configuration Manager
- * component and organizes in more accessible formats.
- */
-public class DeviceConfiguration implements DeviceProperties {
-
- private static final String NO_SUBNET = "No subnet configured on {}";
-
- private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
- private final List<Integer> allSegmentIds = new ArrayList<>();
- private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
- private SegmentRoutingManager srManager;
-
- private class SegmentRouterInfo {
- int ipv4NodeSid = -1;
- int ipv6NodeSid = -1;
- DeviceId deviceId;
- Ip4Address ipv4Loopback;
- Ip6Address ipv6Loopback;
- MacAddress mac;
- boolean isEdge;
- SetMultimap<PortNumber, IpAddress> gatewayIps;
- SetMultimap<PortNumber, IpPrefix> subnets;
- Map<Integer, Set<Integer>> adjacencySids;
- DeviceId pairDeviceId;
- PortNumber pairLocalPort;
- int pwRoutingLabel;
-
- public SegmentRouterInfo() {
- gatewayIps = Multimaps.synchronizedSetMultimap(HashMultimap.create());
- subnets = Multimaps.synchronizedSetMultimap(HashMultimap.create());
- }
- }
-
- /**
- * Constructs device configuration for all Segment Router devices,
- * organizing the data into various maps for easier access.
- *
- * @param srManager Segment Routing Manager
- */
- public DeviceConfiguration(SegmentRoutingManager srManager) {
- this.srManager = srManager;
- updateConfig();
- }
-
- public void updateConfig() {
- // Read config from device subject, excluding gatewayIps and subnets.
- Set<DeviceId> deviceSubjects =
- srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
- deviceSubjects.forEach(subject -> {
- BasicDeviceConfig basicDeviceConfig = srManager.cfgService.addConfig(subject, BasicDeviceConfig.class);
- if (!basicDeviceConfig.purgeOnDisconnection()) {
- // Setting purge on disconnection flag for the device SR has control over.
- // addConfig returns a config if it exists or creates a new one.
- log.info("PurgeOnDisconnection set to true for device {}", subject);
- basicDeviceConfig.purgeOnDisconnection(true);
- srManager.cfgService.applyConfig(subject, BasicDeviceConfig.class, basicDeviceConfig.node());
- }
- SegmentRoutingDeviceConfig config =
- srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
- SegmentRouterInfo info = new SegmentRouterInfo();
- info.deviceId = subject;
- info.ipv4NodeSid = config.nodeSidIPv4();
- info.ipv6NodeSid = config.nodeSidIPv6();
- info.ipv4Loopback = config.routerIpv4();
- info.ipv6Loopback = config.routerIpv6();
- info.mac = config.routerMac();
- info.isEdge = config.isEdgeRouter();
- info.adjacencySids = config.adjacencySids();
- info.pairDeviceId = config.pairDeviceId();
- info.pairLocalPort = config.pairLocalPort();
- info.pwRoutingLabel = info.ipv4NodeSid + 1000;
- deviceConfigMap.put(info.deviceId, info);
- log.debug("Read device config for device: {}", info.deviceId);
- /*
- * IPv6 sid is not inserted. this part of the code is not used for now.
- */
- allSegmentIds.add(info.ipv4NodeSid);
- });
-
- // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
- Set<ConnectPoint> portSubjects = srManager.cfgService
- .getSubjects(ConnectPoint.class, InterfaceConfig.class);
- portSubjects.stream()
- .filter(subject -> deviceConfigMap.containsKey(subject.deviceId()))
- .filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
- InterfaceConfig config =
- srManager.cfgService.getConfig(subject, InterfaceConfig.class);
- Set<Interface> networkInterfaces;
- try {
- networkInterfaces = config.getInterfaces();
- } catch (ConfigException e) {
- log.error("Error loading port configuration");
- return;
- }
- networkInterfaces.forEach(networkInterface -> {
- VlanId vlanId = networkInterface.vlan();
- ConnectPoint connectPoint = networkInterface.connectPoint();
- DeviceId dpid = connectPoint.deviceId();
- PortNumber port = connectPoint.port();
- MacAddress mac = networkInterface.mac();
- SegmentRouterInfo info = deviceConfigMap.get(dpid);
-
- // skip if there is no corresponding device for this ConenctPoint
- if (info != null) {
- // Extract subnet information
- List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
- interfaceAddresses.forEach(interfaceAddress -> {
- // Do not add /0, /32 and /128 to gateway IP list
- int prefixLength = interfaceAddress.subnetAddress().prefixLength();
- IpPrefix ipPrefix = interfaceAddress.subnetAddress();
- if (ipPrefix.isIp4()) {
- if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
- info.gatewayIps.put(port, interfaceAddress.ipAddress());
- }
- info.subnets.put(port, interfaceAddress.subnetAddress());
- } else {
- if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET6_MASK_LENGTH) {
- info.gatewayIps.put(port, interfaceAddress.ipAddress());
- }
- info.subnets.put(port, interfaceAddress.subnetAddress());
- }
- });
-
- // Override interface mac with router mac
- if (!mac.equals(info.mac)) {
- ArrayNode array = (ArrayNode) config.node();
- for (JsonNode intfNode : array) {
- ObjectNode objNode = (ObjectNode) intfNode;
- objNode.put(InterfaceConfig.MAC, info.mac.toString());
- }
- srManager.cfgService.applyConfig(connectPoint, InterfaceConfig.class, array);
- }
- }
- });
- // We register the connect point with the NRS.
- srManager.registerConnectPoint(subject);
- });
- }
-
- public Collection<DeviceId> getRouters() {
- return deviceConfigMap.keySet();
- }
-
- @Override
- public boolean isConfigured(DeviceId deviceId) {
- return deviceConfigMap.get(deviceId) != null;
- }
-
- @Override
- public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
- return srinfo.ipv4NodeSid;
- } else {
- String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- @Override
- public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
- return srinfo.ipv6NodeSid;
- } else {
- String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- @Override
- public int getPWRoutingLabel(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- log.trace("pwRoutingLabel for device{} is {}", deviceId, srinfo.pwRoutingLabel);
- return srinfo.pwRoutingLabel;
- } else {
- String message = "getPWRoutingLabel fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- /**
- * Returns the IPv4 Node segment id of a segment router given its Router mac address.
- *
- * @param routerMac router mac address
- * @return node segment id, or -1 if not found in config
- */
- public int getIPv4SegmentId(MacAddress routerMac) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
- deviceConfigMap.entrySet()) {
- if (entry.getValue().mac.equals(routerMac)) {
- return entry.getValue().ipv4NodeSid;
- }
- }
-
- return -1;
- }
-
- /**
- * Returns the IPv6 Node segment id of a segment router given its Router mac address.
- *
- * @param routerMac router mac address
- * @return node segment id, or -1 if not found in config
- */
- public int getIPv6SegmentId(MacAddress routerMac) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
- deviceConfigMap.entrySet()) {
- if (entry.getValue().mac.equals(routerMac)) {
- return entry.getValue().ipv6NodeSid;
- }
- }
-
- return -1;
- }
-
- /**
- * Returns the IPv4 Node segment id of a segment router given its Router ip address.
- *
- * @param routerAddress router ip address
- * @return node segment id, or -1 if not found in config
- */
- public int getIPv4SegmentId(Ip4Address routerAddress) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
- Ip4Address ipv4Loopback = entry.getValue().ipv4Loopback;
- if (ipv4Loopback == null) {
- continue;
- }
- if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
- if (entry.getValue().ipv4NodeSid == -1) {
- continue;
- }
- return entry.getValue().ipv4NodeSid;
- }
- }
-
- return -1;
- }
-
- /**
- * Returns the IPv6 Node segment id of a segment router given its Router ip address.
- *
- * @param routerAddress router ip address
- * @return node segment id, or -1 if not found in config
- */
- public int getIPv6SegmentId(Ip6Address routerAddress) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
- Ip6Address ipv6Loopback = entry.getValue().ipv6Loopback;
- if (ipv6Loopback == null) {
- continue;
- }
- if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
- if (entry.getValue().ipv6NodeSid == -1) {
- continue;
- }
- return entry.getValue().ipv6NodeSid;
- }
- }
-
- return -1;
- }
-
- @Override
- public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- return srinfo.mac;
- } else {
- String message = "getDeviceMac fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- @Override
- public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
- return srinfo.ipv4Loopback;
- } else {
- String message = "getRouterIpv4 fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- @Override
- public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
- return srinfo.ipv6Loopback;
- } else {
- String message = "getRouterIpv6 fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- /**
- * Gets router ip address based on the destination ip address.
- *
- * @param destIpAddress the destination ip address
- * @param routerDeviceId the device id
- * @return the ip address of the routes
- */
- public IpAddress getRouterIpAddress(IpAddress destIpAddress, DeviceId routerDeviceId) {
- IpAddress routerIpAddress;
- try {
- routerIpAddress = destIpAddress.isIp4() ? getRouterIpv4(routerDeviceId) :
- getRouterIpv6(routerDeviceId);
- } catch (DeviceConfigNotFoundException e) {
- routerIpAddress = null;
- }
- return routerIpAddress;
- }
-
- @Override
- public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
- return srinfo.isEdge;
- } else {
- String message = "isEdgeDevice fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- @Override
- public List<Integer> getAllDeviceSegmentIds() {
- return allSegmentIds;
- }
-
- @Override
- public Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
- throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo == null) {
- String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- // Construct subnet-port mapping from port-subnet mapping
- SetMultimap<PortNumber, IpPrefix> portSubnetMap = srinfo.subnets;
- Map<IpPrefix, List<PortNumber>> subnetPortMap = new HashMap<>();
-
- portSubnetMap.entries().forEach(entry -> {
- PortNumber port = entry.getKey();
- IpPrefix subnet = entry.getValue();
-
- if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
- subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
- return;
- }
-
- if (subnetPortMap.containsKey(subnet)) {
- subnetPortMap.get(subnet).add(port);
- } else {
- ArrayList<PortNumber> ports = new ArrayList<>();
- ports.add(port);
- subnetPortMap.put(subnet, ports);
- }
- });
- return subnetPortMap;
- }
-
- /**
- * Returns the device identifier or data plane identifier (dpid)
- * of a segment router given its segment id.
- *
- * @param sid segment id
- * @return deviceId device identifier
- */
- public DeviceId getDeviceId(int sid) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
- deviceConfigMap.entrySet()) {
- if (entry.getValue().ipv4NodeSid == sid ||
- entry.getValue().ipv6NodeSid == sid) {
- return entry.getValue().deviceId;
- }
- }
-
- return null;
- }
-
- /**
- * Returns the device identifier or data plane identifier (dpid)
- * of a segment router given its router ip address.
- *
- * @param ipAddress router ip address
- * @return deviceId device identifier
- */
- public DeviceId getDeviceId(Ip4Address ipAddress) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
- deviceConfigMap.entrySet()) {
- if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
- return entry.getValue().deviceId;
- }
- }
-
- return null;
- }
-
- /**
- * Returns the device identifier or data plane identifier (dpid)
- * of a segment router given its router ipv6 address.
- *
- * @param ipAddress router ipv6 address
- * @return deviceId device identifier
- */
- public DeviceId getDeviceId(Ip6Address ipAddress) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
- deviceConfigMap.entrySet()) {
- if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
- return entry.getValue().deviceId;
- }
- }
-
- return null;
- }
-
- /**
- * Returns the configured port ip addresses for a segment router.
- * These addresses serve as gateway IP addresses for the subnets configured
- * on those ports.
- *
- * @param deviceId device identifier
- * @return immutable set of ip addresses configured on the ports or null if not found
- */
- public Set<IpAddress> getPortIPs(DeviceId deviceId) {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
- srinfo.gatewayIps.values());
- return ImmutableSet.copyOf(srinfo.gatewayIps.values());
- }
- return null;
- }
-
- /**
- * Returns configured subnets for a segment router.
- *
- * @param deviceId device identifier
- * @return list of ip prefixes or null if not found
- */
- public Set<IpPrefix> getConfiguredSubnets(DeviceId deviceId) {
- Set<IpPrefix> subnets = srManager.interfaceService.getInterfaces().stream()
- .filter(intf -> Objects.equals(deviceId, intf.connectPoint().deviceId()))
- .flatMap(intf -> intf.ipAddressesList().stream())
- .map(InterfaceIpAddress::subnetAddress)
- .collect(Collectors.toSet());
-
- if (subnets.isEmpty()) {
- log.debug(NO_SUBNET, deviceId);
- return Collections.emptySet();
- }
- return subnets;
- }
-
- /**
- * Returns all subnets for a segment router, including subnets learnt from route service.
- *
- * @param deviceId device identifier
- * @return set of ip prefixes or null if not found
- * @deprecated use getBatchedSubnets(DeviceId deviceId) instead
- */
- @Deprecated
- public Set<IpPrefix> getSubnets(DeviceId deviceId) {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null && srinfo.subnets != null) {
- // Note: ImmutableSet.Builder.addAll calls the iterator of parameter internally,
- // which is not protected by SynchronizedCollection mutex.
- ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
- srinfo.subnets.forEach((k, v) -> builder.add(v));
- return builder.build();
- }
- return null;
- }
-
- /**
- * Returns batches of all subnets reachable via given next hop
- * <p>
- * First batch includes FPM and STATIC routes
- * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
- *
- * @param hostId next hop host id
- * @return list of subnet batches, each batch includes a set of prefixes.
- */
- // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
- public List<Set<IpPrefix>> getBatchedSubnets(HostId hostId) {
- Set<IpPrefix> high = Sets.newHashSet();
- Set<IpPrefix> low = Sets.newHashSet();
-
- srManager.routeService.getRouteTables().stream()
- .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
- .flatMap(Collection::stream)
- .forEach(resolvedRoute -> {
- // Continue if next hop is not what we are looking for
- if (!Objects.equals(hostId.mac(), resolvedRoute.nextHopMac()) ||
- !Objects.equals(hostId.vlanId(), resolvedRoute.nextHopVlan())) {
- return;
- }
- // Prioritize STATIC and FPM among others
- if (resolvedRoute.route().source() == Route.Source.STATIC ||
- resolvedRoute.route().source() == Route.Source.FPM) {
- high.add(resolvedRoute.prefix());
- } else {
- low.add(resolvedRoute.prefix());
- }
- });
- return Stream.of(high, low).filter(set -> !set.isEmpty()).collect(Collectors.toList());
- }
-
- /**
- * Returns batches of all subnets reachable on the given device.
- * <p>
- * First batch includes configured subnets, FPM and STATIC routes
- * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
- *
- * @param deviceId device identifier
- * @return list of subnet batches, each batch includes a set of prefixes.
- */
- // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
- public List<Set<IpPrefix>> getBatchedSubnets(DeviceId deviceId) {
- Set<IpPrefix> high = Sets.newHashSet();
- Set<IpPrefix> low = Sets.newHashSet();
-
- high.addAll(getConfiguredSubnets(deviceId));
- srManager.routeService.getRouteTables().stream()
- .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
- .flatMap(Collection::stream)
- .forEach(resolvedRoute -> {
- // Continue to next resolved route if none of the next hop attaches to given device
- if (srManager.nextHopLocations(resolvedRoute).stream()
- .noneMatch(cp -> Objects.equals(deviceId, cp.deviceId()))) {
- return;
- }
- // Prioritize STATIC and FPM among others
- if (resolvedRoute.route().source() == Route.Source.STATIC ||
- resolvedRoute.route().source() == Route.Source.FPM) {
- high.add(resolvedRoute.prefix());
- } else {
- low.add(resolvedRoute.prefix());
- }
- });
- return Lists.newArrayList(high, low);
- }
-
- /**
- * Returns the subnet configuration of given device and port.
- *
- * @param deviceId Device ID
- * @param port Port number
- * @return The subnets configured on given port or empty set if
- * the port is unconfigured or suppressed.
- */
- public Set<IpPrefix> getPortSubnets(DeviceId deviceId, PortNumber port) {
- ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
-
- if (isSuppressedPort(connectPoint)) {
- return Collections.emptySet();
- }
-
- Set<IpPrefix> subnets = srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
- .flatMap(intf -> intf.ipAddressesList().stream())
- .map(InterfaceIpAddress::subnetAddress)
- .collect(Collectors.toSet());
-
- if (subnets.isEmpty()) {
- log.debug(NO_SUBNET, connectPoint);
- return Collections.emptySet();
- }
- return subnets;
- }
-
- /**
- * Returns all ports that has a subnet that contains any of the given IP addresses.
- *
- * @param ips a set of IP addresses
- * @return a set of connect point that has a subnet that contains any of the given IP addresses
- */
- public Set<ConnectPoint> getPortByIps(Set<IpAddress> ips) {
- return srManager.interfaceService.getInterfaces().stream()
- .filter(intf -> intf.ipAddressesList().stream().anyMatch(intfAddress ->
- ips.stream().anyMatch(ip -> intfAddress.subnetAddress().contains(ip))))
- .map(Interface::connectPoint)
- .collect(Collectors.toSet());
- }
-
- /**
- * Returns all the connect points of the segment routers that have the
- * specified ip address in their subnets.
- *
- * @param destIpAddress target ip address
- * @return connect points of the segment routers
- */
- public Set<ConnectPoint> getConnectPointsForASubnetHost(IpAddress destIpAddress) {
- return srManager.interfaceService.getMatchingInterfaces(destIpAddress).stream()
- .map(Interface::connectPoint)
- .collect(Collectors.toSet());
- }
-
- /**
- * Returns the router ip address of segment router that has the
- * specified ip address in its subnets.
- *
- * @param destIpAddress target ip address
- * @return router ip address
- */
- public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
- Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
-
- if (matchIntf == null) {
- log.debug("No router was found for {}", destIpAddress);
- return null;
- }
-
- DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
- SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
- if (srInfo == null) {
- log.debug("No device config was found for {}", routerDeviceId);
- return null;
- }
-
- return srInfo.ipv4Loopback;
- }
-
- /**
- * Returns the router ipv6 address of segment router that has the
- * specified ip address in its subnets.
- *
- * @param destIpAddress target ip address
- * @return router ip address
- */
- public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
- Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
-
- if (matchIntf == null) {
- log.debug("No router was found for {}", destIpAddress);
- return null;
- }
-
- DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
- SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
- if (srInfo == null) {
- log.debug("No device config was found for {}", routerDeviceId);
- return null;
- }
-
- return srInfo.ipv6Loopback;
- }
-
- /**
- * Returns the router mac address of segment router that has the
- * specified ip address as one of its subnet gateway ip address.
- *
- * @param gatewayIpAddress router gateway ip address
- * @return router mac address or null if not found
- */
- public MacAddress getRouterMacForAGatewayIp(IpAddress gatewayIpAddress) {
- for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
- deviceConfigMap.entrySet()) {
- if (entry.getValue().gatewayIps.
- values().contains(gatewayIpAddress)) {
- return entry.getValue().mac;
- }
- }
-
- log.debug("Cannot find a router for {}", gatewayIpAddress);
- return null;
- }
-
- /**
- * Checks if the host IP is in any of the subnet defined in the router with the
- * device ID given.
- *
- * @param deviceId device identification of the router
- * @param hostIp host IP address to check
- * @return true if the given IP is within any of the subnet defined in the router,
- * false if no subnet is defined in the router or if the host is not
- * within any subnet defined in the router
- */
- public boolean inSameSubnet(DeviceId deviceId, IpAddress hostIp) {
- Set<IpPrefix> subnets = getConfiguredSubnets(deviceId);
- if (subnets == null) {
- return false;
- }
-
- for (IpPrefix subnet: subnets) {
- // Exclude /0 since it is a special case used for default route
- if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if the IP is in the subnet defined on given connect point.
- *
- * @param connectPoint Connect point
- * @param ip The IP address to check
- * @return True if the IP belongs to the subnet.
- * False if the IP does not belong to the subnet, or
- * there is no subnet configuration on given connect point.
- */
- public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
- return getPortSubnets(connectPoint.deviceId(), connectPoint.port()).stream()
- .anyMatch(ipPrefix -> ipPrefix.contains(ip));
- }
-
- /**
- * Returns the ports corresponding to the adjacency Sid given.
- *
- * @param deviceId device identification of the router
- * @param sid adjacency Sid
- * @return set of port numbers
- */
- public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- return srinfo != null ?
- ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
- ImmutableSet.copyOf(new HashSet<>());
- }
-
- /**
- * Check if the Sid given is whether adjacency Sid of the router device or not.
- *
- * @param deviceId device identification of the router
- * @param sid Sid to check
- * @return true if the Sid given is the adjacency Sid of the device,
- * otherwise false
- */
- public boolean isAdjacencySid(DeviceId deviceId, int sid) {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- return srinfo != null && srinfo.adjacencySids.containsKey(sid);
- }
-
- /**
- * Add subnet to specific connect point.
- *
- * @param cp connect point
- * @param ipPrefix subnet being added to the device
- */
- public void addSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
- checkNotNull(cp);
- checkNotNull(ipPrefix);
- SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
- if (srinfo == null) {
- log.warn("Device {} is not configured. Abort.", cp.deviceId());
- return;
- }
- srinfo.subnets.put(cp.port(), ipPrefix);
- }
-
- /**
- * Remove subnet from specific connect point.
- *
- * @param cp connect point
- * @param ipPrefix subnet being removed to the device
- */
- public void removeSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
- checkNotNull(cp);
- checkNotNull(ipPrefix);
- SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
- if (srinfo == null) {
- log.warn("Device {} is not configured. Abort.", cp.deviceId());
- return;
- }
- srinfo.subnets.remove(cp.port(), ipPrefix);
- }
-
- private boolean isSuppressedPort(ConnectPoint connectPoint) {
- SegmentRoutingAppConfig appConfig = srManager.cfgService
- .getConfig(srManager.appId(), SegmentRoutingAppConfig.class);
- if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
- log.info("Interface configuration on port {} is ignored", connectPoint);
- return true;
- }
- return false;
- }
-
- public boolean isPairedEdge(DeviceId deviceId) throws DeviceConfigNotFoundException {
- if (!isEdgeDevice(deviceId)) {
- return false;
- }
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- return (srinfo.pairDeviceId == null) ? false : true;
- }
-
- public DeviceId getPairDeviceId(DeviceId deviceId) throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- return srinfo.pairDeviceId;
- } else {
- String message = "getPairDeviceId fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- public PortNumber getPairLocalPort(DeviceId deviceId)
- throws DeviceConfigNotFoundException {
- SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
- if (srinfo != null) {
- return srinfo.pairLocalPort;
- } else {
- String message = "getPairLocalPort fails for device: " + deviceId + ".";
- throw new DeviceConfigNotFoundException(message);
- }
- }
-
- public boolean isPairLocalPort(DeviceId devId, PortNumber pnum) {
- return pnum.equals(srManager.getPairLocalPort(devId).orElse(null));
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
deleted file mode 100644
index 2d0bbd2..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.config;
-
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Mechanism through which group handler module retrieves
- * the device specific attributes such as segment ID,
- * Mac address...etc from group handler applications.
- */
-public interface DeviceProperties {
- /**
- * Checks if the device is configured.
- *
- * @param deviceId device identifier
- * @return true if the device is configured
- */
- boolean isConfigured(DeviceId deviceId);
-
- /**
- * Returns the IPv4 segment id of a device to be used in group creation.
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return segment id of a device
- */
- int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
- /**
- * Returns the IPv6 segment id of a device to be used in group creation.
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return segment id of a device
- */
- int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
- /**
- * Returns the Mac address of a device to be used in group creation.
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return mac address of a device
- */
- MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
- /**
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return the pseudowire routing label for a leaf node
- */
- int getPWRoutingLabel(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
- /**
- * Returns the router ipv4 address of a segment router.
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return router ip address
- */
- IpAddress getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
- /**
- * Returns the router ipv6 address of a segment router.
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return router ip address
- */
- IpAddress getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
- /**
- * Indicates whether a device is edge device or transit/core device.
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return boolean
- */
- boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException;
-
- /**
- * Returns all segment IDs to be considered in building auto
- *
- * created groups.
- * @return list of segment IDs
- */
- List<Integer> getAllDeviceSegmentIds();
-
- /**
- * Returns subnet-to-ports mapping of given device.
- *
- * For each entry of the map
- * Key: a subnet
- * Value: a list of ports, which are bound to the subnet
- *
- * @param deviceId device identifier
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return a map that contains all subnet-to-ports mapping of given device
- */
- Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
- throws DeviceConfigNotFoundException;
-}
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
deleted file mode 100644
index de6ffb9..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-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;
-import org.onosproject.net.config.Config;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * App configuration object for Segment Routing.
- */
-public class SegmentRoutingAppConfig extends Config<ApplicationId> {
-
- private static Logger log = LoggerFactory.getLogger(SegmentRoutingAppConfig.class);
-
- private static final String VROUTER_MACS = "vRouterMacs";
- private static final String SUPPRESS_SUBNET = "suppressSubnet";
- private static final String SUPPRESS_HOST_BY_PORT = "suppressHostByPort";
- // 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, BLACKHOLE_IPS) &&
- vRouterMacs() != null &&
- suppressSubnet() != null && suppressHostByPort() != 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) {
- try {
- address = IpPrefix.valueOf(addrStr);
- builder.add(address);
- } catch (IllegalArgumentException e) {
- log.debug("Not adding {}", jsonNode, e);
- }
- }
- }
- 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;
- }
-
- /**
- * Gets MPLS-ECMP configuration from the config.
- *
- * @return the configuration of MPLS-ECMP. If it is not
- * specified, the default behavior is false.
- */
- public boolean mplsEcmp() {
- return get(MPLS_ECMP, false);
- }
-
- /**
- * Sets MPLS-ECMP to the config.
- *
- * @param mplsEcmp the MPLS-ECMP configuration
- * @return this {@link SegmentRoutingAppConfig}
- */
- public SegmentRoutingAppConfig setMplsEcmp(boolean mplsEcmp) {
- object.put(MPLS_ECMP, mplsEcmp);
- return this;
- }
-
- /**
- * Gets vRouters from the config.
- *
- * @return Set of vRouter MAC addresses, empty is not specified,
- * or null if not valid
- */
- public Set<MacAddress> vRouterMacs() {
- if (!object.has(VROUTER_MACS)) {
- return ImmutableSet.of();
- }
-
- ImmutableSet.Builder<MacAddress> builder = ImmutableSet.builder();
- ArrayNode arrayNode = (ArrayNode) object.path(VROUTER_MACS);
- for (JsonNode jsonNode : arrayNode) {
- MacAddress mac;
-
- String macStr = jsonNode.asText(null);
- if (macStr == null) {
- return null;
- }
- try {
- mac = MacAddress.valueOf(macStr);
- } catch (IllegalArgumentException e) {
- return null;
- }
-
- builder.add(mac);
- }
- return builder.build();
- }
-
- /**
- * Sets vRouters to the config.
- *
- * @param vRouterMacs a set of vRouter MAC addresses
- * @return this {@link SegmentRoutingAppConfig}
- */
- public SegmentRoutingAppConfig setVRouterMacs(Set<MacAddress> vRouterMacs) {
- if (vRouterMacs == null) {
- object.remove(VROUTER_MACS);
- } else {
- ArrayNode arrayNode = mapper.createArrayNode();
-
- vRouterMacs.forEach(mac -> {
- arrayNode.add(mac.toString());
- });
-
- object.set(VROUTER_MACS, arrayNode);
- }
- return this;
- }
-
- /**
- * Gets names of ports to which SegmentRouting does not push subnet rules.
- *
- * @return Set of port names, empty if not specified, or null
- * if not valid
- */
- public Set<ConnectPoint> suppressSubnet() {
- if (!object.has(SUPPRESS_SUBNET)) {
- return ImmutableSet.of();
- }
-
- ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
- ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_SUBNET);
- for (JsonNode jsonNode : arrayNode) {
- String portName = jsonNode.asText(null);
- if (portName == null) {
- return null;
- }
- try {
- builder.add(ConnectPoint.deviceConnectPoint(portName));
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- return builder.build();
- }
-
- /**
- * Sets names of ports to which SegmentRouting does not push subnet rules.
- *
- * @param suppressSubnet names of ports to which SegmentRouting does not push
- * subnet rules
- * @return this {@link SegmentRoutingAppConfig}
- */
- public SegmentRoutingAppConfig setSuppressSubnet(Set<ConnectPoint> suppressSubnet) {
- if (suppressSubnet == null) {
- object.remove(SUPPRESS_SUBNET);
- } else {
- ArrayNode arrayNode = mapper.createArrayNode();
- suppressSubnet.forEach(connectPoint -> {
- arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
- });
- object.set(SUPPRESS_SUBNET, arrayNode);
- }
- return this;
- }
-
- /**
- * Gets connect points to which SegmentRouting does not push host rules.
- *
- * @return Set of connect points, empty if not specified, or null
- * if not valid
- */
- public Set<ConnectPoint> suppressHostByPort() {
- if (!object.has(SUPPRESS_HOST_BY_PORT)) {
- return ImmutableSet.of();
- }
-
- ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
- ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PORT);
- for (JsonNode jsonNode : arrayNode) {
- String portName = jsonNode.asText(null);
- if (portName == null) {
- return null;
- }
- try {
- builder.add(ConnectPoint.deviceConnectPoint(portName));
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
- return builder.build();
- }
-
- /**
- * Sets connect points to which SegmentRouting does not push host rules.
- *
- * @param connectPoints connect points to which SegmentRouting does not push
- * host rules
- * @return this {@link SegmentRoutingAppConfig}
- */
- public SegmentRoutingAppConfig setSuppressHostByPort(Set<ConnectPoint> connectPoints) {
- if (connectPoints == null) {
- object.remove(SUPPRESS_HOST_BY_PORT);
- } else {
- ArrayNode arrayNode = mapper.createArrayNode();
- connectPoints.forEach(connectPoint -> {
- arrayNode.add(connectPoint.deviceId() + "/" + connectPoint.port());
- });
- object.set(SUPPRESS_HOST_BY_PORT, arrayNode);
- }
- return this;
- }
-
- /**
- * Gets provider names from which SegmentRouting does not learn host info.
- *
- * @return array of provider names that need to be ignored
- */
- public Set<String> suppressHostByProvider() {
- if (!object.has(SUPPRESS_HOST_BY_PROVIDER)) {
- return ImmutableSet.of();
- }
-
- ImmutableSet.Builder<String> builder = ImmutableSet.builder();
- ArrayNode arrayNode = (ArrayNode) object.path(SUPPRESS_HOST_BY_PROVIDER);
- for (JsonNode jsonNode : arrayNode) {
- String providerName = jsonNode.asText(null);
- if (providerName == null) {
- return null;
- }
- builder.add(providerName);
- }
- return builder.build();
- }
-
- /**
- * Sets provider names from which SegmentRouting does not learn host info.
- *
- * @param providers set of provider names
- * @return this {@link SegmentRoutingAppConfig}
- */
- public SegmentRoutingAppConfig setSuppressHostByProvider(Set<String> providers) {
- if (providers == null) {
- object.remove(SUPPRESS_HOST_BY_PROVIDER);
- } else {
- ArrayNode arrayNode = mapper.createArrayNode();
- providers.forEach(arrayNode::add);
- object.set(SUPPRESS_HOST_BY_PROVIDER, arrayNode);
- }
- return this;
- }
-
- @Override
- public String toString() {
- return toStringHelper(this)
- .add("vRouterMacs", vRouterMacs())
- .add("suppressSubnet", suppressSubnet())
- .add("suppressHostByPort", suppressHostByPort())
- .add("suppressHostByProvider", suppressHostByProvider())
- .add("mplsEcmp", mplsEcmp())
- .add("blackholeIps", blackholeIPs())
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
deleted file mode 100644
index 7959df6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfig.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableMap;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * Configuration object for Segment Routing Application.
- */
-public class SegmentRoutingDeviceConfig extends Config<DeviceId> {
- private static final String NAME = "name";
- private static final String IP4 = "ipv4Loopback";
- private static final String IP6 = "ipv6Loopback";
- private static final String MAC = "routerMac";
- private static final String IP4_SID = "ipv4NodeSid";
- private static final String IP6_SID = "ipv6NodeSid";
- private static final String EDGE = "isEdgeRouter";
- /**
- * Adjancency SIDs config.
- *
- * @deprecated in Loon (1.11). We are not using and do not plan to use it.
- */
- @Deprecated
- private static final String ADJSIDS = "adjacencySids";
-
- /**
- * Adjancency SID config.
- *
- * @deprecated in Loon (1.11). We are not using and do not plan to use it.
- */
- @Deprecated
- private static final String ADJSID = "adjSid";
-
- /**
- * Adjancency port config.
- *
- * @deprecated in Loon (1.11). We are not using and do not plan to use it.
- */
- @Deprecated
- private static final String PORTS = "ports";
-
- private static final String PAIR_DEVICE_ID = "pairDeviceId";
- private static final String PAIR_LOCAL_PORT = "pairLocalPort";
-
- @Override
- public boolean isValid() {
- return hasOnlyFields(NAME, IP4, IP6, MAC, IP4_SID, IP6_SID, EDGE, ADJSIDS, ADJSID, PORTS,
- PAIR_DEVICE_ID, PAIR_LOCAL_PORT) &&
- name() != null &&
- routerIpv4() != null && (!hasField(IP6) || routerIpv6() != null) &&
- routerMac() != null &&
- nodeSidIPv4() != -1 && (!hasField(IP6_SID) || nodeSidIPv6() != -1) &&
- isEdgeRouter() != null &&
- adjacencySids() != null &&
- // pairDeviceId and pairLocalPort must be both configured or both omitted
- (hasField(PAIR_DEVICE_ID) == hasField(PAIR_LOCAL_PORT)) &&
- (!hasField(PAIR_DEVICE_ID) || pairDeviceId() != null) &&
- (!hasField(PAIR_LOCAL_PORT) || pairLocalPort() != null);
- }
-
- /**
- * Gets the name of the router.
- *
- * @return Optional name of the router. May be empty if not configured.
- */
- public Optional<String> name() {
- String name = get(NAME, null);
- return name != null ? Optional.of(name) : Optional.empty();
- }
-
- /**
- * Sets the name of the router.
- *
- * @param name name of the router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setName(String name) {
- return (SegmentRoutingDeviceConfig) setOrClear(NAME, name);
- }
-
- /**
- * Gets the IPv4 address of the router.
- *
- * @return IP address of the router. Or null if not configured.
- */
- public Ip4Address routerIpv4() {
- String ip = get(IP4, null);
- return ip != null ? Ip4Address.valueOf(ip) : null;
- }
-
- /**
- * Gets the IPv6 address of the router.
- *
- * @return IP address of the router. Or null if not configured.
- */
- public Ip6Address routerIpv6() {
- String ip = get(IP6, null);
- return ip != null ? Ip6Address.valueOf(ip) : null;
- }
-
- /**
- * Sets the IPv4 address of the router.
- *
- * @param ip IPv4 address of the router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setRouterIpv4(String ip) {
- return (SegmentRoutingDeviceConfig) setOrClear(IP4, ip);
- }
-
- /**
- * Sets the IPv6 address of the router.
- *
- * @param ip IPv6 address of the router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setRouterIpv6(String ip) {
- return (SegmentRoutingDeviceConfig) setOrClear(IP6, ip);
- }
-
- /**
- * Gets the MAC address of the router.
- *
- * @return MAC address of the router. Or null if not configured.
- */
- public MacAddress routerMac() {
- String mac = get(MAC, null);
- return mac != null ? MacAddress.valueOf(mac) : null;
- }
-
- /**
- * Sets the MAC address of the router.
- *
- * @param mac MAC address of the router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setRouterMac(String mac) {
- return (SegmentRoutingDeviceConfig) setOrClear(MAC, mac);
- }
-
- /**
- * Gets the IPv4 node SID of the router.
- *
- * @return node SID of the router. Or -1 if not configured.
- */
- public int nodeSidIPv4() {
- return get(IP4_SID, -1);
- }
-
- /**
- * Gets the IPv6 node SID of the router.
- *
- * @return node SID of the router. Or -1 if not configured.
- */
- public int nodeSidIPv6() {
- return get(IP6_SID, -1);
- }
-
- /**
- * Sets the node IPv4 node SID of the router.
- *
- * @param sid node SID of the router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setNodeSidIPv4(int sid) {
- return (SegmentRoutingDeviceConfig) setOrClear(IP4_SID, sid);
- }
-
- /**
- * Sets the node IPv6 node SID of the router.
- *
- * @param sid node SID of the router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setNodeSidIPv6(int sid) {
- return (SegmentRoutingDeviceConfig) setOrClear(IP6_SID, sid);
- }
-
- /**
- * Checks if the router is an edge router.
- *
- * @return true if the router is an edge router.
- * false if the router is not an edge router.
- * null if the value is not configured.
- */
- public Boolean isEdgeRouter() {
- String isEdgeRouter = get(EDGE, null);
- return isEdgeRouter != null ?
- Boolean.valueOf(isEdgeRouter) :
- null;
- }
-
- /**
- * Specifies if the router is an edge router.
- *
- * @param isEdgeRouter true if the router is an edge router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setIsEdgeRouter(boolean isEdgeRouter) {
- return (SegmentRoutingDeviceConfig) setOrClear(EDGE, isEdgeRouter);
- }
-
- /**
- * Gets the adjacency SIDs of the router.
- *
- * @return adjacency SIDs of the router. Or null if not configured.
- */
- public Map<Integer, Set<Integer>> adjacencySids() {
- if (!object.has(ADJSIDS)) {
- return null;
- }
-
- Map<Integer, Set<Integer>> adjacencySids = new HashMap<>();
- ArrayNode adjacencySidsNode = (ArrayNode) object.path(ADJSIDS);
- for (JsonNode adjacencySidNode : adjacencySidsNode) {
- int asid = adjacencySidNode.path(ADJSID).asInt(-1);
- if (asid == -1) {
- return null;
- }
-
- HashSet<Integer> ports = new HashSet<>();
- ArrayNode portsNode = (ArrayNode) adjacencySidNode.path(PORTS);
- for (JsonNode portNode : portsNode) {
- int port = portNode.asInt(-1);
- if (port == -1) {
- return null;
- }
- ports.add(port);
- }
- adjacencySids.put(asid, ports);
- }
-
- return ImmutableMap.copyOf(adjacencySids);
- }
-
- /**
- * Sets the adjacency SIDs of the router.
- *
- * @param adjacencySids adjacency SIDs of the router.
- * @return the config of the router.
- */
- public SegmentRoutingDeviceConfig setAdjacencySids(Map<Integer, Set<Integer>> adjacencySids) {
- if (adjacencySids == null) {
- object.remove(ADJSIDS);
- } else {
- ArrayNode adjacencySidsNode = mapper.createArrayNode();
-
- adjacencySids.forEach((sid, ports) -> {
- ObjectNode adjacencySidNode = mapper.createObjectNode();
-
- adjacencySidNode.put(ADJSID, sid);
-
- ArrayNode portsNode = mapper.createArrayNode();
- ports.forEach(port -> {
- portsNode.add(port.toString());
- });
- adjacencySidNode.set(PORTS, portsNode);
-
- adjacencySidsNode.add(adjacencySidNode);
- });
-
- object.set(ADJSIDS, adjacencySidsNode);
- }
-
- return this;
- }
-
- /**
- * Gets the pair device id.
- *
- * @return pair device id; Or null if not configured.
- */
- public DeviceId pairDeviceId() {
- String pairDeviceId = get(PAIR_DEVICE_ID, null);
- return pairDeviceId != null ? DeviceId.deviceId(pairDeviceId) : null;
- }
-
- /**
- * Sets the pair device id.
- *
- * @param deviceId pair device id
- * @return this configuration
- */
- public SegmentRoutingDeviceConfig setPairDeviceId(DeviceId deviceId) {
- return (SegmentRoutingDeviceConfig) setOrClear(PAIR_DEVICE_ID, deviceId.toString());
- }
-
- /**
- * Gets the pair local port.
- *
- * @return pair local port; Or null if not configured.
- */
- public PortNumber pairLocalPort() {
- long pairLocalPort = get(PAIR_LOCAL_PORT, -1L);
- return pairLocalPort != -1L ? PortNumber.portNumber(pairLocalPort) : null;
- }
-
- /**
- * Sets the pair local port.
- *
- * @param portNumber pair local port
- * @return this configuration
- */
- public SegmentRoutingDeviceConfig setPairLocalPort(PortNumber portNumber) {
- return (SegmentRoutingDeviceConfig) setOrClear(PAIR_LOCAL_PORT, portNumber.toLong());
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/package-info.java
deleted file mode 100644
index a664a8f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Segment routing network configuration mechanism.
- */
-package org.onosproject.segmentrouting.config;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
deleted file mode 100644
index f8d3053..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ /dev/null
@@ -1,1794 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.grouphandler;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import org.apache.commons.lang3.RandomUtils;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.segmentrouting.DefaultRoutingHandler;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceProperties;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.storekey.DestinationSetNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.storekey.MacVlanNextObjectiveStoreKey;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.slf4j.Logger;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Default ECMP group handler creation module. This component creates a set of
- * ECMP groups for every neighbor that this device is connected to based on
- * whether the current device is an edge device or a transit device.
- */
-public class DefaultGroupHandler {
- private static final Logger log = getLogger(DefaultGroupHandler.class);
-
- private static final long VERIFY_INTERVAL = 30; // secs
-
- protected final DeviceId deviceId;
- protected final ApplicationId appId;
- protected final DeviceProperties deviceConfig;
- protected final List<Integer> allSegmentIds;
- protected int ipv4NodeSegmentId = -1;
- protected int ipv6NodeSegmentId = -1;
- protected boolean isEdgeRouter = false;
- protected MacAddress nodeMacAddr = null;
- protected LinkService linkService;
- protected FlowObjectiveService flowObjectiveService;
- private DeviceConfiguration config;
-
- /**
- * local store for neighbor-device-ids and the set of ports on this device
- * that connect to the same neighbor.
- */
- protected ConcurrentHashMap<DeviceId, Set<PortNumber>> devicePortMap =
- new ConcurrentHashMap<>();
- /**
- * local store for ports on this device connected to neighbor-device-id.
- */
- protected ConcurrentHashMap<PortNumber, DeviceId> portDeviceMap =
- new ConcurrentHashMap<>();
-
- // distributed store for (device+destination-set) mapped to next-id and neighbors
- protected EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
- dsNextObjStore = null;
- // distributed store for (device+subnet-ip-prefix) mapped to next-id
- protected EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
- vlanNextObjStore = null;
- // distributed store for (device+mac+vlan+treatment) mapped to next-id
- protected EventuallyConsistentMap<MacVlanNextObjectiveStoreKey, Integer>
- macVlanNextObjStore = null;
- // distributed store for (device+port+treatment) mapped to next-id
- protected EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
- portNextObjStore = null;
- private SegmentRoutingManager srManager;
-
- private ScheduledExecutorService executorService
- = newScheduledThreadPool(1, groupedThreads("bktCorrector", "bktC-%d", log));
-
- protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
- .register(URI.class).register(HashSet.class)
- .register(DeviceId.class).register(PortNumber.class)
- .register(DestinationSet.class).register(PolicyGroupIdentifier.class)
- .register(PolicyGroupParams.class)
- .register(GroupBucketIdentifier.class)
- .register(GroupBucketIdentifier.BucketOutputType.class);
-
- protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId,
- DeviceProperties config,
- LinkService linkService,
- FlowObjectiveService flowObjService,
- SegmentRoutingManager srManager) {
- this.deviceId = checkNotNull(deviceId);
- this.appId = checkNotNull(appId);
- this.deviceConfig = checkNotNull(config);
- this.linkService = checkNotNull(linkService);
- this.allSegmentIds = checkNotNull(config.getAllDeviceSegmentIds());
- try {
- this.ipv4NodeSegmentId = config.getIPv4SegmentId(deviceId);
- this.ipv6NodeSegmentId = config.getIPv6SegmentId(deviceId);
- this.isEdgeRouter = config.isEdgeDevice(deviceId);
- this.nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Skipping value assignment in DefaultGroupHandler");
- }
- this.flowObjectiveService = flowObjService;
- this.dsNextObjStore = srManager.dsNextObjStore();
- this.vlanNextObjStore = srManager.vlanNextObjStore();
- this.portNextObjStore = srManager.portNextObjStore();
- this.macVlanNextObjStore = srManager.macVlanNextObjStore();
- this.srManager = srManager;
- executorService.scheduleWithFixedDelay(new BucketCorrector(), 10,
- VERIFY_INTERVAL,
- TimeUnit.SECONDS);
- populateNeighborMaps();
- }
-
- /**
- * Gracefully shuts down a groupHandler. Typically called when the handler is
- * no longer needed.
- */
- public void shutdown() {
- executorService.shutdown();
- }
-
- /**
- * Creates a group handler object.
- *
- * @param deviceId device identifier
- * @param appId application identifier
- * @param config interface to retrieve the device properties
- * @param linkService link service object
- * @param flowObjService flow objective service object
- * @param srManager segment routing manager
- * @throws DeviceConfigNotFoundException if the device configuration is not found
- * @return default group handler type
- */
- public static DefaultGroupHandler createGroupHandler(
- DeviceId deviceId,
- ApplicationId appId,
- DeviceProperties config,
- LinkService linkService,
- FlowObjectiveService flowObjService,
- SegmentRoutingManager srManager)
- throws DeviceConfigNotFoundException {
- return new DefaultGroupHandler(deviceId, appId, config,
- linkService,
- flowObjService,
- srManager);
- }
-
- /**
- * Updates local stores for link-src-device/port to neighbor (link-dst) for
- * link that has come up.
- *
- * @param link the infrastructure link
- */
- public void portUpForLink(Link link) {
- if (!link.src().deviceId().equals(deviceId)) {
- log.warn("linkUp: deviceId{} doesn't match with link src {}",
- deviceId, link.src().deviceId());
- return;
- }
-
- log.info("* portUpForLink: Device {} linkUp at local port {} to "
- + "neighbor {}", deviceId, link.src().port(), link.dst().deviceId());
- // ensure local state is updated even if linkup is aborted later on
- addNeighborAtPort(link.dst().deviceId(),
- link.src().port());
- }
-
- /**
- * Updates local stores for link-src-device/port to neighbor (link-dst) for
- * link that has gone down.
- *
- * @param link the infrastructure link
- */
- public void portDownForLink(Link link) {
- PortNumber port = link.src().port();
- if (portDeviceMap.get(port) == null) {
- log.warn("portDown: unknown port");
- return;
- }
-
- log.debug("Device {} portDown {} to neighbor {}", deviceId, port,
- portDeviceMap.get(port));
- devicePortMap.get(portDeviceMap.get(port)).remove(port);
- portDeviceMap.remove(port);
- }
-
- /**
- * Cleans up local stores for removed neighbor device.
- *
- * @param neighborId the device identifier for the neighbor device
- */
- public void cleanUpForNeighborDown(DeviceId neighborId) {
- Set<PortNumber> ports = devicePortMap.remove(neighborId);
- if (ports != null) {
- ports.forEach(p -> portDeviceMap.remove(p));
- }
- }
-
- /**
- * Checks all groups in the src-device of link for neighbor sets that include
- * the dst-device of link, and edits the hash groups according to link up
- * or down. Should only be called by the master instance of the src-switch
- * of link. Typically used when there are no route-path changes due to the
- * link up or down, as the ECMPspg does not change.
- *
- * @param link the infrastructure link that has gone down or come up
- * @param linkDown true if link has gone down
- * @param firstTime true if link has come up for the first time i.e a link
- * not seen-before
- */
- public void retryHash(Link link, boolean linkDown, boolean firstTime) {
- MacAddress neighborMac;
- try {
- neighborMac = deviceConfig.getDeviceMac(link.dst().deviceId());
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting retryHash.");
- return;
- }
- // find all the destinationSets related to link
- Set<DestinationSetNextObjectiveStoreKey> dsKeySet = dsNextObjStore.entrySet()
- .stream()
- .filter(entry -> entry.getKey().deviceId().equals(deviceId))
- // Filter out PW transit groups or include them if MPLS ECMP is supported
- .filter(entry -> !entry.getKey().destinationSet().notBos() ||
- (entry.getKey().destinationSet().notBos() && srManager.getMplsEcmp()))
- // Filter out simple SWAP groups or include them if MPLS ECMP is supported
- .filter(entry -> !entry.getKey().destinationSet().swap() ||
- (entry.getKey().destinationSet().swap() && srManager.getMplsEcmp()))
- .filter(entry -> entry.getValue().containsNextHop(link.dst().deviceId()))
- .map(entry -> entry.getKey())
- .collect(Collectors.toSet());
-
- log.debug("retryHash: dsNextObjStore contents for linkSrc {} -> linkDst {}: {}",
- deviceId, link.dst().deviceId(), dsKeySet);
-
- for (DestinationSetNextObjectiveStoreKey dsKey : dsKeySet) {
- NextNeighbors nextHops = dsNextObjStore.get(dsKey);
- if (nextHops == null) {
- log.warn("retryHash in device {}, but global store has no record "
- + "for dsKey:{}", deviceId, dsKey);
- continue;
- }
- int nextId = nextHops.nextId();
- Set<DeviceId> dstSet = nextHops.getDstForNextHop(link.dst().deviceId());
- if (!linkDown) {
- List<PortLabel> pl = Lists.newArrayList();
- if (firstTime) {
- // some links may have come up before the next-objective was created
- // we take this opportunity to ensure other ports to same next-hop-dst
- // are part of the hash group (see CORD-1180). Duplicate additions
- // to the same hash group are avoided by the driver.
- for (PortNumber p : devicePortMap.get(link.dst().deviceId())) {
- dstSet.forEach(dst -> {
- int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
- pl.add(new PortLabel(p, edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
- });
- }
- addToHashedNextObjective(pl, neighborMac, nextId);
- } else {
- // handle only the port that came up
- dstSet.forEach(dst -> {
- int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
- pl.add(new PortLabel(link.src().port(), edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
- });
- addToHashedNextObjective(pl, neighborMac, nextId);
- }
- } else {
- // linkdown
- List<PortLabel> pl = Lists.newArrayList();
- dstSet.forEach(dst -> {
- int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
- pl.add(new PortLabel(link.src().port(), edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
- });
- removeFromHashedNextObjective(pl, neighborMac, nextId);
- }
- }
- }
-
- /**
- * Utility class for associating output ports and the corresponding MPLS
- * labels to push. In dual-homing, there are different labels to push
- * corresponding to the destination switches in an edge-pair. If both
- * destinations are reachable via the same spine, then the output-port to
- * the spine will be associated with two labels i.e. there will be two
- * PortLabel objects for the same port but with different labels.
- */
- private class PortLabel {
- PortNumber port;
- int edgeLabel;
- boolean popVlan;
-
- PortLabel(PortNumber port, int edgeLabel, boolean popVlan) {
- this.port = port;
- this.edgeLabel = edgeLabel;
- this.popVlan = popVlan;
- }
-
- @Override
- public String toString() {
- return port.toString() + "/" + String.valueOf(edgeLabel) + (popVlan ? "/popVlan" : "");
- }
- }
-
- /**
- * Makes a call to the FlowObjective service to add buckets to
- * a hashed group. User must ensure that all the ports & labels are meant
- * same neighbor (ie. dstMac).
- *
- * @param portLabels a collection of port & label combinations to add
- * to the hash group identified by the nextId
- * @param dstMac destination mac address of next-hop
- * @param nextId id for next-objective to which buckets will be added
- *
- */
- private void addToHashedNextObjective(Collection<PortLabel> portLabels,
- MacAddress dstMac, Integer nextId) {
- // setup metadata to pass to nextObjective - indicate the vlan on egress
- // if needed by the switch pipeline. Since hashed next-hops are always to
- // other neighboring routers, there is no subnet assigned on those ports.
- TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
- metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
- NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
- .withId(nextId)
- .withType(NextObjective.Type.HASHED)
- .withMeta(metabuilder.build())
- .fromApp(appId);
- // Create the new buckets to be updated
- portLabels.forEach(pl -> {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- tBuilder.setOutput(pl.port)
- .setEthDst(dstMac)
- .setEthSrc(nodeMacAddr);
- if (pl.popVlan) {
- tBuilder.popVlan();
- }
- if (pl.edgeLabel != DestinationSet.NO_EDGE_LABEL) {
- tBuilder.pushMpls()
- .copyTtlOut()
- .setMpls(MplsLabel.mplsLabel(pl.edgeLabel));
- }
- nextObjBuilder.addTreatment(tBuilder.build());
- });
-
- log.debug("addToHash in device {}: Adding Bucket with port/label {} "
- + "to nextId {}", deviceId, portLabels, nextId);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("addToHash port/label {} addedTo "
- + "NextObj {} on {}", portLabels, nextId, deviceId),
- (objective, error) -> {
- log.warn("addToHash failed to add port/label {} to NextObj {} on {}: {}",
- portLabels, nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObjective = nextObjBuilder.addToExisting(context);
- flowObjectiveService.next(deviceId, nextObjective);
- }
-
- /**
- * Makes a call to the FlowObjective service to remove buckets from
- * a hash group. User must ensure that all the ports & labels are meant
- * same neighbor (ie. dstMac).
- *
- * @param portLabels a collection of port & label combinations to remove
- * from the hash group identified by the nextId
- * @param dstMac destination mac address of next-hop
- * @param nextId id for next-objective from which buckets will be removed
- */
- private void removeFromHashedNextObjective(Collection<PortLabel> portLabels,
- MacAddress dstMac, Integer nextId) {
- TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
- metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder()
- .withType(NextObjective.Type.HASHED) //same as original
- .withMeta(metabuilder.build())
- .withId(nextId)
- .fromApp(appId);
- // Create the buckets to be removed
- portLabels.forEach(pl -> {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- tBuilder.setOutput(pl.port)
- .setEthDst(dstMac)
- .setEthSrc(nodeMacAddr);
- if (pl.popVlan) {
- tBuilder.popVlan();
- }
- if (pl.edgeLabel != DestinationSet.NO_EDGE_LABEL) {
- tBuilder.pushMpls()
- .copyTtlOut()
- .setMpls(MplsLabel.mplsLabel(pl.edgeLabel));
- }
- nextObjBuilder.addTreatment(tBuilder.build());
- });
- log.debug("removeFromHash in device {}: Removing Bucket with port/label"
- + " {} from nextId {}", deviceId, portLabels, nextId);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("port/label {} removedFrom NextObj"
- + " {} on {}", portLabels, nextId, deviceId),
- (objective, error) -> {
- log.warn("port/label {} failed to removeFrom NextObj {} on {}: {}",
- portLabels, nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObjective = nextObjBuilder.removeFromExisting(context);
- flowObjectiveService.next(deviceId, nextObjective);
- }
-
- /**
- * Checks all the hash-groups in the target-switch meant for the destination
- * switch, and either adds or removes buckets to make the neighbor-set
- * match the given next-hops. Typically called by the master instance of the
- * destination switch, which may be different from the master instance of the
- * target switch where hash-group changes are made.
- *
- * @param targetSw the switch in which the hash groups will be edited
- * @param nextHops the current next hops for the target switch to reach
- * the dest sw
- * @param destSw the destination switch
- * @param revoke true if hash groups need to remove buckets from the
- * the groups to match the current next hops
- * @return true if calls are made to edit buckets, or if no edits are required
- */
- public boolean fixHashGroups(DeviceId targetSw, Set<DeviceId> nextHops,
- DeviceId destSw, boolean revoke) {
- // temporary storage of keys to be updated
- Map<DestinationSetNextObjectiveStoreKey, Set<DeviceId>> tempStore =
- new HashMap<>();
- boolean foundNextObjective = false, success = true;
-
- // retrieve hash-groups meant for destSw, which have destinationSets
- // with different neighbors than the given next-hops
- for (DestinationSetNextObjectiveStoreKey dskey : dsNextObjStore.keySet()) {
- if (!dskey.deviceId().equals(targetSw) ||
- !dskey.destinationSet().getDestinationSwitches().contains(destSw)) {
- continue;
- }
- foundNextObjective = true;
- NextNeighbors nhops = dsNextObjStore.get(dskey);
- Set<DeviceId> currNeighbors = nhops.nextHops(destSw);
- int edgeLabel = dskey.destinationSet().getEdgeLabel(destSw);
- Integer nextId = nhops.nextId();
- if (currNeighbors == null || nextHops == null) {
- log.warn("fixing hash groups but found currNeighbors:{} or nextHops:{}"
- + " in targetSw:{} for dstSw:{}", currNeighbors,
- nextHops, targetSw, destSw);
- success &= false;
- continue;
- }
-
- // some store elements may not be hashed next-objectives - ignore them
- if (isSimpleNextObjective(dskey)) {
- log.debug("Ignoring {} of SIMPLE nextObj for targetSw:{}"
- + " -> dstSw:{} with current nextHops:{} to new"
- + " nextHops: {} in nextId:{}",
- (revoke) ? "removal" : "addition", targetSw, destSw,
- currNeighbors, nextHops, nextId);
- if ((revoke && !nextHops.isEmpty())
- || (!revoke && !nextHops.equals(currNeighbors))) {
- log.debug("Simple next objective cannot be edited to "
- + "move from {} to {}", currNeighbors, nextHops);
- }
- continue;
- }
-
- Set<DeviceId> diff;
- if (revoke) {
- diff = Sets.difference(currNeighbors, nextHops);
- log.debug("targetSw:{} -> dstSw:{} in nextId:{} has current next "
- + "hops:{} ..removing {}", targetSw, destSw, nextId,
- currNeighbors, diff);
- } else {
- diff = Sets.difference(nextHops, currNeighbors);
- log.debug("targetSw:{} -> dstSw:{} in nextId:{} has current next "
- + "hops:{} ..adding {}", targetSw, destSw, nextId,
- currNeighbors, diff);
- }
- boolean suc = updateAllPortsToNextHop(diff, edgeLabel, nextId, popVlanInHashGroup(dskey.destinationSet()),
- revoke);
- if (suc) {
- // to update neighbor set with changes made
- if (revoke) {
- tempStore.put(dskey, Sets.difference(currNeighbors, diff));
- } else {
- tempStore.put(dskey, Sets.union(currNeighbors, diff));
- }
- }
- success &= suc;
- }
-
- if (!foundNextObjective) {
- log.debug("Cannot find any nextObjectives for route targetSw:{} "
- + "-> dstSw:{}", targetSw, destSw);
- return false; // nothing to do, return false so re-route will be performed
- }
-
- // update the dsNextObjectiveStore with new destinationSet to nextId mappings
- for (DestinationSetNextObjectiveStoreKey key : tempStore.keySet()) {
- NextNeighbors currentNextHops = dsNextObjStore.get(key);
- if (currentNextHops == null) {
- log.warn("fixHashGroups could not update global store in "
- + "device {} .. missing nextNeighbors for key {}",
- deviceId, key);
- continue;
- }
- Set<DeviceId> newNeighbors = new HashSet<>();
- newNeighbors.addAll(tempStore.get(key));
- Map<DeviceId, Set<DeviceId>> oldDstNextHops =
- ImmutableMap.copyOf(currentNextHops.dstNextHops());
- currentNextHops.dstNextHops().put(destSw, newNeighbors); //local change
- log.debug("Updating nsNextObjStore target:{} -> dst:{} in key:{} nextId:{}",
- targetSw, destSw, key, currentNextHops.nextId());
- log.debug("Old dstNextHops: {}", oldDstNextHops);
- log.debug("New dstNextHops: {}", currentNextHops.dstNextHops());
- // update global store
- dsNextObjStore.put(key,
- new NextNeighbors(currentNextHops.dstNextHops(),
- currentNextHops.nextId()));
- }
-
- // even if one fails and others succeed, return false so ECMPspg not updated
- return success;
- }
-
- /**
- * Updates the DestinationSetNextObjectiveStore with any per-destination nexthops
- * that are not already in the store for the given DestinationSet. Note that
- * this method does not remove existing next hops for the destinations in the
- * DestinationSet.
- *
- * @param ds the DestinationSet for which the next hops need to be updated
- * @param newDstNextHops a map of per-destination next hops to update the
- * destinationSet with
- * @return true if successful in updating all next hops
- */
- private boolean updateNextHops(DestinationSet ds,
- Map<DeviceId, Set<DeviceId>> newDstNextHops) {
- DestinationSetNextObjectiveStoreKey key =
- new DestinationSetNextObjectiveStoreKey(deviceId, ds);
- NextNeighbors currNext = dsNextObjStore.get(key);
- Map<DeviceId, Set<DeviceId>> currDstNextHops = currNext.dstNextHops();
-
- // add newDstNextHops to currDstNextHops for each dst
- boolean success = true;
- for (DeviceId dstSw : ds.getDestinationSwitches()) {
- Set<DeviceId> currNhops = currDstNextHops.get(dstSw);
- Set<DeviceId> newNhops = newDstNextHops.get(dstSw);
- currNhops = (currNhops == null) ? Sets.newHashSet() : currNhops;
- newNhops = (newNhops == null) ? Sets.newHashSet() : newNhops;
- int edgeLabel = ds.getEdgeLabel(dstSw);
- int nextId = currNext.nextId();
-
- // new next hops should be added
- boolean suc = updateAllPortsToNextHop(Sets.difference(newNhops, currNhops),
- edgeLabel, nextId, popVlanInHashGroup(key.destinationSet()), false);
- if (suc) {
- currNhops.addAll(newNhops);
- currDstNextHops.put(dstSw, currNhops); // this is only a local change
- }
- success &= suc;
- }
-
- if (success) {
- // update global store
- dsNextObjStore.put(key, new NextNeighbors(currDstNextHops,
- currNext.nextId()));
- log.debug("Updated device:{} ds:{} new next-hops: {}", deviceId, ds,
- dsNextObjStore.get(key));
- }
- return success;
- }
-
- /**
- * Adds or removes buckets for all ports to a set of neighbor devices. Caller
- * needs to ensure that the given neighbors are all next hops towards the
- * same destination (represented by the given edgeLabel).
- *
- * @param neighbors set of neighbor device ids
- * @param edgeLabel MPLS label to use in buckets
- * @param nextId the nextObjective to change
- * @param popVlan this hash group bucket shuold includes a popVlan action
- * @param revoke true if buckets need to be removed, false if they need to
- * be added
- * @return true if successful in adding or removing buckets for all ports
- * to the neighbors
- */
- private boolean updateAllPortsToNextHop(Set<DeviceId> neighbors, int edgeLabel,
- int nextId, boolean popVlan, boolean revoke) {
- for (DeviceId neighbor : neighbors) {
- MacAddress neighborMac;
- try {
- neighborMac = deviceConfig.getDeviceMac(neighbor);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting updateAllPortsToNextHop"
- + " for nextId:" + nextId);
- return false;
- }
- Collection<PortNumber> portsToNeighbor = devicePortMap.get(neighbor);
- if (portsToNeighbor == null || portsToNeighbor.isEmpty()) {
- log.warn("No ports found in dev:{} for neighbor:{} .. cannot "
- + "updateAllPortsToNextHop for nextId: {}",
- deviceId, neighbor, nextId);
- return false;
- }
- List<PortLabel> pl = Lists.newArrayList();
- portsToNeighbor.forEach(p -> pl.add(new PortLabel(p, edgeLabel, popVlan)));
- if (revoke) {
- log.debug("updateAllPortsToNextHops in device {}: Removing Bucket(s) "
- + "with Port/Label:{} to next object id {}",
- deviceId, pl, nextId);
- removeFromHashedNextObjective(pl, neighborMac, nextId);
- } else {
- log.debug("fixHashGroup in device {}: Adding Bucket(s) "
- + "with Port/Label: {} to next object id {}",
- deviceId, pl, nextId);
- addToHashedNextObjective(pl, neighborMac, nextId);
- }
- }
- return true;
- }
-
- /**
- * Returns true if the destination set is meant for swap or multi-labeled
- * packet transport, and MPLS ECMP is not supported.
- *
- * @param dskey the key representing the destination set
- * @return true if destination set is meant for simple next objectives
- */
- boolean isSimpleNextObjective(DestinationSetNextObjectiveStoreKey dskey) {
- return (dskey.destinationSet().notBos() || dskey.destinationSet().swap())
- && !srManager.getMplsEcmp();
- }
-
- /**
- * Adds or removes a port that has been configured with a vlan to a broadcast group
- * for bridging. Should only be called by the master instance for this device.
- *
- * @param port the port on this device that needs to be added/removed to a bcast group
- * @param vlanId the vlan id corresponding to the broadcast domain/group
- * @param popVlan indicates if packets should be sent out untagged or not out
- * of the port. If true, indicates an access (untagged) or native vlan
- * configuration. If false, indicates a trunk (tagged) vlan config.
- * @param portUp true if port is enabled, false if disabled
- */
- public void processEdgePort(PortNumber port, VlanId vlanId,
- boolean popVlan, boolean portUp) {
- //get the next id for the subnet and edit it.
- Integer nextId = getVlanNextObjectiveId(vlanId);
- if (nextId == -1) {
- if (portUp) {
- log.debug("**Creating flooding group for first port enabled in"
- + " vlan {} on dev {} port {}", vlanId, deviceId, port);
- createBcastGroupFromVlan(vlanId, Collections.singleton(port));
- } else {
- log.warn("Could not find flooding group for subnet {} on dev:{} when"
- + " removing port:{}", vlanId, deviceId, port);
- }
- return;
- }
-
- log.info("**port{} in device {}: {} Bucket with Port {} to"
- + " next-id {}", (portUp) ? "UP" : "DOWN", deviceId,
- (portUp) ? "Adding" : "Removing",
- port, nextId);
- // Create the bucket to be added or removed
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (popVlan) {
- tBuilder.popVlan();
- }
- tBuilder.setOutput(port);
-
- TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.BROADCAST).fromApp(appId)
- .addTreatment(tBuilder.build())
- .withMeta(metadata);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("port {} successfully {} NextObj {} on {}",
- port, (portUp) ? "addedTo" : "removedFrom",
- nextId, deviceId),
- (objective, error) -> {
- log.warn("port {} failed to {} NextObj {} on {}: {}",
- port, (portUp) ? "addTo" : "removeFrom", nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
-
- NextObjective nextObj = (portUp) ? nextObjBuilder.addToExisting(context)
- : nextObjBuilder.removeFromExisting(context);
- log.debug("edgePort processed: Submited next objective {} in device {}",
- nextId, deviceId);
- flowObjectiveService.next(deviceId, nextObj);
- }
-
- /**
- * Returns the next objective of type hashed (or simple) associated with the
- * destination set. In addition, updates the existing next-objective if new
- * route-paths found have resulted in the addition of new next-hops to a
- * particular destination. If there is no existing next objective for this
- * destination set, this method would create a next objective and return the
- * nextId. Optionally metadata can be passed in for the creation of the next
- * objective. If the parameter simple is true then a simple next objective
- * is created instead of a hashed one.
- *
- * @param ds destination set
- * @param nextHops a map of per destination next hops
- * @param meta metadata passed into the creation of a Next Objective
- * @param simple if true, a simple next objective will be created instead of
- * a hashed next objective
- * @return int if found or -1 if there are errors in the creation of the
- * neighbor set.
- */
- public int getNextObjectiveId(DestinationSet ds,
- Map<DeviceId, Set<DeviceId>> nextHops,
- TrafficSelector meta, boolean simple) {
- NextNeighbors next = dsNextObjStore.
- get(new DestinationSetNextObjectiveStoreKey(deviceId, ds));
- if (next == null) {
- log.debug("getNextObjectiveId in device{}: Next objective id "
- + "not found for {} ... creating", deviceId, ds);
- log.trace("getNextObjectiveId: nsNextObjStore contents for device {}: {}",
- deviceId,
- dsNextObjStore.entrySet()
- .stream()
- .filter((nsStoreEntry) ->
- (nsStoreEntry.getKey().deviceId().equals(deviceId)))
- .collect(Collectors.toList()));
-
- createGroupFromDestinationSet(ds, nextHops, meta, simple);
- next = dsNextObjStore.
- get(new DestinationSetNextObjectiveStoreKey(deviceId, ds));
- if (next == null) {
- log.warn("getNextObjectiveId: unable to create next objective");
- // failure in creating group
- return -1;
- } else {
- log.debug("getNextObjectiveId in device{}: Next objective id {} "
- + "created for {}", deviceId, next.nextId(), ds);
- }
- } else {
- log.trace("getNextObjectiveId in device{}: Next objective id {} "
- + "found for {}", deviceId, next.nextId(), ds);
- // should fix hash groups too if next-hops have changed
- if (!next.dstNextHops().equals(nextHops)) {
- log.debug("Nexthops have changed for dev:{} nextId:{} ..updating",
- deviceId, next.nextId());
- if (!updateNextHops(ds, nextHops)) {
- // failure in updating group
- return -1;
- }
- }
- }
- return next.nextId();
- }
-
- /**
- * Returns the next objective of type broadcast associated with the vlan,
- * or -1 if no such objective exists. Note that this method does NOT create
- * the next objective as a side-effect. It is expected that is objective is
- * created at startup from network configuration. Typically this is used
- * for L2 flooding within the subnet configured on the switch.
- *
- * @param vlanId vlan id
- * @return int if found or -1
- */
- public int getVlanNextObjectiveId(VlanId vlanId) {
- Integer nextId = vlanNextObjStore.
- get(new VlanNextObjectiveStoreKey(deviceId, vlanId));
-
- return (nextId != null) ? nextId : -1;
- }
-
- /**
- * Returns the next objective of type simple associated with the mac/vlan on the
- * device, given the treatment. Different treatments to the same mac/vlan result
- * in different next objectives. If no such objective exists, this method
- * creates one (if requested) and returns the id. Optionally metadata can be passed in for
- * the creation of the objective. Typically this is used for L2 and L3 forwarding
- * to compute nodes and containers/VMs on the compute nodes directly attached
- * to the switch.
- *
- * @param macAddr the mac addr for the simple next objective
- * @param vlanId the vlan for the simple next objective
- * @param port port with which to create the Next Obj.
- * @param createIfMissing true if a next object should be created if not found
- * @return int if found or created, -1 if there are errors during the
- * creation of the next objective.
- */
- public int getMacVlanNextObjectiveId(MacAddress macAddr, VlanId vlanId, PortNumber port,
- boolean createIfMissing) {
-
- Integer nextId = macVlanNextObjStore
- .get(new MacVlanNextObjectiveStoreKey(deviceId, macAddr, vlanId));
-
- if (nextId != null) {
- return nextId;
- }
-
- log.debug("getMacVlanNextObjectiveId in device {}: Next objective id "
- + "not found for host : {}/{} .. {}", deviceId, macAddr, vlanId,
- (createIfMissing) ? "creating" : "aborting");
-
- if (!createIfMissing) {
- return -1;
- }
-
- MacAddress deviceMac;
- try {
- deviceMac = deviceConfig.getDeviceMac(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " in getMacVlanNextObjectiveId");
- return -1;
- }
-
- // since we are creating now, port cannot be null
- if (port == null) {
- log.debug("getMacVlanNextObjectiveId : port information cannot be null "
- + "for device {}, host {}/{}", deviceId, macAddr, vlanId);
- return -1;
- }
-
- TrafficSelector.Builder meta = DefaultTrafficSelector.builder();
-
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.deferred()
- .setEthDst(macAddr)
- .setEthSrc(deviceMac)
- .setOutput(port);
-
- ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
- VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
- Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
- VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
-
- // Adjust the meta according to VLAN configuration
- if (taggedVlans.contains(vlanId)) {
- treatment.setVlanId(vlanId);
- } else if (vlanId.equals(VlanId.NONE)) {
- if (untaggedVlan != null) {
- meta.matchVlanId(untaggedVlan);
- } else if (nativeVlan != null) {
- meta.matchVlanId(nativeVlan);
- } else {
- log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan",
- macAddr, vlanId, connectPoint);
- return -1;
- }
- } else {
- log.warn("Tagged nexthop {}/{} is not allowed on {} without VLAN listed"
- + " in tagged vlan", macAddr, vlanId, connectPoint);
- return -1;
- }
-
- /* create missing next objective */
- nextId = createGroupFromMacVlan(macAddr, vlanId, treatment.build(), meta.build());
- if (nextId == null) {
- log.warn("getMacVlanNextObjectiveId: unable to create next obj"
- + "for dev:{} host:{}/{}", deviceId, macAddr, vlanId);
- return -1;
- }
- return nextId;
- }
-
-
- /**
- * Returns the next objective of type simple associated with the port on the
- * device, given the treatment. Different treatments to the same port result
- * in different next objectives. If no such objective exists, this method
- * creates one (if requested) and returns the id. Optionally metadata can be passed in for
- * the creation of the objective. Typically this is used for L2 and L3 forwarding
- * to compute nodes and containers/VMs on the compute nodes directly attached
- * to the switch.
- *
- * @param portNum the port number for the simple next objective
- * @param treatment the actions to apply on the packets (should include outport)
- * @param meta optional metadata passed into the creation of the next objective
- * @param createIfMissing true if a next object should be created if not found
- * @return int if found or created, -1 if there are errors during the
- * creation of the next objective.
- */
- public int getPortNextObjectiveId(PortNumber portNum, TrafficTreatment treatment,
- TrafficSelector meta, boolean createIfMissing) {
- Integer nextId = portNextObjStore
- .get(new PortNextObjectiveStoreKey(deviceId, portNum, treatment, meta));
- if (nextId != null) {
- return nextId;
- }
- log.debug("getPortNextObjectiveId in device {}: Next objective id "
- + "not found for port: {} .. {}", deviceId, portNum,
- (createIfMissing) ? "creating" : "aborting");
- if (!createIfMissing) {
- return -1;
- }
- // create missing next objective
- createGroupFromPort(portNum, treatment, meta);
- nextId = portNextObjStore.get(new PortNextObjectiveStoreKey(deviceId, portNum,
- treatment, meta));
- if (nextId == null) {
- log.warn("getPortNextObjectiveId: unable to create next obj"
- + "for dev:{} port:{}", deviceId, portNum);
- return -1;
- }
- return nextId;
- }
-
- /**
- * Checks if the next objective ID (group) for the neighbor set exists or not.
- *
- * @param ns neighbor set to check
- * @return true if it exists, false otherwise
- */
- public boolean hasNextObjectiveId(DestinationSet ns) {
- NextNeighbors nextHops = dsNextObjStore.
- get(new DestinationSetNextObjectiveStoreKey(deviceId, ns));
- if (nextHops == null) {
- return false;
- }
-
- return true;
- }
-
- private void populateNeighborMaps() {
- Set<Link> outgoingLinks = linkService.getDeviceEgressLinks(deviceId);
- for (Link link : outgoingLinks) {
- if (link.type() != Link.Type.DIRECT) {
- continue;
- }
- addNeighborAtPort(link.dst().deviceId(), link.src().port());
- }
- }
-
- protected void addNeighborAtPort(DeviceId neighborId,
- PortNumber portToNeighbor) {
- // Update DeviceToPort database
- log.debug("Device {} addNeighborAtPort: neighbor {} at port {}",
- deviceId, neighborId, portToNeighbor);
- Set<PortNumber> ports = Collections
- .newSetFromMap(new ConcurrentHashMap<PortNumber, Boolean>());
- ports.add(portToNeighbor);
- Set<PortNumber> portnums = devicePortMap.putIfAbsent(neighborId, ports);
- if (portnums != null) {
- portnums.add(portToNeighbor);
- }
-
- // Update portToDevice database
- // should always update as neighbor could have changed on this port
- DeviceId prev = portDeviceMap.put(portToNeighbor, neighborId);
- if (prev != null) {
- log.warn("Device/port: {}/{} previous neighbor: {}, current neighbor: {} ",
- deviceId, portToNeighbor, prev, neighborId);
- }
- }
-
- /**
- * Creates a NextObjective for a hash group in this device from a given
- * DestinationSet. If the parameter simple is true, a simple next objective
- * is created instead.
- *
- * @param ds the DestinationSet
- * @param neighbors a map for each destination and its next-hops
- * @param meta metadata passed into the creation of a Next Objective
- * @param simple if true, a simple next objective will be created instead of
- * a hashed next objective
- */
- public void createGroupFromDestinationSet(DestinationSet ds,
- Map<DeviceId, Set<DeviceId>> neighbors,
- TrafficSelector meta,
- boolean simple) {
- int nextId = flowObjectiveService.allocateNextId();
- NextObjective.Type type = (simple) ? NextObjective.Type.SIMPLE
- : NextObjective.Type.HASHED;
- if (neighbors == null || neighbors.isEmpty()) {
- log.warn("createGroupsFromDestinationSet: needs at least one neighbor"
- + "to create group in dev:{} for ds: {} with next-hops {}",
- deviceId, ds, neighbors);
- return;
- }
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder()
- .withId(nextId)
- .withType(type)
- .fromApp(appId);
- if (meta != null) {
- nextObjBuilder.withMeta(meta);
- }
-
- // create treatment buckets for each neighbor for each dst Device
- // except in the special case where we only want to pick a single
- // neighbor/port for a simple nextObj
- boolean foundSingleNeighbor = false;
- boolean treatmentAdded = false;
- Map<DeviceId, Set<DeviceId>> dstNextHops = new ConcurrentHashMap<>();
- for (DeviceId dst : ds.getDestinationSwitches()) {
- Set<DeviceId> nextHops = neighbors.get(dst);
- if (nextHops == null || nextHops.isEmpty()) {
- continue;
- }
-
- if (foundSingleNeighbor) {
- break;
- }
-
- for (DeviceId neighborId : nextHops) {
- if (devicePortMap.get(neighborId) == null) {
- log.warn("Neighbor {} is not in the port map yet for dev:{}",
- neighborId, deviceId);
- return;
- } else if (devicePortMap.get(neighborId).isEmpty()) {
- log.warn("There are no ports for "
- + "the Device {} in the port map yet", neighborId);
- return;
- }
-
- MacAddress neighborMac;
- try {
- neighborMac = deviceConfig.getDeviceMac(neighborId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting createGroupsFromDestinationset.");
- return;
- }
- // For each port to the neighbor, we create a new treatment
- Set<PortNumber> neighborPorts = devicePortMap.get(neighborId);
- // In this case we need a SIMPLE nextObj. We randomly pick a port
- if (simple) {
- int size = devicePortMap.get(neighborId).size();
- int index = RandomUtils.nextInt(0, size);
- neighborPorts = Collections.singleton(
- Iterables.get(devicePortMap.get(neighborId),
- index));
- foundSingleNeighbor = true;
- }
-
- for (PortNumber sp : neighborPorts) {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
- .builder();
- tBuilder.setEthDst(neighborMac).setEthSrc(nodeMacAddr);
- int edgeLabel = ds.getEdgeLabel(dst);
- if (edgeLabel != DestinationSet.NO_EDGE_LABEL) {
- if (simple) {
- // swap label case
- tBuilder.setMpls(MplsLabel.mplsLabel(edgeLabel));
- } else {
- // ecmp with label push case
- tBuilder.pushMpls().copyTtlOut()
- .setMpls(MplsLabel.mplsLabel(edgeLabel));
- }
- }
-
- // Set VLAN ID for PW transport. Otherwise pop vlan
- if (!popVlanInHashGroup(ds)) {
- tBuilder.setVlanId(srManager.getPwTransportVlan());
- } else {
- tBuilder.popVlan();
- }
-
- tBuilder.setOutput(sp);
- nextObjBuilder.addTreatment(tBuilder.build());
- treatmentAdded = true;
- //update store
- Set<DeviceId> existingNeighbors = dstNextHops.get(dst);
- if (existingNeighbors == null) {
- existingNeighbors = new HashSet<>();
- }
- existingNeighbors.add(neighborId);
- dstNextHops.put(dst, existingNeighbors);
- log.debug("creating treatment for port/label {}/{} in next:{}",
- sp, edgeLabel, nextId);
- }
-
- if (foundSingleNeighbor) {
- break;
- }
- }
- }
-
- if (!treatmentAdded) {
- log.warn("Could not createGroup from DestinationSet {} without any"
- + "next hops {}", ds, neighbors);
- return;
- }
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("createGroupsFromDestinationSet installed "
- + "NextObj {} on {}", nextId, deviceId),
- (objective, error) -> {
- log.warn("createGroupsFromDestinationSet failed to install NextObj {} on {}: {}",
- nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObj = nextObjBuilder.add(context);
- log.debug(".. createGroupsFromDestinationSet: Submitted "
- + "next objective {} in device {}", nextId, deviceId);
- flowObjectiveService.next(deviceId, nextObj);
- //update store
- dsNextObjStore.put(new DestinationSetNextObjectiveStoreKey(deviceId, ds),
- new NextNeighbors(dstNextHops, nextId));
- }
-
- /**
- * Creates broadcast groups for all ports in the same subnet for
- * all configured subnets.
- */
- public void createGroupsFromVlanConfig() {
- srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
- createBcastGroupFromVlan(vlanId, ports);
- });
- }
-
- /**
- * Creates a single broadcast group from a given vlan id and list of ports.
- *
- * @param vlanId vlan id
- * @param ports list of ports in the subnet
- */
- public void createBcastGroupFromVlan(VlanId vlanId, Collection<PortNumber> ports) {
- VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
- if (vlanNextObjStore.containsKey(key)) {
- log.debug("Broadcast group for device {} and subnet {} exists",
- deviceId, vlanId);
- return;
- }
-
- TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
- int nextId = flowObjectiveService.allocateNextId();
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.BROADCAST).fromApp(appId)
- .withMeta(metadata);
-
- ports.forEach(port -> {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (toPopVlan(port, vlanId)) {
- tBuilder.popVlan();
- }
- tBuilder.setOutput(port);
- nextObjBuilder.addTreatment(tBuilder.build());
- });
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("createBroadcastGroupFromVlan installed "
- + "NextObj {} on {}", nextId, deviceId),
- (objective, error) -> {
- log.warn("createBroadcastGroupFromVlan failed to install NextObj {} on {}: {}",
- nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObj = nextObjBuilder.add(context);
- flowObjectiveService.next(deviceId, nextObj);
- log.debug("createBcastGroupFromVlan: Submitted next objective {} "
- + "for vlan: {} in device {}", nextId, vlanId, deviceId);
-
- vlanNextObjStore.put(key, nextId);
- }
-
- /**
- * Removes a single broadcast group from a given vlan id.
- * The group should be empty.
- * @param deviceId device Id to remove the group
- * @param portNum port number related to the group
- * @param vlanId vlan id of the broadcast group to remove
- * @param popVlan true if the TrafficTreatment involves pop vlan tag action
- */
- public void removeBcastGroupFromVlan(DeviceId deviceId, PortNumber portNum,
- VlanId vlanId, boolean popVlan) {
- VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
- if (!vlanNextObjStore.containsKey(key)) {
- log.debug("Broadcast group for device {} and subnet {} does not exist",
- deviceId, vlanId);
- return;
- }
-
- TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
- int nextId = vlanNextObjStore.get(key);
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.BROADCAST).fromApp(appId)
- .withMeta(metadata);
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (popVlan) {
- tBuilder.popVlan();
- }
- tBuilder.setOutput(portNum);
- nextObjBuilder.addTreatment(tBuilder.build());
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("removeBroadcastGroupFromVlan removed "
- + "NextObj {} on {}", nextId, deviceId),
- (objective, error) -> {
- log.warn("removeBroadcastGroupFromVlan failed to remove NextObj {} on {}: {}",
- nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObj = nextObjBuilder.remove(context);
- flowObjectiveService.next(deviceId, nextObj);
- log.debug("removeBcastGroupFromVlan: Submited next objective {} in device {}",
- nextId, deviceId);
-
- vlanNextObjStore.remove(key, nextId);
- }
-
- /**
- * Determine if we should pop given vlan before sending packets to the given port.
- *
- * @param portNumber port number
- * @param vlanId vlan id
- * @return true if the vlan id is not contained in any vlanTagged config
- */
- private boolean toPopVlan(PortNumber portNumber, VlanId vlanId) {
- return srManager.interfaceService
- .getInterfacesByPort(new ConnectPoint(deviceId, portNumber))
- .stream().noneMatch(intf -> intf.vlanTagged().contains(vlanId));
- }
-
- /**
- * Create simple next objective for an indirect host mac/vlan. The treatments can include
- * all outgoing actions that need to happen on the packet.
- *
- * @param macAddr the mac address of the host
- * @param vlanId the vlan of the host
- * @param treatment the actions to apply on the packets (should include outport)
- * @param meta optional data to pass to the driver
- * @return next objective ID
- */
- public int createGroupFromMacVlan(MacAddress macAddr, VlanId vlanId, TrafficTreatment treatment,
- TrafficSelector meta) {
- int nextId = flowObjectiveService.allocateNextId();
- MacVlanNextObjectiveStoreKey key = new MacVlanNextObjectiveStoreKey(deviceId, macAddr, vlanId);
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.SIMPLE)
- .addTreatment(treatment)
- .fromApp(appId)
- .withMeta(meta);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("createGroupFromMacVlan installed "
- + "NextObj {} on {}", nextId, deviceId),
- (objective, error) -> {
- log.warn("createGroupFromMacVlan failed to install NextObj {} on {}: {}", nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObj = nextObjBuilder.add(context);
- flowObjectiveService.next(deviceId, nextObj);
- log.debug("createGroupFromMacVlan: Submited next objective {} in device {} "
- + "for host {}/{}", nextId, deviceId, macAddr, vlanId);
-
- macVlanNextObjStore.put(key, nextId);
- return nextId;
- }
-
- /**
- * Create simple next objective for a single port. The treatments can include
- * all outgoing actions that need to happen on the packet.
- *
- * @param portNum the outgoing port on the device
- * @param treatment the actions to apply on the packets (should include outport)
- * @param meta optional data to pass to the driver
- */
- public void createGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
- TrafficSelector meta) {
- int nextId = flowObjectiveService.allocateNextId();
- PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
- deviceId, portNum, treatment, meta);
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.SIMPLE)
- .addTreatment(treatment)
- .fromApp(appId)
- .withMeta(meta);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("createGroupFromPort installed "
- + "NextObj {} on {}", nextId, deviceId),
- (objective, error) -> {
- log.warn("createGroupFromPort failed to install NextObj {} on {}: {}", nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObj = nextObjBuilder.add(context);
- flowObjectiveService.next(deviceId, nextObj);
- log.debug("createGroupFromPort: Submited next objective {} in device {} "
- + "for port {}", nextId, deviceId, portNum);
-
- portNextObjStore.put(key, nextId);
- }
-
- /**
- * Creates simple next objective for a single port.
- *
- * @param deviceId device id that has the port to deal with
- * @param portNum the outgoing port on the device
- * @param vlanId vlan id associated with the port
- * @param popVlan true if POP_VLAN action is applied on the packets, false otherwise
- */
- public void createPortNextObjective(DeviceId deviceId, PortNumber portNum, VlanId vlanId, boolean popVlan) {
- TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
- mbuilder.matchVlanId(vlanId);
-
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.immediate().setOutput(portNum);
- if (popVlan) {
- tbuilder.immediate().popVlan();
- }
-
- createGroupFromPort(portNum, tbuilder.build(), mbuilder.build());
- }
-
- /**
- * Removes simple next objective for a single port.
- *
- * @param deviceId device id that has the port to deal with
- * @param portNum the outgoing port on the device
- * @param vlanId vlan id associated with the port
- * @param popVlan true if POP_VLAN action is applied on the packets, false otherwise
- */
- public void removePortNextObjective(DeviceId deviceId, PortNumber portNum, VlanId vlanId, boolean popVlan) {
- TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
- mbuilder.matchVlanId(vlanId);
-
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.immediate().setOutput(portNum);
- if (popVlan) {
- tbuilder.immediate().popVlan();
- }
-
- int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNum,
- tbuilder.build(), mbuilder.build(), false);
-
- PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
- deviceId, portNum, tbuilder.build(), mbuilder.build());
- if (portNextObjId != -1 && portNextObjStore.containsKey(key)) {
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(portNextObjId)
- .withType(NextObjective.Type.SIMPLE).fromApp(appId);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("removePortNextObjective removes NextObj {} on {}",
- portNextObjId, deviceId),
- (objective, error) -> {
- log.warn("removePortNextObjective failed to remove NextObj {} on {}: {}",
- portNextObjId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObjective = nextObjBuilder.remove(context);
- log.info("**removePortNextObjective: Submitted "
- + "next objective {} in device {}",
- portNextObjId, deviceId);
- flowObjectiveService.next(deviceId, nextObjective);
-
- portNextObjStore.remove(key);
- }
- }
-
- /**
- * Removes groups for the next objective ID given.
- *
- * @param objectiveId next objective ID to remove
- * @return true if succeeds, false otherwise
- */
- public boolean removeGroup(int objectiveId) {
- for (Map.Entry<DestinationSetNextObjectiveStoreKey, NextNeighbors> e :
- dsNextObjStore.entrySet()) {
- if (e.getValue().nextId() != objectiveId) {
- continue;
- }
- // Right now it is just used in TunnelHandler
- // remember in future that PW transit groups could
- // be Indirect groups
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(objectiveId)
- .withType(NextObjective.Type.HASHED).fromApp(appId);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("RemoveGroup removes NextObj {} on {}",
- objectiveId, deviceId),
- (objective, error) -> {
- log.warn("RemoveGroup failed to remove NextObj {} on {}: {}", objectiveId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObjective = nextObjBuilder.remove(context);
- log.info("**removeGroup: Submited "
- + "next objective {} in device {}",
- objectiveId, deviceId);
- flowObjectiveService.next(deviceId, nextObjective);
-
- dsNextObjStore.remove(e.getKey());
- return true;
- }
-
- return false;
- }
- /**
- * Remove simple next objective for a single port. The treatments can include
- * all outgoing actions that need to happen on the packet.
- *
- * @param portNum the outgoing port on the device
- * @param treatment the actions applied on the packets (should include outport)
- * @param meta optional data to pass to the driver
- */
- public void removeGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
- TrafficSelector meta) {
- PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
- deviceId, portNum, treatment, meta);
- Integer nextId = portNextObjStore.get(key);
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.SIMPLE)
- .addTreatment(treatment)
- .fromApp(appId)
- .withMeta(meta);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.info("removeGroupFromPort installed "
- + "NextObj {} on {}", nextId, deviceId),
- (objective, error) -> {
- log.warn("removeGroupFromPort failed to install NextObj {} on {}: {}", nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- }
- );
- NextObjective nextObj = nextObjBuilder.remove(context);
- flowObjectiveService.next(deviceId, nextObj);
- log.info("removeGroupFromPort: Submitted next objective {} in device {} "
- + "for port {}", nextId, deviceId, portNum);
-
- portNextObjStore.remove(key);
- }
-
- /**
- * Removes all groups from all next objective stores.
- */
- /*public void removeAllGroups() {
- for (Map.Entry<NeighborSetNextObjectiveStoreKey, NextNeighbors> entry:
- nsNextObjStore.entrySet()) {
- removeGroup(entry.getValue().nextId());
- }
- for (Map.Entry<PortNextObjectiveStoreKey, Integer> entry:
- portNextObjStore.entrySet()) {
- removeGroup(entry.getValue());
- }
- for (Map.Entry<VlanNextObjectiveStoreKey, Integer> entry:
- vlanNextObjStore.entrySet()) {
- removeGroup(entry.getValue());
- }
- }*/ //XXX revisit
-
- /**
- * Triggers a one time bucket verification operation on all hash groups
- * on this device.
- */
- public void triggerBucketCorrector() {
- BucketCorrector bc = new BucketCorrector();
- bc.run();
- }
-
- /**
- * Modifies L2IG bucket when the interface configuration is updated, especially
- * when the interface has same VLAN ID but the VLAN type is changed (e.g., from
- * vlan-tagged [10] to vlan-untagged 10), which requires changes on
- * TrafficTreatment in turn.
- *
- * @param portNumber the port on this device that needs to be updated
- * @param vlanId the vlan id corresponding to this port
- * @param pushVlan indicates if packets should be sent out untagged or not out
- * from the port. If true, updated TrafficTreatment involves
- * pop vlan tag action. If false, updated TrafficTreatment
- * does not involve pop vlan tag action.
- */
- public void updateL2InterfaceGroupBucket(PortNumber portNumber, VlanId vlanId, boolean pushVlan) {
- TrafficTreatment.Builder oldTBuilder = DefaultTrafficTreatment.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- tBuilder.setOutput(portNumber);
- oldTBuilder.setOutput(portNumber);
- if (pushVlan) {
- tBuilder.popVlan();
- } else {
- oldTBuilder.popVlan();
- }
-
- TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
- // Update portNextObjStore with new L2IG
- int nextId = getPortNextObjectiveId(portNumber, oldTBuilder.build(), metadata, false);
- portNextObjStore.remove(new PortNextObjectiveStoreKey(deviceId, portNumber, oldTBuilder.build(), metadata));
- portNextObjStore.put(new PortNextObjectiveStoreKey(deviceId, portNumber, tBuilder.build(), metadata), nextId);
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.SIMPLE).fromApp(appId)
- .addTreatment(tBuilder.build())
- .withMeta(metadata);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("port {} successfully updated NextObj {} on {}",
- portNumber, nextId, deviceId),
- (objective, error) -> {
- log.warn("port {} failed to updated NextObj {} on {}: {}", portNumber, nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
-
- flowObjectiveService.next(deviceId, nextObjBuilder.modify(context));
- }
-
- /**
- * Updates the next objective for the given nextId .
- *
- * @param hostMac mac of host for which Next obj is to be updated.
- * @param hostVlanId vlan of host for which Next obj is to be updated.
- * @param port port with which to update the Next Obj.
- * @param nextId of Next Obj which needs to be updated.
- */
- public void updateL3UcastGroupBucket(MacAddress hostMac, VlanId hostVlanId, PortNumber port, int nextId) {
-
- MacAddress deviceMac;
- try {
- deviceMac = deviceConfig.getDeviceMac(deviceId);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " in updateL3UcastGroupBucket");
- return;
- }
-
- TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(hostVlanId).build();
-
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- tbuilder.deferred()
- .setEthDst(hostMac)
- .setEthSrc(deviceMac)
- .setVlanId(hostVlanId)
- .setOutput(port);
-
- log.debug(" update L3Ucast : deviceMac {}, port {}, host {}/{}, nextid {}, Treatment {} Meta {}",
- deviceMac, port, hostMac, hostVlanId, nextId, tbuilder.build(), metadata);
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.SIMPLE).fromApp(appId)
- .addTreatment(tbuilder.build())
- .withMeta(metadata);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug(" NextId {} successfully updated host {} vlan {} with port {}",
- nextId, hostMac, hostVlanId, port),
- (objective, error) -> {
- log.warn(" NextId {} failed to update host {} vlan {} with port {}, error : {}",
- nextId, hostMac, hostVlanId, port, error);
- srManager.invalidateNextObj(objective.id());
- });
-
- NextObjective nextObj = nextObjBuilder.modify(context);
- flowObjectiveService.next(deviceId, nextObj);
-
- }
-
- /**
- * Adds a single port to the L2FG or removes it from the L2FG.
- *
- * @param vlanId the vlan id corresponding to this port
- * @param portNum the port on this device to be updated
- * @param nextId the next objective ID for the given vlan id
- * @param install if true, adds the port to L2FG. If false, removes it from L2FG.
- */
- public void updateGroupFromVlanConfiguration(VlanId vlanId, PortNumber portNum, int nextId, boolean install) {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (toPopVlan(portNum, vlanId)) {
- tBuilder.popVlan();
- }
- tBuilder.setOutput(portNum);
-
- TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
-
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.BROADCAST).fromApp(appId)
- .addTreatment(tBuilder.build())
- .withMeta(metadata);
-
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("port {} successfully removedFrom NextObj {} on {}",
- portNum, nextId, deviceId),
- (objective, error) -> {
- log.warn("port {} failed to removedFrom NextObj {} on {}: {}", portNum, nextId, deviceId, error);
- srManager.invalidateNextObj(objective.id());
- });
-
- if (install) {
- flowObjectiveService.next(deviceId, nextObjBuilder.addToExisting(context));
- } else {
- flowObjectiveService.next(deviceId, nextObjBuilder.removeFromExisting(context));
- }
- }
-
- /**
- * Performs bucket verification operation for all hash groups in this device.
- * Checks RouteHandler to ensure that routing is stable before attempting
- * verification. Verification involves creating a nextObjective with
- * operation VERIFY for existing next objectives in the store, and passing
- * it to the driver. It is the driver that actually performs the verification
- * by adding or removing buckets to match the verification next objective
- * created here.
- */
- protected final class BucketCorrector implements Runnable {
- Integer nextId;
-
- BucketCorrector() {
- this.nextId = null;
- }
-
- BucketCorrector(Integer nextId) {
- this.nextId = nextId;
- }
-
- @Override
- public void run() {
- if (!srManager.mastershipService.isLocalMaster(deviceId)) {
- return;
- }
- DefaultRoutingHandler rh = srManager.getRoutingHandler();
- if (rh == null) {
- return;
- }
- if (!rh.isRoutingStable()) {
- return;
- }
- rh.acquireRoutingLock();
- try {
- log.trace("running bucket corrector for dev: {}", deviceId);
- Set<DestinationSetNextObjectiveStoreKey> dsKeySet = dsNextObjStore.entrySet()
- .stream()
- .filter(entry -> entry.getKey().deviceId().equals(deviceId))
- // Filter out PW transit groups or include them if MPLS ECMP is supported
- .filter(entry -> !entry.getKey().destinationSet().notBos() ||
- (entry.getKey().destinationSet().notBos() && srManager.getMplsEcmp()))
- // Filter out simple SWAP groups or include them if MPLS ECMP is supported
- .filter(entry -> !entry.getKey().destinationSet().swap() ||
- (entry.getKey().destinationSet().swap() && srManager.getMplsEcmp()))
- .map(entry -> entry.getKey())
- .collect(Collectors.toSet());
- for (DestinationSetNextObjectiveStoreKey dsKey : dsKeySet) {
- NextNeighbors next = dsNextObjStore.get(dsKey);
- if (next == null) {
- continue;
- }
- int nid = next.nextId();
- if (nextId != null && nextId != nid) {
- continue;
- }
- log.trace("bkt-corr: dsNextObjStore for device {}: {}",
- deviceId, dsKey, next);
- TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
- metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
- NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
- .withId(nid)
- .withType(NextObjective.Type.HASHED)
- .withMeta(metabuilder.build())
- .fromApp(appId);
-
- next.dstNextHops().forEach((dstDev, nextHops) -> {
- int edgeLabel = dsKey.destinationSet().getEdgeLabel(dstDev);
- nextHops.forEach(neighbor -> {
- MacAddress neighborMac;
- try {
- neighborMac = deviceConfig.getDeviceMac(neighbor);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting neighbor"
- + neighbor);
- return;
- }
- devicePortMap.get(neighbor).forEach(port -> {
- log.trace("verify in device {} nextId {}: bucket with"
- + " port/label {}/{} to dst {} via {}",
- deviceId, nid, port, edgeLabel,
- dstDev, neighbor);
- nextObjBuilder
- .addTreatment(treatmentBuilder(port,
- neighborMac,
- dsKey.destinationSet().swap(),
- edgeLabel));
- });
- });
- });
-
- NextObjective nextObjective = nextObjBuilder.verify();
- flowObjectiveService.next(deviceId, nextObjective);
- }
- } finally {
- rh.releaseRoutingLock();
- }
-
- }
-
- TrafficTreatment treatmentBuilder(PortNumber outport, MacAddress dstMac,
- boolean swap, int edgeLabel) {
- TrafficTreatment.Builder tBuilder =
- DefaultTrafficTreatment.builder();
- tBuilder.setOutput(outport)
- .setEthDst(dstMac)
- .setEthSrc(nodeMacAddr);
- if (edgeLabel != DestinationSet.NO_EDGE_LABEL) {
- if (swap) {
- // swap label case
- tBuilder.setMpls(MplsLabel.mplsLabel(edgeLabel));
- } else {
- // ecmp with label push case
- tBuilder.pushMpls()
- .copyTtlOut()
- .setMpls(MplsLabel.mplsLabel(edgeLabel));
- }
- }
- return tBuilder.build();
- }
- }
-
- /**
- * Determines whether the hash group bucket should include a popVlan action.
- * We don't popVlan for PW.
- *
- * @param ds destination set
- * @return true if VLAN needs to be popped
- */
- private boolean popVlanInHashGroup(DestinationSet ds) {
- return (ds.getTypeOfDstSet() != DestinationSet.DestinationSetType.SWAP_NOT_BOS) &&
- (ds.getTypeOfDstSet() != DestinationSet.DestinationSetType.POP_NOT_BOS);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java
deleted file mode 100644
index 3ecdd61..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.grouphandler;
-
-import org.onosproject.net.DeviceId;
-import org.slf4j.Logger;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Representation of a set of destination switch dpids along with their
- * edge-node labels. Meant to be used as a lookup-key in a hash-map to retrieve
- * an ECMP-group that hashes packets towards a specific destination switch, or
- * paired-destination switches. May also be used to represent cases where the
- * forwarding does not use ECMP groups (ie SIMPLE next objectives)
- */
-public final class DestinationSet {
- public static final int NO_EDGE_LABEL = -1;
- private static final int NOT_ASSIGNED = 0;
- private final DeviceId dstSw1;
- private final int edgeLabel1;
- private final DeviceId dstSw2;
- private final int edgeLabel2;
- private final DestinationSetType typeOfDstSet;
-
- private static final Logger log = getLogger(DestinationSet.class);
-
- /**
- * Constructor for a single destination with no Edge label.
- *
- * @param dsType type of next objective
- * @param dstSw the destination switch
- */
- private DestinationSet(DestinationSetType dsType, DeviceId dstSw) {
- this.edgeLabel1 = NO_EDGE_LABEL;
- this.dstSw1 = dstSw;
- this.edgeLabel2 = NOT_ASSIGNED;
- this.dstSw2 = null;
- this.typeOfDstSet = dsType;
- }
-
- /**
- * Constructor for a single destination with Edge label.
- *
- * @param dsType type of next objective
- * @param edgeLabel label to be pushed as part of group operation
- * @param dstSw the destination switch
- */
- private DestinationSet(DestinationSetType dsType,
- int edgeLabel, DeviceId dstSw) {
- this.edgeLabel1 = edgeLabel;
- this.dstSw1 = dstSw;
- this.edgeLabel2 = NOT_ASSIGNED;
- this.dstSw2 = null;
- this.typeOfDstSet = dsType;
- }
-
- /**
- * Constructor for paired destination switches and their associated edge
- * labels.
- *
- * @param dsType type of next objective
- * @param edgeLabel1 label to be pushed as part of group operation for
- * dstSw1
- * @param dstSw1 one of the paired destination switches
- * @param edgeLabel2 label to be pushed as part of group operation for
- * dstSw2
- * @param dstSw2 the other paired destination switch
- */
- private DestinationSet(DestinationSetType dsType,
- int edgeLabel1, DeviceId dstSw1,
- int edgeLabel2, DeviceId dstSw2) {
- if (dstSw1.toString().compareTo(dstSw2.toString()) <= 0) {
- this.edgeLabel1 = edgeLabel1;
- this.dstSw1 = dstSw1;
- this.edgeLabel2 = edgeLabel2;
- this.dstSw2 = dstSw2;
- } else {
- this.edgeLabel1 = edgeLabel2;
- this.dstSw1 = dstSw2;
- this.edgeLabel2 = edgeLabel1;
- this.dstSw2 = dstSw1;
- }
- this.typeOfDstSet = dsType;
- }
- /**
- * Default constructor for kryo serialization.
- */
- private DestinationSet() {
- this.edgeLabel1 = NOT_ASSIGNED;
- this.edgeLabel2 = NOT_ASSIGNED;
- this.dstSw1 = DeviceId.NONE;
- this.dstSw2 = DeviceId.NONE;
- this.typeOfDstSet = null;
- }
-
- /**
- * Gets the label associated with given destination switch.
- *
- * @param dstSw the destination switch
- * @return integer the label associated with the destination switch
- */
- public int getEdgeLabel(DeviceId dstSw) {
- if (dstSw.equals(dstSw1)) {
- return edgeLabel1;
- } else if (dstSw.equals(dstSw2)) {
- return edgeLabel2;
- }
- return NOT_ASSIGNED;
- }
-
- /**
- * Gets all the destination switches in this destination set.
- *
- * @return a set of destination switch ids
- */
- public Set<DeviceId> getDestinationSwitches() {
- Set<DeviceId> dests = new HashSet<>();
- dests.add(dstSw1);
- if (dstSw2 != null) {
- dests.add(dstSw2);
- }
- return dests;
- }
-
- /**
- * Returns the type of this ds.
- *
- * @return the type of the destination set
- */
- public DestinationSetType getTypeOfDstSet() {
- return typeOfDstSet;
- }
-
- /**
- * Returns true if the next objective represented by this destination set
- * is of type SWAP_NOT_BOS or POP_NOT_BOS.
- *
- * @return the value of notBos
- */
- public boolean notBos() {
- if ((typeOfDstSet == DestinationSetType.SWAP_NOT_BOS) || (typeOfDstSet == DestinationSetType.POP_NOT_BOS)) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns true if the next objective represented by this destination set
- * is of type SWAP_NOT_BOS or SWAP_BOS.
- *
- * @return the value of swap
- */
- public boolean swap() {
- if ((typeOfDstSet == DestinationSetType.SWAP_BOS) || (typeOfDstSet == DestinationSetType.SWAP_NOT_BOS)) {
- return true;
- }
- return false;
- }
-
- // The list of destination ids and label are used for comparison.
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof DestinationSet)) {
- return false;
- }
- DestinationSet that = (DestinationSet) o;
- if (this.typeOfDstSet != that.typeOfDstSet) {
- return false;
- }
- boolean equal = (this.edgeLabel1 == that.edgeLabel1 &&
- this.dstSw1.equals(that.dstSw1));
- if (this.dstSw2 != null && that.dstSw2 == null ||
- this.dstSw2 == null && that.dstSw2 != null) {
- return false;
- }
- if (this.dstSw2 != null && that.dstSw2 != null) {
- equal = equal && (this.edgeLabel2 == that.edgeLabel2 &&
- this.dstSw2.equals(that.dstSw2));
- }
- return equal;
- }
-
- // The list of destination ids and label are used for comparison.
- @Override
- public int hashCode() {
- if (dstSw2 == null) {
- return Objects.hash(typeOfDstSet, edgeLabel1, dstSw1);
- }
- return Objects.hash(typeOfDstSet, edgeLabel1, dstSw1, edgeLabel2,
- dstSw2);
- }
-
- @Override
- public String toString() {
- ToStringHelper h = toStringHelper(this)
- .add("Type", typeOfDstSet.getType())
- .add("DstSw1", dstSw1)
- .add("Label1", edgeLabel1);
- if (dstSw2 != null) {
- h.add("DstSw2", dstSw2)
- .add("Label2", edgeLabel2);
- }
- return h.toString();
- }
-
- public enum DestinationSetType {
- /**
- * Used to represent DestinationSetType where the next hop
- * is the same as the final destination.
- */
- PUSH_NONE("pushnon"),
- /**
- * Used to represent DestinationSetType where we need to
- * push a single mpls label, that of the destination.
- */
- PUSH_BOS("pushbos"),
- /**
- * Used to represent DestinationSetType where we need to pop
- * an mpls label which has the bos bit set.
- */
- POP_BOS("pop-bos"),
- /**
- * Used to represent DestinationSetType where we swap the outer
- * mpls label with a new one, and where the outer label has the
- * bos bit set.
- */
- SWAP_BOS("swapbos"),
- /**
- * Used to represent DestinationSetType where we need to pop
- * an mpls label which does not have the bos bit set.
- */
- POP_NOT_BOS("popnbos"),
- /**
- * Used to represent DestinationSetType where we swap the outer
- * mpls label with a new one, and where the outer label does not
- * have the bos bit set.
- */
- SWAP_NOT_BOS("swap-nb");
-
- private final String typeOfDstDest;
- DestinationSetType(String s) {
- typeOfDstDest = s;
- }
-
- public String getType() {
- return typeOfDstDest;
- }
- }
-
- /*
- * Static methods for creating DestinationSet objects in
- * order to remove ambiquity with multiple constructors.
- */
-
- /**
- * Returns a DestinationSet with type PUSH_NONE.
- *
- * @param destSw The deviceId for this next objective.
- * @return The DestinationSet of this type.
- */
- public static DestinationSet createTypePushNone(DeviceId destSw) {
- return new DestinationSet(DestinationSetType.PUSH_NONE, destSw);
- }
-
- /**
- * Returns a DestinationSet with type PUSH_BOS.
- *
- * @param edgeLabel1 The mpls label to push.
- * @param destSw1 The device on which the label is assigned.
- * @return The DestinationSet of this type.
- */
- public static DestinationSet createTypePushBos(int edgeLabel1, DeviceId destSw1) {
- return new DestinationSet(DestinationSetType.PUSH_BOS, edgeLabel1, destSw1);
- }
-
- /**
- * Returns a DestinationSet with type PUSH_BOS used for paired leafs.
- *
- * @param edgeLabel1 The label of first paired leaf.
- * @param destSw1 The device id of first paired leaf.
- * @param edgeLabel2 The label of the second leaf.
- * @param destSw2 The device id of the second leaf.
- * @return The DestinationSet of this type.
- */
- public static DestinationSet createTypePushBos(int edgeLabel1, DeviceId destSw1, int edgeLabel2, DeviceId destSw2) {
- return new DestinationSet(DestinationSetType.PUSH_BOS, edgeLabel1, destSw1, edgeLabel2, destSw2);
- }
-
- /**
- * Returns a DestinationSet with type POP_BOS.
- *
- * @param deviceId The deviceId for this next objective.
- * @return The DestinationSet of this type.
- */
- public static DestinationSet createTypePopBos(DeviceId deviceId) {
- return new DestinationSet(DestinationSetType.POP_BOS, deviceId);
- }
-
- /**
- * Returns a DestinationSet with type SWAP_BOS.
- *
- * @param edgeLabel The edge label to swap with.
- * @param deviceId The deviceId for this next objective.
- * @return The DestinationSet of this type.
- */
- public static DestinationSet createTypeSwapBos(int edgeLabel, DeviceId deviceId) {
- return new DestinationSet(DestinationSetType.SWAP_BOS, edgeLabel, deviceId);
- }
-
- /**
- * Returns a DestinationSet with type POP_NOT_BOS.
- *
- * @param deviceId The device-id this next objective should be installed.
- * @return The DestinationSet of this type.
- */
- public static DestinationSet createTypePopNotBos(DeviceId deviceId) {
- return new DestinationSet(DestinationSetType.POP_NOT_BOS, deviceId);
- }
-
- /**
- * Returns a DestinationSet with type SWAP_NOT_BOS.
- *
- * @param edgeLabel The edge label to swap with.
- * @param deviceId The deviceId for this next objective.
- * @return The DestinationSet of this type.
- */
- public static DestinationSet createTypeSwapNotBos(int edgeLabel, DeviceId deviceId) {
- return new DestinationSet(DestinationSetType.SWAP_NOT_BOS, edgeLabel, deviceId);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/GroupBucketIdentifier.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/GroupBucketIdentifier.java
deleted file mode 100644
index 1c2e1ac..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/GroupBucketIdentifier.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.grouphandler;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import org.onosproject.net.PortNumber;
-
-/**
- * Representation of policy group bucket identifier. Not exposed to
- * the application and only to be used internally.
- */
-public class GroupBucketIdentifier {
- private int label;
- private BucketOutputType type;
- private PortNumber outPort;
- private PolicyGroupIdentifier outGroup;
-
- protected enum BucketOutputType {
- PORT,
- GROUP
- }
-
- protected GroupBucketIdentifier(int label,
- PortNumber outPort) {
- this.label = label;
- this.type = BucketOutputType.PORT;
- this.outPort = checkNotNull(outPort);
- this.outGroup = null;
- }
-
- protected GroupBucketIdentifier(int label,
- PolicyGroupIdentifier outGroup) {
- this.label = label;
- this.type = BucketOutputType.GROUP;
- this.outPort = null;
- this.outGroup = checkNotNull(outGroup);
- }
-
- protected int label() {
- return this.label;
- }
-
- protected BucketOutputType type() {
- return this.type;
- }
-
- protected PortNumber outPort() {
- return this.outPort;
- }
-
- protected PolicyGroupIdentifier outGroup() {
- return this.outGroup;
- }
-}
-
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/NextNeighbors.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/NextNeighbors.java
deleted file mode 100644
index eaca1aa..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/NextNeighbors.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.grouphandler;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-import org.onosproject.net.DeviceId;
-
-/**
- * Represents the nexthop information associated with a route-path towards a
- * set of destinations.
- */
-public class NextNeighbors {
- private final Map<DeviceId, Set<DeviceId>> dstNextHops;
- private final int nextId;
-
- /**
- * Constructor.
- *
- * @param dstNextHops map of destinations and the next-hops towards each dest
- * @param nextId id of nextObjective that manifests the next-hop info
- */
- public NextNeighbors(Map<DeviceId, Set<DeviceId>> dstNextHops, int nextId) {
- this.dstNextHops = dstNextHops;
- this.nextId = nextId;
- }
-
- /**
- * Returns a map of destinations and the next-hops towards them.
- *
- * @return map of destinations and the next-hops towards them
- */
- public Map<DeviceId, Set<DeviceId>> dstNextHops() {
- return dstNextHops;
- }
-
- /**
- * Set of next-hops towards the given destination.
- *
- * @param deviceId the destination
- * @return set of nexthops towards the destination
- */
- public Set<DeviceId> nextHops(DeviceId deviceId) {
- return dstNextHops.get(deviceId);
- }
-
- /**
- * Return the nextId representing the nextObjective towards the next-hops.
- *
- * @return nextId representing the nextObjective towards the next-hops
- */
- public int nextId() {
- return nextId;
- }
-
- /**
- * Checks if the given nextHopId is a valid next hop to any one of the
- * destinations.
- *
- * @param nextHopId the deviceId for the next hop
- * @return true if given next
- */
- public boolean containsNextHop(DeviceId nextHopId) {
- for (Set<DeviceId> nextHops : dstNextHops.values()) {
- if (nextHops != null && nextHops.contains(nextHopId)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns a set of destinations which have the given nextHopId as one
- * of the next-hops to that destination.
- *
- * @param nextHopId the deviceId for the next hop
- * @return set of deviceIds that have the given nextHopId as a next-hop
- * which could be empty if no destinations were found
- */
- public Set<DeviceId> getDstForNextHop(DeviceId nextHopId) {
- Set<DeviceId> dstSet = new HashSet<>();
- for (DeviceId dstKey : dstNextHops.keySet()) {
- if (dstNextHops.get(dstKey).contains(nextHopId)) {
- dstSet.add(dstKey);
- }
- }
- return dstSet;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof NextNeighbors)) {
- return false;
- }
- NextNeighbors that = (NextNeighbors) o;
- return (this.nextId == that.nextId) &&
- this.dstNextHops.equals(that.dstNextHops);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(nextId, dstNextHops);
- }
-
- @Override
- public String toString() {
- return toStringHelper(this)
- .add("nextId", nextId)
- .add("dstNextHops", dstNextHops)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
deleted file mode 100644
index c0935ce..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.grouphandler;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.DeviceProperties;
-import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.link.LinkService;
-import org.slf4j.Logger;
-
-/**
- * A module to create group chains based on the specified device
- * ports and label stack to be applied on each port.
- */
-public class PolicyGroupHandler extends DefaultGroupHandler {
-
- private final Logger log = getLogger(getClass());
- private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
-
- /**
- * Constructs policy group handler.
- *
- * @param deviceId device identifier
- * @param appId application identifier
- * @param config interface to retrieve the device properties
- * @param linkService link service object
- * @param flowObjService flow objective service object
- * @param srManager segment routing manager
- */
- public PolicyGroupHandler(DeviceId deviceId,
- ApplicationId appId,
- DeviceProperties config,
- LinkService linkService,
- FlowObjectiveService flowObjService,
- SegmentRoutingManager srManager) {
- super(deviceId, appId, config, linkService, flowObjService, srManager);
- }
-
- /**
- * Creates policy group chain.
- *
- * @param id unique identifier associated with the policy group
- * @param params a list of policy group params
- * @return policy group identifier
- */
- public PolicyGroupIdentifier createPolicyGroupChain(String id,
- List<PolicyGroupParams> params) {
- List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
- for (PolicyGroupParams param: params) {
- List<PortNumber> ports = param.getPorts();
- if (ports == null) {
- log.warn("createPolicyGroupChain in sw {} with wrong "
- + "input parameters", deviceId);
- return null;
- }
-
- int labelStackSize = (param.getLabelStack() != null) ?
- param.getLabelStack().size() : 0;
-
- if (labelStackSize > 1) {
- for (PortNumber sp : ports) {
- PolicyGroupIdentifier previousGroupkey = null;
- DeviceId neighbor = portDeviceMap.get(sp);
- for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
- int label = param.getLabelStack().get(idx);
- if (idx == (labelStackSize - 1)) {
- // Innermost Group
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label,
- previousGroupkey);
- bucketIds.add(bucketId);
- } else if (idx == 0) {
- // Outermost Group
- List<GroupBucket> outBuckets = new ArrayList<>();
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label, sp);
- PolicyGroupIdentifier key = new
- PolicyGroupIdentifier(id,
- Collections.singletonList(param),
- Collections.singletonList(bucketId));
- MacAddress neighborEthDst;
- try {
- neighborEthDst = deviceConfig.getDeviceMac(neighbor);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Skipping createPolicyGroupChain for this label.");
- continue;
- }
-
- TrafficTreatment.Builder tBuilder =
- DefaultTrafficTreatment.builder();
- tBuilder.setOutput(sp)
- .setEthDst(neighborEthDst)
- .setEthSrc(nodeMacAddr)
- .pushMpls()
- .setMpls(MplsLabel.mplsLabel(label));
- /*outBuckets.add(DefaultGroupBucket.
- createSelectGroupBucket(tBuilder.build()));
- GroupDescription desc = new
- DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(outBuckets));
- //TODO: BoS*/
- previousGroupkey = key;
- //groupService.addGroup(desc);
- //TODO: Use nextObjective APIs here
- } else {
- // Intermediate Groups
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label,
- previousGroupkey);
- PolicyGroupIdentifier key = new
- PolicyGroupIdentifier(id,
- Collections.singletonList(param),
- Collections.singletonList(bucketId));
- // Add to group dependency list
- dependentGroups.put(previousGroupkey, key);
- previousGroupkey = key;
- }
- }
- }
- } else {
- int label = -1;
- if (labelStackSize == 1) {
- label = param.getLabelStack().get(0);
- }
- for (PortNumber sp : ports) {
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label, sp);
- bucketIds.add(bucketId);
- }
- }
- }
- PolicyGroupIdentifier innermostGroupkey = null;
- if (!bucketIds.isEmpty()) {
- innermostGroupkey = new
- PolicyGroupIdentifier(id,
- params,
- bucketIds);
- // Add to group dependency list
- boolean fullyResolved = true;
- for (GroupBucketIdentifier bucketId:bucketIds) {
- if (bucketId.type() == BucketOutputType.GROUP) {
- dependentGroups.put(bucketId.outGroup(),
- innermostGroupkey);
- fullyResolved = false;
- }
- }
-
- if (fullyResolved) {
- List<GroupBucket> outBuckets = new ArrayList<>();
- for (GroupBucketIdentifier bucketId : bucketIds) {
- DeviceId neighbor = portDeviceMap.
- get(bucketId.outPort());
-
- MacAddress neighborEthDst;
- try {
- neighborEthDst = deviceConfig.getDeviceMac(neighbor);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage()
- + " Skipping createPolicyGroupChain for this bucketId.");
- continue;
- }
-
- TrafficTreatment.Builder tBuilder =
- DefaultTrafficTreatment.builder();
- tBuilder.setOutput(bucketId.outPort())
- .setEthDst(neighborEthDst)
- .setEthSrc(nodeMacAddr);
- if (bucketId.label() != DestinationSet.NO_EDGE_LABEL) {
- tBuilder.pushMpls()
- .setMpls(MplsLabel.mplsLabel(bucketId.label()));
- }
- //TODO: BoS
- /*outBuckets.add(DefaultGroupBucket.
- createSelectGroupBucket(tBuilder.build()));*/
- }
- /*GroupDescription desc = new
- DefaultGroupDescription(deviceId,
- GroupDescription.Type.SELECT,
- new GroupBuckets(outBuckets));
- groupService.addGroup(desc);*/
- //TODO: Use nextObjective APIs here
- }
- }
- return innermostGroupkey;
- }
-
- //TODO: Use nextObjective APIs to handle the group chains
- /*
- @Override
- protected void handleGroupEvent(GroupEvent event) {}
- */
-
- /**
- * Generates policy group key.
- *
- * @param id unique identifier associated with the policy group
- * @param params a list of policy group params
- * @return policy group identifier
- */
- public PolicyGroupIdentifier generatePolicyGroupKey(String id,
- List<PolicyGroupParams> params) {
- List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
- for (PolicyGroupParams param: params) {
- List<PortNumber> ports = param.getPorts();
- if (ports == null) {
- log.warn("generateGroupKey in sw {} with wrong "
- + "input parameters", deviceId);
- return null;
- }
-
- int labelStackSize = (param.getLabelStack() != null)
- ? param.getLabelStack().size() : 0;
-
- if (labelStackSize > 1) {
- for (PortNumber sp : ports) {
- PolicyGroupIdentifier previousGroupkey = null;
- for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
- int label = param.getLabelStack().get(idx);
- if (idx == (labelStackSize - 1)) {
- // Innermost Group
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label,
- previousGroupkey);
- bucketIds.add(bucketId);
- } else if (idx == 0) {
- // Outermost Group
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label, sp);
- PolicyGroupIdentifier key = new
- PolicyGroupIdentifier(id,
- Collections.singletonList(param),
- Collections.singletonList(bucketId));
- previousGroupkey = key;
- } else {
- // Intermediate Groups
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label,
- previousGroupkey);
- PolicyGroupIdentifier key = new
- PolicyGroupIdentifier(id,
- Collections.singletonList(param),
- Collections.singletonList(bucketId));
- previousGroupkey = key;
- }
- }
- }
- } else {
- int label = -1;
- if (labelStackSize == 1) {
- label = param.getLabelStack().get(0);
- }
- for (PortNumber sp : ports) {
- GroupBucketIdentifier bucketId =
- new GroupBucketIdentifier(label, sp);
- bucketIds.add(bucketId);
- }
- }
- }
- PolicyGroupIdentifier innermostGroupkey = null;
- if (!bucketIds.isEmpty()) {
- innermostGroupkey = new
- PolicyGroupIdentifier(id,
- params,
- bucketIds);
- }
- return innermostGroupkey;
- }
-
- /**
- * Removes policy group chain.
- *
- * @param key policy group identifier
- */
- public void removeGroupChain(PolicyGroupIdentifier key) {
- checkArgument(key != null);
- List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
- groupsToBeDeleted.add(key);
-
- Iterator<PolicyGroupIdentifier> it =
- groupsToBeDeleted.iterator();
-
- while (it.hasNext()) {
- PolicyGroupIdentifier innerMostGroupKey = it.next();
- for (GroupBucketIdentifier bucketId:
- innerMostGroupKey.bucketIds()) {
- if (bucketId.type() != BucketOutputType.GROUP) {
- groupsToBeDeleted.add(bucketId.outGroup());
- }
- }
- /*groupService.removeGroup(deviceId,
- getGroupKey(innerMostGroupKey),
- appId);*/
- //TODO: Use nextObjective APIs here
- it.remove();
- }
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupIdentifier.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupIdentifier.java
deleted file mode 100644
index fdc6dea..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupIdentifier.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.grouphandler;
-
-import java.util.List;
-
-/**
- * Representation of policy based group identifiers.
- * Opaque to group handler applications and only the outermost
- * policy group identifier in a chain is visible to the applications.
- */
-public class PolicyGroupIdentifier {
- private String id;
- private List<PolicyGroupParams> inputParams;
- private List<GroupBucketIdentifier> bucketIds;
-
- /**
- * Constructs policy group identifier.
- *
- * @param id unique identifier associated with the policy group
- * @param input policy group params associated with this group
- * @param bucketIds buckets associated with this group
- */
- protected PolicyGroupIdentifier(String id,
- List<PolicyGroupParams> input,
- List<GroupBucketIdentifier> bucketIds) {
- this.id = id;
- this.inputParams = input;
- this.bucketIds = bucketIds;
- }
-
- /**
- * Returns the bucket identifier list associated with the policy
- * group identifier.
- *
- * @return list of bucket identifier
- */
- protected List<GroupBucketIdentifier> bucketIds() {
- return this.bucketIds;
- }
-
- @Override
- public int hashCode() {
- int result = 17;
- int combinedHash = 0;
- for (PolicyGroupParams input:inputParams) {
- combinedHash = combinedHash + input.hashCode();
- }
- for (GroupBucketIdentifier bucketId:bucketIds) {
- combinedHash = combinedHash + bucketId.hashCode();
- }
- result = 31 * result + combinedHash;
-
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof PolicyGroupIdentifier) {
- PolicyGroupIdentifier that = (PolicyGroupIdentifier) obj;
- boolean result = this.id.equals(that.id);
- result = result &&
- this.inputParams.containsAll(that.inputParams) &&
- that.inputParams.containsAll(this.inputParams);
- result = result &&
- this.bucketIds.containsAll(that.bucketIds) &&
- that.bucketIds.containsAll(this.bucketIds);
- return result;
- }
-
- return false;
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupParams.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupParams.java
deleted file mode 100644
index 5baf849..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupParams.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.grouphandler;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.List;
-import java.util.Objects;
-
-import org.onosproject.net.PortNumber;
-
-/**
- * Representation of parameters used to create policy based groups.
- */
-public class PolicyGroupParams {
- private final List<PortNumber> ports;
- private final List<Integer> labelStack;
-
- /**
- * Constructor.
- *
- * @param labelStack mpls label stack to be applied on the ports
- * @param ports ports to be part of the policy group
- */
- public PolicyGroupParams(List<Integer> labelStack,
- List<PortNumber> ports) {
- this.ports = checkNotNull(ports);
- this.labelStack = checkNotNull(labelStack);
- }
-
- /**
- * Returns the ports associated with the policy group params.
- *
- * @return list of port numbers
- */
- public List<PortNumber> getPorts() {
- return ports;
- }
-
- /**
- * Returns the label stack associated with the policy group params.
- *
- * @return list of integers
- */
- public List<Integer> getLabelStack() {
- return labelStack;
- }
-
- @Override
- public int hashCode() {
- int result = 17;
- int combinedHash = 0;
- for (PortNumber port:ports) {
- combinedHash = combinedHash + port.hashCode();
- }
- combinedHash = combinedHash + Objects.hash(labelStack);
- result = 31 * result + combinedHash;
-
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof PolicyGroupParams) {
- PolicyGroupParams that = (PolicyGroupParams) obj;
- boolean result = this.labelStack.equals(that.labelStack);
- result = result &&
- this.ports.containsAll(that.ports) &&
- that.ports.containsAll(this.ports);
- return result;
- }
-
- return false;
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/package-info.java
deleted file mode 100644
index d99f1d1..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/grouphandler/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Segment routing group handling.
- */
-package org.onosproject.segmentrouting.grouphandler;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreKey.java
deleted file mode 100644
index 6d69984..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreKey.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Key of multicast filtering objective store.
- */
-public class McastFilteringObjStoreKey {
-
- private final ConnectPoint ingressCP;
- private final VlanId vlanId;
- private final boolean isIpv4;
-
- /**
- * Constructs the key of multicast filtering objective store.
- *
- * @param ingressCP ingress ConnectPoint
- * @param vlanId vlan id
- * @param isIpv4 is Ipv4
- */
- public McastFilteringObjStoreKey(ConnectPoint ingressCP, VlanId vlanId, boolean isIpv4) {
- checkNotNull(ingressCP, "connectpoint cannot be null");
- checkNotNull(vlanId, "vlanid cannot be null");
- this.ingressCP = ingressCP;
- this.vlanId = vlanId;
- this.isIpv4 = isIpv4;
- }
-
- // Constructor for serialization
- private McastFilteringObjStoreKey() {
- this.ingressCP = null;
- this.vlanId = null;
- this.isIpv4 = false;
- }
-
-
- /**
- * Returns the connect point.
- *
- * @return ingress connectpoint
- */
- public ConnectPoint ingressCP() {
- return ingressCP;
- }
-
- /**
- * Returns whether the filtering is for ipv4 mcast.
- *
- * @return isIpv4
- */
- public boolean isIpv4() {
- return isIpv4;
- }
-
- /**
- * Returns the vlan ID of this key.
- *
- * @return vlan ID
- */
- public VlanId vlanId() {
- return vlanId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof McastFilteringObjStoreKey)) {
- return false;
- }
- McastFilteringObjStoreKey that =
- (McastFilteringObjStoreKey) o;
- return (Objects.equals(this.ingressCP, that.ingressCP) &&
- Objects.equals(this.isIpv4, that.isIpv4) &&
- Objects.equals(this.vlanId, that.vlanId));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(ingressCP, vlanId, isIpv4);
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("ingressCP", ingressCP)
- .add("isIpv4", isIpv4)
- .add("vlanId", vlanId)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreSerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreSerializer.java
deleted file mode 100644
index a23fa69..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastFilteringObjStoreSerializer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-/**
- * Custom serializer for {@link McastFilteringObjStoreKey}.
- */
-class McastFilteringObjStoreSerializer extends Serializer<McastFilteringObjStoreKey> {
-
- /**
- * Creates {@link McastFilteringObjStoreSerializer} serializer instance.
- */
- McastFilteringObjStoreSerializer() {
- // non-null, immutable
- super(false, true);
- }
-
- @Override
- public void write(Kryo kryo, Output output, McastFilteringObjStoreKey object) {
- kryo.writeClassAndObject(output, object.ingressCP());
- kryo.writeClassAndObject(output, object.vlanId());
- kryo.writeClassAndObject(output, object.isIpv4());
- }
-
- @Override
- public McastFilteringObjStoreKey read(Kryo kryo, Input input, Class<McastFilteringObjStoreKey> type) {
- ConnectPoint ingressCP = (ConnectPoint) kryo.readClassAndObject(input);
- VlanId vlanId = (VlanId) kryo.readClassAndObject(input);
- boolean isIpv4 = (boolean) kryo.readClassAndObject(input);
- return new McastFilteringObjStoreKey(ingressCP, vlanId, isIpv4);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
deleted file mode 100644
index 8c4968a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
+++ /dev/null
@@ -1,2055 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.mcast.api.McastEvent;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.mcast.api.McastRouteUpdate;
-import org.onosproject.net.Device;
-import org.onosproject.net.HostId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.ConsistentMultimap;
-import org.onosproject.store.service.DistributedSet;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.Versioned;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.time.Instant;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-
-import static org.onosproject.mcast.api.McastEvent.Type.ROUTE_ADDED;
-import static org.onosproject.mcast.api.McastEvent.Type.ROUTE_REMOVED;
-import static org.onosproject.mcast.api.McastEvent.Type.SOURCES_ADDED;
-import static org.onosproject.mcast.api.McastEvent.Type.SOURCES_REMOVED;
-import static org.onosproject.mcast.api.McastEvent.Type.SINKS_ADDED;
-import static org.onosproject.mcast.api.McastEvent.Type.SINKS_REMOVED;
-
-import static org.onosproject.segmentrouting.mcast.McastRole.EGRESS;
-import static org.onosproject.segmentrouting.mcast.McastRole.INGRESS;
-import static org.onosproject.segmentrouting.mcast.McastRole.TRANSIT;
-
-/**
- * Handles Multicast related events.
- */
-public class McastHandler {
- // Internal elements
- private static final Logger log = LoggerFactory.getLogger(McastHandler.class);
- private final SegmentRoutingManager srManager;
- private final McastUtils mcastUtils;
- private final ConsistentMap<McastStoreKey, NextObjective> mcastNextObjStore;
- private final ConsistentMap<McastRoleStoreKey, McastRole> mcastRoleStore;
- private final ConsistentMultimap<McastPathStoreKey, List<Link>> mcastPathStore;
- private final DistributedSet<McastFilteringObjStoreKey> mcastFilteringObjStore;
- // Stability threshold for Mcast. Seconds
- private static final long MCAST_STABLITY_THRESHOLD = 5;
- // Verify interval for Mcast bucket corrector
- private static final long MCAST_VERIFY_INTERVAL = 30;
- // Max verify that can be processed at the same time
- private static final int MAX_VERIFY_ON_FLIGHT = 10;
- // Last change done
- private AtomicReference<Instant> lastMcastChange = new AtomicReference<>(Instant.now());
- // Last bucker corrector execution
- private AtomicReference<Instant> lastBktCorrExecution = new AtomicReference<>(Instant.now());
- // Executors for mcast bucket corrector and for the events
- private ScheduledExecutorService mcastCorrector
- = newScheduledThreadPool(1, groupedThreads("onos", "m-corrector", log));
- private ScheduledExecutorService mcastWorker
- = newScheduledThreadPool(1, groupedThreads("onos", "m-worker-%d", log));
-
- /**
- * Constructs the McastEventHandler.
- *
- * @param srManager Segment Routing manager
- */
- public McastHandler(SegmentRoutingManager srManager) {
- ApplicationId coreAppId = srManager.coreService.getAppId(CoreService.CORE_APP_NAME);
- this.srManager = srManager;
- KryoNamespace.Builder mcastKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(new McastStoreKeySerializer(), McastStoreKey.class);
- mcastNextObjStore = srManager.storageService
- .<McastStoreKey, NextObjective>consistentMapBuilder()
- .withName("onos-mcast-nextobj-store")
- .withSerializer(Serializer.using(mcastKryo.build("McastHandler-NextObj")))
- .build();
- mcastKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(new McastRoleStoreKeySerializer(), McastRoleStoreKey.class)
- .register(McastRole.class);
- mcastRoleStore = srManager.storageService
- .<McastRoleStoreKey, McastRole>consistentMapBuilder()
- .withName("onos-mcast-role-store")
- .withSerializer(Serializer.using(mcastKryo.build("McastHandler-Role")))
- .build();
- mcastKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(new McastFilteringObjStoreSerializer(), McastFilteringObjStoreKey.class);
- mcastFilteringObjStore = srManager.storageService
- .<McastFilteringObjStoreKey>setBuilder()
- .withName("onos-mcast-filtering-store")
- .withSerializer(Serializer.using(mcastKryo.build("McastHandler-FilteringObj")))
- .build()
- .asDistributedSet();
- mcastKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(new McastPathStoreKeySerializer(), McastPathStoreKey.class);
- mcastPathStore = srManager.storageService
- .<McastPathStoreKey, List<Link>>consistentMultimapBuilder()
- .withName("onos-mcast-path-store")
- .withSerializer(Serializer.using(mcastKryo.build("McastHandler-Path")))
- .build();
- mcastUtils = new McastUtils(srManager, coreAppId, log);
- // Init the executor for the buckets corrector
- mcastCorrector.scheduleWithFixedDelay(new McastBucketCorrector(), 10,
- MCAST_VERIFY_INTERVAL, TimeUnit.SECONDS);
- }
-
- /**
- * Determines if mcast in the network has been stable in the last
- * MCAST_STABLITY_THRESHOLD seconds, by comparing the current time
- * to the last mcast change timestamp.
- *
- * @return true if stable
- */
- private boolean isMcastStable() {
- long last = (long) (lastMcastChange.get().toEpochMilli() / 1000.0);
- long now = (long) (Instant.now().toEpochMilli() / 1000.0);
- log.trace("Multicast stable since {}s", now - last);
- return (now - last) > MCAST_STABLITY_THRESHOLD;
- }
-
- /**
- * Assures there are always MCAST_VERIFY_INTERVAL seconds between each execution,
- * by comparing the current time with the last corrector execution.
- *
- * @return true if stable
- */
- private boolean wasBktCorrRunning() {
- long last = (long) (lastBktCorrExecution.get().toEpochMilli() / 1000.0);
- long now = (long) (Instant.now().toEpochMilli() / 1000.0);
- log.trace("McastBucketCorrector executed {}s ago", now - last);
- return (now - last) < MCAST_VERIFY_INTERVAL;
- }
-
- /**
- * Read initial multicast configuration from mcast store.
- */
- public void init() {
- mcastWorker.execute(this::initInternal);
- }
-
- private void initInternal() {
- srManager.multicastRouteService.getRoutes().forEach(mcastRoute -> {
- lastMcastChange.set(Instant.now());
- log.debug("Init group {}", mcastRoute.group());
- if (!mcastUtils.isLeader(mcastRoute.group())) {
- log.debug("Skip {} due to lack of leadership", mcastRoute.group());
- return;
- }
- McastRouteData mcastRouteData = srManager.multicastRouteService.routeData(mcastRoute);
- // For each source process the mcast tree
- srManager.multicastRouteService.sources(mcastRoute).forEach(source -> {
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastRoute.group(), source);
- Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
- mcastPathStore.get(pathStoreKey), Lists.newArrayList());
- Map<ConnectPoint, List<ConnectPoint>> mcastPaths = buildMcastPaths(storedPaths, mcastRoute.group(),
- source);
- // Get all the sinks and process them
- Set<ConnectPoint> sinks = processSinksToBeAdded(source, mcastRoute.group(),
- mcastRouteData.sinks());
- // Filter out all the working sinks, we do not want to move them
- // TODO we need a better way to distinguish flows coming from different sources
- sinks = sinks.stream()
- .filter(sink -> !mcastPaths.containsKey(sink) ||
- !isSinkForSource(mcastRoute.group(), sink, source))
- .collect(Collectors.toSet());
- if (sinks.isEmpty()) {
- log.debug("Skip {} for source {} nothing to do", mcastRoute.group(), source);
- return;
- }
- Map<ConnectPoint, List<Path>> mcasTree = mcastUtils.computeSinkMcastTree(mcastRoute.group(),
- source.deviceId(), sinks);
- mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink, mcastRoute.group(),
- null));
- });
- });
- }
-
- /**
- * Clean up when deactivating the application.
- */
- public void terminate() {
- mcastCorrector.shutdown();
- mcastWorker.shutdown();
- mcastNextObjStore.destroy();
- mcastRoleStore.destroy();
- mcastFilteringObjStore.destroy();
- mcastPathStore.destroy();
- mcastUtils.terminate();
- log.info("Terminated");
- }
-
- /**
- * Processes the SOURCE_ADDED, SOURCE_UPDATED, SINK_ADDED,
- * SINK_REMOVED, ROUTE_ADDED and ROUTE_REMOVED events.
- *
- * @param event the multicast event to be processed
- */
- public void processMcastEvent(McastEvent event) {
- mcastWorker.execute(() -> processMcastEventInternal(event));
- }
-
- private void processMcastEventInternal(McastEvent event) {
- lastMcastChange.set(Instant.now());
- // Current subject is null, for ROUTE_REMOVED events
- final McastRouteUpdate mcastUpdate = event.subject();
- final McastRouteUpdate mcastPrevUpdate = event.prevSubject();
- IpAddress mcastIp = mcastPrevUpdate.route().group();
- Set<ConnectPoint> prevSinks = mcastPrevUpdate.sinks()
- .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
- Set<ConnectPoint> prevSources = mcastPrevUpdate.sources()
- .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
- Set<ConnectPoint> sources;
- // Events handling
- if (event.type() == ROUTE_ADDED) {
- processRouteAddedInternal(mcastUpdate.route().group());
- } else if (event.type() == ROUTE_REMOVED) {
- processRouteRemovedInternal(prevSources, mcastIp);
- } else if (event.type() == SOURCES_ADDED) {
- // Current subject and prev just differ for the source connect points
- sources = mcastUpdate.sources()
- .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
- Set<ConnectPoint> sourcesToBeAdded = Sets.difference(sources, prevSources);
- processSourcesAddedInternal(sourcesToBeAdded, mcastIp, mcastUpdate.sinks());
- } else if (event.type() == SOURCES_REMOVED) {
- // Current subject and prev just differ for the source connect points
- sources = mcastUpdate.sources()
- .values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
- Set<ConnectPoint> sourcesToBeRemoved = Sets.difference(prevSources, sources);
- processSourcesRemovedInternal(sourcesToBeRemoved, sources, mcastIp, mcastUpdate.sinks());
- } else if (event.type() == SINKS_ADDED) {
- processSinksAddedInternal(prevSources, mcastIp, mcastUpdate.sinks(), prevSinks);
- } else if (event.type() == SINKS_REMOVED) {
- processSinksRemovedInternal(prevSources, mcastIp, mcastUpdate.sinks(), mcastPrevUpdate.sinks());
- } else {
- log.warn("Event {} not handled", event);
- }
- }
-
- /**
- * Process the SOURCES_ADDED event.
- *
- * @param sources the sources connect point
- * @param mcastIp the group address
- * @param sinks the sinks connect points
- */
- private void processSourcesAddedInternal(Set<ConnectPoint> sources, IpAddress mcastIp,
- Map<HostId, Set<ConnectPoint>> sinks) {
- lastMcastChange.set(Instant.now());
- log.info("Processing sources added {} for group {}", sources, mcastIp);
- if (!mcastUtils.isLeader(mcastIp)) {
- log.debug("Skip {} due to lack of leadership", mcastIp);
- return;
- }
- if (sources.isEmpty()) {
- log.debug("Skip {} due to empty sources to be added", mcastIp);
- return;
- }
- sources.forEach(source -> {
- Set<ConnectPoint> sinksToBeAdded = processSinksToBeAdded(source, mcastIp, sinks);
- Map<ConnectPoint, List<Path>> mcasTree = mcastUtils.computeSinkMcastTree(mcastIp, source.deviceId(),
- sinksToBeAdded);
- mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink, mcastIp, paths));
- });
- }
-
- /**
- * Process the SOURCES_REMOVED event.
- *
- * @param sourcesToBeRemoved the source connect points to be removed
- * @param remainingSources the remainig source connect points
- * @param mcastIp the group address
- * @param sinks the sinks connect points
- */
- private void processSourcesRemovedInternal(Set<ConnectPoint> sourcesToBeRemoved,
- Set<ConnectPoint> remainingSources,
- IpAddress mcastIp,
- Map<HostId, Set<ConnectPoint>> sinks) {
- lastMcastChange.set(Instant.now());
- log.info("Processing sources removed {} for group {}", sourcesToBeRemoved, mcastIp);
- if (!mcastUtils.isLeader(mcastIp)) {
- log.debug("Skip {} due to lack of leadership", mcastIp);
- return;
- }
- if (remainingSources.isEmpty()) {
- log.debug("There are no more sources for {}", mcastIp);
- processRouteRemovedInternal(sourcesToBeRemoved, mcastIp);
- return;
- }
- // Let's heal the trees
- Set<Link> notAffectedLinks = Sets.newHashSet();
- Map<ConnectPoint, Set<Link>> affectedLinks = Maps.newHashMap();
- Map<ConnectPoint, Set<ConnectPoint>> candidateSinks = Maps.newHashMap();
- Set<ConnectPoint> totalSources = Sets.newHashSet(sourcesToBeRemoved);
- totalSources.addAll(remainingSources);
- // Calculate all the links used by the sources and the current sinks
- totalSources.forEach(source -> {
- Set<ConnectPoint> currentSinks = sinks.values()
- .stream().flatMap(Collection::stream)
- .filter(sink -> isSinkForSource(mcastIp, sink, source))
- .collect(Collectors.toSet());
- candidateSinks.put(source, currentSinks);
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
- mcastPathStore.get(pathStoreKey), Lists.newArrayList());
- currentSinks.forEach(currentSink -> {
- Optional<? extends List<Link>> currentPath = mcastUtils.getStoredPath(currentSink.deviceId(),
- storedPaths);
- if (currentPath.isPresent()) {
- if (!sourcesToBeRemoved.contains(source)) {
- notAffectedLinks.addAll(currentPath.get());
- } else {
- affectedLinks.compute(source, (k, v) -> {
- v = v == null ? Sets.newHashSet() : v;
- v.addAll(currentPath.get());
- return v;
- });
- }
- }
- });
- });
- // Clean transit links
- affectedLinks.forEach((source, currentCandidateLinks) -> {
- Set<Link> linksToBeRemoved = Sets.difference(currentCandidateLinks, notAffectedLinks)
- .immutableCopy();
- if (!linksToBeRemoved.isEmpty()) {
- currentCandidateLinks.forEach(link -> {
- DeviceId srcLink = link.src().deviceId();
- // Remove ports only on links to be removed
- if (linksToBeRemoved.contains(link)) {
- removePortFromDevice(link.src().deviceId(), link.src().port(), mcastIp,
- mcastUtils.assignedVlan(srcLink.equals(source.deviceId()) ?
- source : null));
- }
- // Remove role on the candidate links
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, srcLink, source));
- });
- }
- });
- // Clean ingress and egress
- sourcesToBeRemoved.forEach(source -> {
- Set<ConnectPoint> currentSinks = candidateSinks.get(source);
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- currentSinks.forEach(currentSink -> {
- VlanId assignedVlan = mcastUtils.assignedVlan(source.deviceId().equals(currentSink.deviceId()) ?
- source : null);
- // Sinks co-located with the source
- if (source.deviceId().equals(currentSink.deviceId())) {
- if (source.port().equals(currentSink.port())) {
- log.warn("Skip {} since sink {} is on the same port of source {}. Abort",
- mcastIp, currentSink, source);
- return;
- }
- // We need to check against the other sources and if it is
- // necessary remove the port from the device - no overlap
- Set<VlanId> otherVlans = remainingSources.stream()
- // Only sources co-located and having this sink
- .filter(remainingSource -> remainingSource.deviceId()
- .equals(source.deviceId()) && candidateSinks.get(remainingSource)
- .contains(currentSink))
- .map(remainingSource -> mcastUtils.assignedVlan(
- remainingSource.deviceId().equals(currentSink.deviceId()) ?
- remainingSource : null)).collect(Collectors.toSet());
- if (!otherVlans.contains(assignedVlan)) {
- removePortFromDevice(currentSink.deviceId(), currentSink.port(),
- mcastIp, assignedVlan);
- }
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(),
- source));
- return;
- }
- Set<VlanId> otherVlans = remainingSources.stream()
- .filter(remainingSource -> candidateSinks.get(remainingSource)
- .contains(currentSink))
- .map(remainingSource -> mcastUtils.assignedVlan(
- remainingSource.deviceId().equals(currentSink.deviceId()) ?
- remainingSource : null)).collect(Collectors.toSet());
- // Sinks on other leaves
- if (!otherVlans.contains(assignedVlan)) {
- removePortFromDevice(currentSink.deviceId(), currentSink.port(),
- mcastIp, assignedVlan);
- }
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(),
- source));
- });
- // Clean the mcast paths
- mcastPathStore.removeAll(pathStoreKey);
- });
- }
-
- /**
- * Process the ROUTE_ADDED event.
- *
- * @param mcastIp the group address
- */
- private void processRouteAddedInternal(IpAddress mcastIp) {
- lastMcastChange.set(Instant.now());
- log.info("Processing route added for Multicast group {}", mcastIp);
- // Just elect a new leader
- mcastUtils.isLeader(mcastIp);
- }
-
- /**
- * Removes the entire mcast tree related to this group.
- * @param sources the source connect points
- * @param mcastIp multicast group IP address
- */
- private void processRouteRemovedInternal(Set<ConnectPoint> sources, IpAddress mcastIp) {
- lastMcastChange.set(Instant.now());
- log.info("Processing route removed for group {}", mcastIp);
- if (!mcastUtils.isLeader(mcastIp)) {
- log.debug("Skip {} due to lack of leadership", mcastIp);
- mcastUtils.withdrawLeader(mcastIp);
- return;
- }
- sources.forEach(source -> {
- // Find out the ingress, transit and egress device of the affected group
- DeviceId ingressDevice = getDevice(mcastIp, INGRESS, source)
- .stream().findFirst().orElse(null);
- Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT, source);
- Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS, source);
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- // If there are no egress and transit devices, sinks could be only on the ingress
- if (!egressDevices.isEmpty()) {
- egressDevices.forEach(deviceId -> {
- removeGroupFromDevice(deviceId, mcastIp, mcastUtils.assignedVlan(null));
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, deviceId, source));
- });
- }
- if (!transitDevices.isEmpty()) {
- transitDevices.forEach(deviceId -> {
- removeGroupFromDevice(deviceId, mcastIp, mcastUtils.assignedVlan(null));
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, deviceId, source));
- });
- }
- if (ingressDevice != null) {
- removeGroupFromDevice(ingressDevice, mcastIp, mcastUtils.assignedVlan(source));
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, ingressDevice, source));
- }
- // Clean the mcast paths
- mcastPathStore.removeAll(pathStoreKey);
- });
- // Finally, withdraw the leadership
- mcastUtils.withdrawLeader(mcastIp);
- }
-
- /**
- * Process sinks to be removed.
- *
- * @param sources the source connect points
- * @param mcastIp the ip address of the group
- * @param newSinks the new sinks to be processed
- * @param prevSinks the previous sinks
- */
- private void processSinksRemovedInternal(Set<ConnectPoint> sources, IpAddress mcastIp,
- Map<HostId, Set<ConnectPoint>> newSinks,
- Map<HostId, Set<ConnectPoint>> prevSinks) {
- lastMcastChange.set(Instant.now());
- log.info("Processing sinks removed for group {} and for sources {}",
- mcastIp, sources);
- if (!mcastUtils.isLeader(mcastIp)) {
- log.debug("Skip {} due to lack of leadership", mcastIp);
- return;
- }
- Map<ConnectPoint, Map<ConnectPoint, Optional<? extends List<Link>>>> treesToBeRemoved = Maps.newHashMap();
- Map<ConnectPoint, Set<ConnectPoint>> treesToBeAdded = Maps.newHashMap();
- Set<Link> goodLinks = Sets.newHashSet();
- Map<ConnectPoint, Set<DeviceId>> goodDevicesBySource = Maps.newHashMap();
- sources.forEach(source -> {
- // Save the path associated to the sinks to be removed
- Set<ConnectPoint> sinksToBeRemoved = processSinksToBeRemoved(mcastIp, prevSinks,
- newSinks, source);
- Map<ConnectPoint, Optional<? extends List<Link>>> treeToBeRemoved = Maps.newHashMap();
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
- mcastPathStore.get(pathStoreKey), Lists.newArrayList());
- sinksToBeRemoved.forEach(sink -> treeToBeRemoved.put(sink, mcastUtils.getStoredPath(sink.deviceId(),
- storedPaths)));
- treesToBeRemoved.put(source, treeToBeRemoved);
- // Save the good links and good devices
- Set<DeviceId> goodDevices = Sets.newHashSet();
- Set<DeviceId> totalDevices = Sets.newHashSet(getDevice(mcastIp, EGRESS, source));
- totalDevices.addAll(getDevice(mcastIp, INGRESS, source));
- Set<ConnectPoint> notAffectedSinks = Sets.newHashSet();
- // Compute good sinks
- totalDevices.forEach(device -> {
- Set<ConnectPoint> sinks = getSinks(mcastIp, device, source);
- notAffectedSinks.addAll(Sets.difference(sinks, sinksToBeRemoved));
- });
- // Compute good paths and good devices
- notAffectedSinks.forEach(notAffectedSink -> {
- Optional<? extends List<Link>> notAffectedPath = mcastUtils.getStoredPath(notAffectedSink.deviceId(),
- storedPaths);
- if (notAffectedPath.isPresent()) {
- List<Link> goodPath = notAffectedPath.get();
- goodLinks.addAll(goodPath);
- goodPath.forEach(link -> goodDevices.add(link.src().deviceId()));
- } else {
- goodDevices.add(notAffectedSink.deviceId());
- }
- });
- goodDevicesBySource.compute(source, (k, v) -> {
- v = v == null ? Sets.newHashSet() : v;
- v.addAll(goodDevices);
- return v;
- });
- // Recover the dual-homed sinks
- Set<ConnectPoint> sinksToBeRecovered = processSinksToBeRecovered(mcastIp, newSinks,
- prevSinks, source);
- treesToBeAdded.put(source, sinksToBeRecovered);
- });
- // Remove the sinks taking into account the multiple sources and the original paths
- treesToBeRemoved.forEach((source, tree) ->
- tree.forEach((sink, path) -> processSinkRemovedInternal(source, sink, mcastIp, path,
- goodLinks, goodDevicesBySource.get(source))));
- // Add new sinks according to the recovery procedure
- treesToBeAdded.forEach((source, sinks) ->
- sinks.forEach(sink -> processSinkAddedInternal(source, sink, mcastIp, null)));
- }
-
- /**
- * Removes a path from source to sink for given multicast group.
- *
- * @param source connect point of the multicast source
- * @param sink connection point of the multicast sink
- * @param mcastIp multicast group IP address
- * @param mcastPath path associated to the sink
- * @param usedLinks links used by the other sinks
- * @param usedDevices devices used by other sinks
- */
- private void processSinkRemovedInternal(ConnectPoint source, ConnectPoint sink,
- IpAddress mcastIp, Optional<? extends List<Link>> mcastPath,
- Set<Link> usedLinks, Set<DeviceId> usedDevices) {
-
- log.info("Used links {}", usedLinks);
- log.info("Used devices {}", usedDevices);
-
- lastMcastChange.set(Instant.now());
- log.info("Processing sink removed {} for group {} and for source {}", sink, mcastIp, source);
- boolean isLast;
- // When source and sink are on the same device
- if (source.deviceId().equals(sink.deviceId())) {
- // Source and sink are on even the same port. There must be something wrong.
- if (source.port().equals(sink.port())) {
- log.warn("Skip {} since sink {} is on the same port of source {}. Abort", mcastIp, sink, source);
- return;
- }
- isLast = removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(source));
- if (isLast) {
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, sink.deviceId(), source));
- }
- return;
- }
- // Process the egress device
- isLast = removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(null));
- if (isLast) {
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, sink.deviceId(), source));
- }
- // If this is the last sink on the device, also update upstream
- if (mcastPath.isPresent()) {
- List<Link> links = Lists.newArrayList(mcastPath.get());
- if (isLast) {
- // Clean the path
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- mcastPathStore.remove(pathStoreKey, mcastPath.get());
- Collections.reverse(links);
- for (Link link : links) {
- // If nobody is using the port remove
- if (!usedLinks.contains(link)) {
- removePortFromDevice(link.src().deviceId(), link.src().port(), mcastIp,
- mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
- }
- // If nobody is using the device
- if (!usedDevices.contains(link.src().deviceId())) {
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, link.src().deviceId(), source));
- }
- }
- }
- }
- }
-
- /**
- * Process sinks to be added.
- *
- * @param sources the source connect points
- * @param mcastIp the group IP
- * @param newSinks the new sinks to be processed
- * @param allPrevSinks all previous sinks
- */
- private void processSinksAddedInternal(Set<ConnectPoint> sources, IpAddress mcastIp,
- Map<HostId, Set<ConnectPoint>> newSinks,
- Set<ConnectPoint> allPrevSinks) {
- lastMcastChange.set(Instant.now());
- log.info("Processing sinks added for group {} and for sources {}", mcastIp, sources);
- if (!mcastUtils.isLeader(mcastIp)) {
- log.debug("Skip {} due to lack of leadership", mcastIp);
- return;
- }
- sources.forEach(source -> {
- Set<ConnectPoint> sinksToBeAdded = processSinksToBeAdded(source, mcastIp, newSinks);
- sinksToBeAdded = Sets.difference(sinksToBeAdded, allPrevSinks);
- sinksToBeAdded.forEach(sink -> processSinkAddedInternal(source, sink, mcastIp, null));
- });
- }
-
- /**
- * Establishes a path from source to sink for given multicast group.
- *
- * @param source connect point of the multicast source
- * @param sink connection point of the multicast sink
- * @param mcastIp multicast group IP address
- */
- private void processSinkAddedInternal(ConnectPoint source, ConnectPoint sink,
- IpAddress mcastIp, List<Path> allPaths) {
- lastMcastChange.set(Instant.now());
- log.info("Processing sink added {} for group {} and for source {}", sink, mcastIp, source);
- // Process the ingress device
- McastFilteringObjStoreKey mcastFilterObjStoreKey = new McastFilteringObjStoreKey(source,
- mcastUtils.assignedVlan(source), mcastIp.isIp4());
- addFilterToDevice(mcastFilterObjStoreKey, mcastIp, INGRESS);
- if (source.deviceId().equals(sink.deviceId())) {
- if (source.port().equals(sink.port())) {
- log.warn("Skip {} since sink {} is on the same port of source {}. Abort",
- mcastIp, sink, source);
- return;
- }
- addPortToDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(source));
- mcastRoleStore.put(new McastRoleStoreKey(mcastIp, sink.deviceId(), source), INGRESS);
- return;
- }
- // Find a path. If present, create/update groups and flows for each hop
- Optional<Path> mcastPath = getPath(source.deviceId(), sink.deviceId(), mcastIp, allPaths);
- if (mcastPath.isPresent()) {
- List<Link> links = mcastPath.get().links();
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- // Setup mcast role for ingress
- mcastRoleStore.put(new McastRoleStoreKey(mcastIp, source.deviceId(), source), INGRESS);
- // Setup properly the transit forwarding
- links.forEach(link -> {
- addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp,
- mcastUtils.assignedVlan(link.src().deviceId()
- .equals(source.deviceId()) ? source : null));
- McastFilteringObjStoreKey filteringKey = new McastFilteringObjStoreKey(link.dst(),
- mcastUtils.assignedVlan(null), mcastIp.isIp4());
- addFilterToDevice(filteringKey, mcastIp, null);
- });
- // Setup mcast role for the transit
- links.stream()
- .filter(link -> !link.dst().deviceId().equals(sink.deviceId()))
- .forEach(link -> mcastRoleStore.put(new McastRoleStoreKey(mcastIp, link.dst().deviceId(),
- source), TRANSIT));
- // Process the egress device
- addPortToDevice(sink.deviceId(), sink.port(), mcastIp, mcastUtils.assignedVlan(null));
- // Setup mcast role for egress
- mcastRoleStore.put(new McastRoleStoreKey(mcastIp, sink.deviceId(), source), EGRESS);
- // Store the used path
- mcastPathStore.put(pathStoreKey, links);
- } else {
- log.warn("Unable to find a path from {} to {}. Abort sinkAdded", source.deviceId(), sink.deviceId());
- }
- }
-
- /**
- * Processes the PORT_UPDATED event.
- *
- * @param affectedDevice Affected device
- * @param affectedPort Affected port
- */
- public void processPortUpdate(Device affectedDevice, Port affectedPort) {
- mcastWorker.execute(() -> processPortUpdateInternal(affectedDevice, affectedPort));
- }
-
- private void processPortUpdateInternal(Device affectedDevice, Port affectedPort) {
- // Clean the filtering obj store. Edge port case.
- lastMcastChange.set(Instant.now());
- ConnectPoint portDown = new ConnectPoint(affectedDevice.id(), affectedPort.number());
- if (!affectedPort.isEnabled()) {
- log.info("Processing port down {}", portDown);
- updateFilterObjStoreByPort(portDown);
- }
- }
-
- /**
- * Processes the LINK_DOWN event.
- *
- * @param linkDown Link that is going down
- */
- public void processLinkDown(Link linkDown) {
- mcastWorker.execute(() -> processLinkDownInternal(linkDown));
- }
-
- private void processLinkDownInternal(Link linkDown) {
- // Get mcast groups affected by the link going down
- Set<IpAddress> affectedGroups = getAffectedGroups(linkDown);
- log.info("Processing link down {} for groups {}", linkDown, affectedGroups);
- affectedGroups.forEach(mcastIp -> {
- lastMcastChange.set(Instant.now());
- log.debug("Processing link down {} for group {}", linkDown, mcastIp);
- recoverFailure(mcastIp, linkDown);
- });
- }
-
- /**
- * Process the DEVICE_DOWN event.
- *
- * @param deviceDown device going down
- */
- public void processDeviceDown(DeviceId deviceDown) {
- mcastWorker.execute(() -> processDeviceDownInternal(deviceDown));
- }
-
- private void processDeviceDownInternal(DeviceId deviceDown) {
- // Get the mcast groups affected by the device going down
- Set<IpAddress> affectedGroups = getAffectedGroups(deviceDown);
- log.info("Processing device down {} for groups {}", deviceDown, affectedGroups);
- updateFilterObjStoreByDevice(deviceDown);
- affectedGroups.forEach(mcastIp -> {
- lastMcastChange.set(Instant.now());
- log.debug("Processing device down {} for group {}", deviceDown, mcastIp);
- recoverFailure(mcastIp, deviceDown);
- });
- }
-
- /**
- * General failure recovery procedure.
- *
- * @param mcastIp the group to recover
- * @param failedElement the failed element
- */
- private void recoverFailure(IpAddress mcastIp, Object failedElement) {
- // Do not proceed if we are not the leaders
- if (!mcastUtils.isLeader(mcastIp)) {
- log.debug("Skip {} due to lack of leadership", mcastIp);
- return;
- }
- // Skip if it is not an infra failure
- Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT);
- if (!mcastUtils.isInfraFailure(transitDevices, failedElement)) {
- log.debug("Skip {} not an infrastructure failure", mcastIp);
- return;
- }
- // Do not proceed if the sources of this group are missing
- Set<ConnectPoint> sources = getSources(mcastIp);
- if (sources.isEmpty()) {
- log.warn("Missing sources for group {}", mcastIp);
- return;
- }
- // Get all the paths, affected paths, good links and good devices
- Set<List<Link>> storedPaths = getStoredPaths(mcastIp);
- Set<List<Link>> affectedPaths = mcastUtils.getAffectedPaths(storedPaths, failedElement);
- Set<Link> goodLinks = Sets.newHashSet();
- Map<DeviceId, Set<DeviceId>> goodDevicesBySource = Maps.newHashMap();
- Map<DeviceId, Set<ConnectPoint>> processedSourcesByEgress = Maps.newHashMap();
- Sets.difference(storedPaths, affectedPaths).forEach(goodPath -> {
- goodLinks.addAll(goodPath);
- DeviceId srcDevice = goodPath.get(0).src().deviceId();
- Set<DeviceId> goodDevices = Sets.newHashSet();
- goodPath.forEach(link -> goodDevices.add(link.src().deviceId()));
- goodDevicesBySource.compute(srcDevice, (k, v) -> {
- v = v == null ? Sets.newHashSet() : v;
- v.addAll(goodDevices);
- return v;
- });
- });
- affectedPaths.forEach(affectedPath -> {
- // TODO remove
- log.info("Good links {}", goodLinks);
- // TODO remove
- log.info("Good devices {}", goodDevicesBySource);
- // TODO trace
- log.info("Healing the path {}", affectedPath);
- DeviceId srcDevice = affectedPath.get(0).src().deviceId();
- DeviceId dstDevice = affectedPath.get(affectedPath.size() - 1).dst().deviceId();
- // Fix in one shot multiple sources
- Set<ConnectPoint> affectedSources = sources.stream()
- .filter(device -> device.deviceId().equals(srcDevice))
- .collect(Collectors.toSet());
- Set<ConnectPoint> processedSources = processedSourcesByEgress.getOrDefault(dstDevice,
- Collections.emptySet());
- Optional<Path> alternativePath = getPath(srcDevice, dstDevice, mcastIp, null);
- // If an alternative is possible go ahead
- if (alternativePath.isPresent()) {
- // TODO trace
- log.info("Alternative path {}", alternativePath.get().links());
- } else {
- // Otherwise try to come up with an alternative
- // TODO trace
- log.info("No alternative path");
- Set<ConnectPoint> notAffectedSources = Sets.difference(sources, affectedSources);
- Set<ConnectPoint> remainingSources = Sets.difference(notAffectedSources, processedSources);
- alternativePath = recoverSinks(dstDevice, mcastIp, affectedSources, remainingSources);
- processedSourcesByEgress.compute(dstDevice, (k, v) -> {
- v = v == null ? Sets.newHashSet() : v;
- v.addAll(affectedSources);
- return v;
- });
- }
- // Recover from the failure if possible
- Optional<Path> finalPath = alternativePath;
- affectedSources.forEach(affectedSource -> {
- // Update the mcastPath store
- McastPathStoreKey mcastPathStoreKey = new McastPathStoreKey(mcastIp, affectedSource);
- // Verify if there are local sinks
- Set<DeviceId> localSinks = getSinks(mcastIp, srcDevice, affectedSource).stream()
- .map(ConnectPoint::deviceId)
- .collect(Collectors.toSet());
- Set<DeviceId> goodDevices = goodDevicesBySource.compute(affectedSource.deviceId(), (k, v) -> {
- v = v == null ? Sets.newHashSet() : v;
- v.addAll(localSinks);
- return v;
- });
- // TODO remove
- log.info("Good devices {}", goodDevicesBySource);
- Collection<? extends List<Link>> storedPathsBySource = Versioned.valueOrElse(
- mcastPathStore.get(mcastPathStoreKey), Lists.newArrayList());
- Optional<? extends List<Link>> storedPath = storedPathsBySource.stream()
- .filter(path -> path.equals(affectedPath))
- .findFirst();
- // Remove bad links
- affectedPath.forEach(affectedLink -> {
- DeviceId affectedDevice = affectedLink.src().deviceId();
- // If there is overlap with good paths - skip it
- if (!goodLinks.contains(affectedLink)) {
- removePortFromDevice(affectedDevice, affectedLink.src().port(), mcastIp,
- mcastUtils.assignedVlan(affectedDevice.equals(affectedSource.deviceId()) ?
- affectedSource : null));
- }
- // Remove role on the affected links if last
- if (!goodDevices.contains(affectedDevice)) {
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, affectedDevice, affectedSource));
- }
- });
- // Sometimes the removal fails for serialization issue
- // trying with the original object as workaround
- if (storedPath.isPresent()) {
- mcastPathStore.remove(mcastPathStoreKey, storedPath.get());
- } else {
- log.warn("Unable to find the corresponding path - trying removeal");
- mcastPathStore.remove(mcastPathStoreKey, affectedPath);
- }
- // Program new links
- if (finalPath.isPresent()) {
- List<Link> links = finalPath.get().links();
- installPath(mcastIp, affectedSource, links);
- mcastPathStore.put(mcastPathStoreKey, links);
- links.forEach(link -> goodDevices.add(link.src().deviceId()));
- goodDevicesBySource.compute(srcDevice, (k, v) -> {
- v = v == null ? Sets.newHashSet() : v;
- v.addAll(goodDevices);
- return v;
- });
- goodLinks.addAll(finalPath.get().links());
- }
- });
- });
- }
-
- /**
- * Try to recover sinks using alternative locations.
- *
- * @param notRecovered the device not recovered
- * @param mcastIp the group address
- * @param affectedSources affected sources
- * @param goodSources sources not affected
- */
- private Optional<Path> recoverSinks(DeviceId notRecovered, IpAddress mcastIp,
- Set<ConnectPoint> affectedSources,
- Set<ConnectPoint> goodSources) {
- log.debug("Processing recover sinks on {} for group {}", notRecovered, mcastIp);
- Map<ConnectPoint, Set<ConnectPoint>> affectedSinksBySource = Maps.newHashMap();
- Map<ConnectPoint, Set<ConnectPoint>> sinksBySource = Maps.newHashMap();
- Set<ConnectPoint> sources = Sets.union(affectedSources, goodSources);
- // Hosts influenced by the failure
- Map<HostId, Set<ConnectPoint>> hostIdSetMap = mcastUtils.getAffectedSinks(notRecovered, mcastIp);
- // Locations influenced by the failure
- Set<ConnectPoint> affectedSinks = hostIdSetMap.values()
- .stream()
- .flatMap(Collection::stream)
- .filter(connectPoint -> connectPoint.deviceId().equals(notRecovered))
- .collect(Collectors.toSet());
- // All locations
- Set<ConnectPoint> sinks = hostIdSetMap.values()
- .stream()
- .flatMap(Collection::stream)
- .collect(Collectors.toSet());
- // Maps sinks with the sources
- sources.forEach(source -> {
- Set<ConnectPoint> currentSinks = affectedSinks.stream()
- .filter(sink -> isSinkForSource(mcastIp, sink, source))
- .collect(Collectors.toSet());
- affectedSinksBySource.put(source, currentSinks);
- });
- // Remove sinks one by one if they are not used by other sources
- affectedSources.forEach(affectedSource -> {
- Set<ConnectPoint> currentSinks = affectedSinksBySource.get(affectedSource);
- log.info("Current sinks {} for source {}", currentSinks, affectedSource);
- currentSinks.forEach(currentSink -> {
- VlanId assignedVlan = mcastUtils.assignedVlan(
- affectedSource.deviceId().equals(currentSink.deviceId()) ? affectedSource : null);
- log.info("Assigned vlan {}", assignedVlan);
- Set<VlanId> otherVlans = goodSources.stream()
- .filter(remainingSource -> affectedSinksBySource.get(remainingSource).contains(currentSink))
- .map(remainingSource -> mcastUtils.assignedVlan(
- remainingSource.deviceId().equals(currentSink.deviceId()) ? remainingSource : null))
- .collect(Collectors.toSet());
- log.info("Other vlans {}", otherVlans);
- // Sinks on other leaves
- if (!otherVlans.contains(assignedVlan)) {
- removePortFromDevice(currentSink.deviceId(), currentSink.port(), mcastIp, assignedVlan);
- }
- mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(), affectedSource));
- });
- });
- // Get the sinks to be added and the new egress
- Set<DeviceId> newEgress = Sets.newHashSet();
- affectedSources.forEach(affectedSource -> {
- Set<ConnectPoint> currentSinks = affectedSinksBySource.get(affectedSource);
- Set<ConnectPoint> newSinks = Sets.difference(sinks, currentSinks);
- sinksBySource.put(affectedSource, newSinks);
- newSinks.stream()
- .map(ConnectPoint::deviceId)
- .forEach(newEgress::add);
- });
- log.info("newEgress {}", newEgress);
- // If there are more than one new egresses, return the problem
- if (newEgress.size() != 1) {
- log.warn("There are {} new egress, wrong configuration. Abort.", newEgress.size());
- return Optional.empty();
- }
- DeviceId egress = newEgress.stream()
- .findFirst()
- .orElse(null);
- DeviceId ingress = affectedSources.stream()
- .map(ConnectPoint::deviceId)
- .findFirst()
- .orElse(null);
- log.info("Ingress {}", ingress);
- if (ingress == null) {
- log.warn("No new ingress, wrong configuration. Abort.");
- return Optional.empty();
- }
- // Get an alternative path
- Optional<Path> alternativePath = getPath(ingress, egress, mcastIp, null);
- // If there are new path install sinks and return path
- if (alternativePath.isPresent()) {
- log.info("Alternative path {}", alternativePath.get().links());
- affectedSources.forEach(affectedSource -> {
- Set<ConnectPoint> newSinks = sinksBySource.get(affectedSource);
- newSinks.forEach(newSink -> {
- addPortToDevice(newSink.deviceId(), newSink.port(), mcastIp, mcastUtils.assignedVlan(null));
- mcastRoleStore.put(new McastRoleStoreKey(mcastIp, newSink.deviceId(), affectedSource), EGRESS);
- });
- });
- return alternativePath;
- }
- // No new path but sinks co-located with sources install sinks and return empty
- if (ingress.equals(egress)) {
- log.info("No Alternative path but sinks co-located");
- affectedSources.forEach(affectedSource -> {
- Set<ConnectPoint> newSinks = sinksBySource.get(affectedSource);
- newSinks.forEach(newSink -> {
- if (affectedSource.port().equals(newSink.port())) {
- log.warn("Skip {} since sink {} is on the same port of source {}. Abort",
- mcastIp, newSink, affectedSource);
- return;
- }
- addPortToDevice(newSink.deviceId(), newSink.port(), mcastIp,
- mcastUtils.assignedVlan(affectedSource));
- mcastRoleStore.put(new McastRoleStoreKey(mcastIp, newSink.deviceId(), affectedSource), INGRESS);
- });
- });
- }
- return Optional.empty();
- }
-
- /**
- * Process all the sinks related to a mcast group and return
- * the ones to be removed.
- *
- * @param mcastIp the group address
- * @param prevsinks the previous sinks to be evaluated
- * @param newSinks the new sinks to be evaluted
- * @param source the source connect point
- * @return the set of the sinks to be removed
- */
- private Set<ConnectPoint> processSinksToBeRemoved(IpAddress mcastIp,
- Map<HostId, Set<ConnectPoint>> prevsinks,
- Map<HostId, Set<ConnectPoint>> newSinks,
- ConnectPoint source) {
- final Set<ConnectPoint> sinksToBeProcessed = Sets.newHashSet();
- log.debug("Processing sinks to be removed for Multicast group {}, source {}",
- mcastIp, source);
- prevsinks.forEach(((hostId, connectPoints) -> {
- if (Objects.equal(HostId.NONE, hostId)) {
- //in this case connect points are single homed sinks.
- //just found the difference btw previous and new sinks for this source.
- Set<ConnectPoint> difference = Sets.difference(connectPoints, newSinks.get(hostId));
- sinksToBeProcessed.addAll(difference);
- return;
- }
- // We have to check with the existing flows
- ConnectPoint sinkToBeProcessed = connectPoints.stream()
- .filter(connectPoint -> isSinkForSource(mcastIp, connectPoint, source))
- .findFirst().orElse(null);
- if (sinkToBeProcessed != null) {
- // If the host has been removed or location has been removed
- if (!newSinks.containsKey(hostId) ||
- !newSinks.get(hostId).contains(sinkToBeProcessed)) {
- sinksToBeProcessed.add(sinkToBeProcessed);
- }
- }
- }));
- // We have done, return the set
- return sinksToBeProcessed;
- }
-
- /**
- * Process new locations and return the set of sinks to be added
- * in the context of the recovery.
- *
- * @param newSinks the remaining sinks
- * @param prevSinks the previous sinks
- * @param source the source connect point
- * @return the set of the sinks to be processed
- */
- private Set<ConnectPoint> processSinksToBeRecovered(IpAddress mcastIp,
- Map<HostId, Set<ConnectPoint>> newSinks,
- Map<HostId, Set<ConnectPoint>> prevSinks,
- ConnectPoint source) {
- final Set<ConnectPoint> sinksToBeProcessed = Sets.newHashSet();
- log.debug("Processing sinks to be recovered for Multicast group {}, source {}",
- mcastIp, source);
- newSinks.forEach((hostId, connectPoints) -> {
- // If it has more than 1 locations
- if (connectPoints.size() > 1 || connectPoints.size() == 0) {
- log.debug("Skip {} since sink {} has {} locations",
- mcastIp, hostId, connectPoints.size());
- return;
- }
- // If previously it had two locations, we need to recover it
- // Filter out if the remaining location is already served
- if (prevSinks.containsKey(hostId) && prevSinks.get(hostId).size() == 2) {
- ConnectPoint sinkToBeProcessed = connectPoints.stream()
- .filter(connectPoint -> !isSinkForSource(mcastIp, connectPoint, source))
- .findFirst().orElse(null);
- if (sinkToBeProcessed != null) {
- sinksToBeProcessed.add(sinkToBeProcessed);
- }
- }
- });
- return sinksToBeProcessed;
- }
-
- /**
- * Process all the sinks related to a mcast group and return
- * the ones to be processed.
- *
- * @param source the source connect point
- * @param mcastIp the group address
- * @param sinks the sinks to be evaluated
- * @return the set of the sinks to be processed
- */
- private Set<ConnectPoint> processSinksToBeAdded(ConnectPoint source, IpAddress mcastIp,
- Map<HostId, Set<ConnectPoint>> sinks) {
- final Set<ConnectPoint> sinksToBeProcessed = Sets.newHashSet();
- log.debug("Processing sinks to be added for Multicast group {}, source {}",
- mcastIp, source);
- sinks.forEach(((hostId, connectPoints) -> {
- //add all connect points that are not tied with any host
- if (Objects.equal(HostId.NONE, hostId)) {
- sinksToBeProcessed.addAll(connectPoints);
- return;
- }
- // If it has more than 2 locations
- if (connectPoints.size() > 2 || connectPoints.size() == 0) {
- log.debug("Skip {} since sink {} has {} locations",
- mcastIp, hostId, connectPoints.size());
- return;
- }
- // If it has one location, just use it
- if (connectPoints.size() == 1) {
- sinksToBeProcessed.add(connectPoints.stream().findFirst().orElse(null));
- return;
- }
- // We prefer to reuse existing flows
- ConnectPoint sinkToBeProcessed = connectPoints.stream()
- .filter(connectPoint -> {
- if (!isSinkForGroup(mcastIp, connectPoint, source)) {
- return false;
- }
- if (!isSinkReachable(mcastIp, connectPoint, source)) {
- return false;
- }
- ConnectPoint other = connectPoints.stream()
- .filter(remaining -> !remaining.equals(connectPoint))
- .findFirst().orElse(null);
- // We are already serving the sink
- return !isSinkForSource(mcastIp, other, source);
- }).findFirst().orElse(null);
-
- if (sinkToBeProcessed != null) {
- sinksToBeProcessed.add(sinkToBeProcessed);
- return;
- }
- // Otherwise we prefer to reuse existing egresses
- Set<DeviceId> egresses = getDevice(mcastIp, EGRESS, source);
- sinkToBeProcessed = connectPoints.stream()
- .filter(connectPoint -> {
- if (!egresses.contains(connectPoint.deviceId())) {
- return false;
- }
- if (!isSinkReachable(mcastIp, connectPoint, source)) {
- return false;
- }
- ConnectPoint other = connectPoints.stream()
- .filter(remaining -> !remaining.equals(connectPoint))
- .findFirst().orElse(null);
- return !isSinkForSource(mcastIp, other, source);
- }).findFirst().orElse(null);
- if (sinkToBeProcessed != null) {
- sinksToBeProcessed.add(sinkToBeProcessed);
- return;
- }
- // Otherwise we prefer a location co-located with the source (if it exists)
- sinkToBeProcessed = connectPoints.stream()
- .filter(connectPoint -> connectPoint.deviceId().equals(source.deviceId()))
- .findFirst().orElse(null);
- if (sinkToBeProcessed != null) {
- sinksToBeProcessed.add(sinkToBeProcessed);
- return;
- }
- // Finally, we randomly pick a new location if it is reachable
- sinkToBeProcessed = connectPoints.stream()
- .filter(connectPoint -> {
- if (!isSinkReachable(mcastIp, connectPoint, source)) {
- return false;
- }
- ConnectPoint other = connectPoints.stream()
- .filter(remaining -> !remaining.equals(connectPoint))
- .findFirst().orElse(null);
- return !isSinkForSource(mcastIp, other, source);
- }).findFirst().orElse(null);
- if (sinkToBeProcessed != null) {
- sinksToBeProcessed.add(sinkToBeProcessed);
- }
- }));
- return sinksToBeProcessed;
- }
-
- /**
- * Adds a port to given multicast group on given device. This involves the
- * update of L3 multicast group and multicast routing table entry.
- *
- * @param deviceId device ID
- * @param port port to be added
- * @param mcastIp multicast group
- * @param assignedVlan assigned VLAN ID
- */
- private void addPortToDevice(DeviceId deviceId, PortNumber port,
- IpAddress mcastIp, VlanId assignedVlan) {
- // TODO trace
- log.info("Adding {} on {}/{} and vlan {}", mcastIp, deviceId, port, assignedVlan);
- McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
- ImmutableSet.Builder<PortNumber> portBuilder = ImmutableSet.builder();
- NextObjective newNextObj;
- if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
- // First time someone request this mcast group via this device
- portBuilder.add(port);
- // New nextObj
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("Passing 0 as nextId for unconfigured device {}", deviceId);
- newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
- portBuilder.build(), 0).add();
- } else {
- newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
- portBuilder.build(), null).add();
- }
- // Store the new port
- mcastNextObjStore.put(mcastStoreKey, newNextObj);
- // Create, store and apply the new nextObj and fwdObj
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Successfully add {} on {}/{}, vlan {}",
- mcastIp, deviceId, port.toLong(), assignedVlan),
- (objective, error) -> {
- log.warn("Failed to add {} on {}/{}, vlan {}: {}",
- mcastIp, deviceId, port.toLong(), assignedVlan, error);
- // Schedule the removal using directly the key
- mcastWorker.execute(() -> mcastNextObjStore.remove(mcastStoreKey));
- });
- ForwardingObjective fwdObj = mcastUtils.fwdObjBuilder(mcastIp, assignedVlan,
- newNextObj.id()).add(context);
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("skip next and forward flowobjective addition for device: {}", deviceId);
- } else {
- srManager.flowObjectiveService.next(deviceId, newNextObj);
- srManager.flowObjectiveService.forward(deviceId, fwdObj);
- }
- } else {
- // This device already serves some subscribers of this mcast group
- NextObjective nextObj = mcastNextObjStore.get(mcastStoreKey).value();
- // Stop if the port is already in the nextobj
- Set<PortNumber> existingPorts = mcastUtils.getPorts(nextObj.next());
- if (existingPorts.contains(port)) {
- log.debug("Port {}/{} already exists for {}. Abort", deviceId, port, mcastIp);
- return;
- }
- // Let's add the port and reuse the previous one
- portBuilder.addAll(existingPorts).add(port);
- // Reuse previous nextObj
- newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
- portBuilder.build(), nextObj.id()).addToExisting();
- // Store the final next objective and send only the difference to the driver
- mcastNextObjStore.put(mcastStoreKey, newNextObj);
- // Add just the new port
- portBuilder = ImmutableSet.builder();
- portBuilder.add(port);
- newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
- portBuilder.build(), nextObj.id()).addToExisting();
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("skip next flowobjective update for device: {}", deviceId);
- } else {
- // no need to update the flow here since we have updated the nextobjective/group
- // the existing flow will keep pointing to the updated nextobj
- srManager.flowObjectiveService.next(deviceId, newNextObj);
- }
- }
- }
-
- /**
- * Removes a port from given multicast group on given device.
- * This involves the update of L3 multicast group and multicast routing
- * table entry.
- *
- * @param deviceId device ID
- * @param port port to be added
- * @param mcastIp multicast group
- * @param assignedVlan assigned VLAN ID
- * @return true if this is the last sink on this device
- */
- private boolean removePortFromDevice(DeviceId deviceId, PortNumber port,
- IpAddress mcastIp, VlanId assignedVlan) {
- // TODO trace
- log.info("Removing {} on {}/{} and vlan {}", mcastIp, deviceId, port, assignedVlan);
- McastStoreKey mcastStoreKey =
- new McastStoreKey(mcastIp, deviceId, assignedVlan);
- // This device is not serving this multicast group
- if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
- return true;
- }
- NextObjective nextObj = mcastNextObjStore.get(mcastStoreKey).value();
- Set<PortNumber> existingPorts = mcastUtils.getPorts(nextObj.next());
- // This port does not serve this multicast group
- if (!existingPorts.contains(port)) {
- if (!existingPorts.isEmpty()) {
- log.debug("{} is not serving {} on port {}. Abort.", deviceId, mcastIp, port);
- return false;
- }
- return true;
- }
- // Copy and modify the ImmutableSet
- existingPorts = Sets.newHashSet(existingPorts);
- existingPorts.remove(port);
- NextObjective newNextObj;
- ObjectiveContext context;
- ForwardingObjective fwdObj;
- if (existingPorts.isEmpty()) {
- context = new DefaultObjectiveContext(
- (objective) -> log.debug("Successfully remove {} on {}/{}, vlan {}",
- mcastIp, deviceId, port.toLong(), assignedVlan),
- (objective, error) -> log.warn("Failed to remove {} on {}/{}, vlan {}: {}",
- mcastIp, deviceId, port.toLong(), assignedVlan, error));
- fwdObj = mcastUtils.fwdObjBuilder(mcastIp, assignedVlan, nextObj.id()).remove(context);
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("skip forward flowobjective removal for device: {}", deviceId);
- } else {
- srManager.flowObjectiveService.forward(deviceId, fwdObj);
- }
- mcastNextObjStore.remove(mcastStoreKey);
- } else {
- // Here we store the next objective with the remaining port
- newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
- existingPorts, nextObj.id()).removeFromExisting();
- mcastNextObjStore.put(mcastStoreKey, newNextObj);
- // Let's modify the next objective removing the bucket
- newNextObj = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
- ImmutableSet.of(port), nextObj.id()).removeFromExisting();
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("skip next flowobjective update for device: {}", deviceId);
- } else {
- // no need to update the flow here since we have updated the next objective + group
- // the existing flow will keep pointing to the updated nextobj
- srManager.flowObjectiveService.next(deviceId, newNextObj);
- }
- }
- return existingPorts.isEmpty();
- }
-
- /**
- * Removes entire group on given device.
- *
- * @param deviceId device ID
- * @param mcastIp multicast group to be removed
- * @param assignedVlan assigned VLAN ID
- */
- private void removeGroupFromDevice(DeviceId deviceId, IpAddress mcastIp,
- VlanId assignedVlan) {
- // TODO trace
- log.info("Removing {} on {} and vlan {}", mcastIp, deviceId, assignedVlan);
- McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
- // This device is not serving this multicast group
- if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
- log.debug("{} is not serving {}. Abort.", deviceId, mcastIp);
- return;
- }
- NextObjective nextObj = mcastNextObjStore.get(mcastStoreKey).value();
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Successfully remove {} on {}, vlan {}",
- mcastIp, deviceId, assignedVlan),
- (objective, error) -> log.warn("Failed to remove {} on {}, vlan {}: {}",
- mcastIp, deviceId, assignedVlan, error));
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("skip flow changes on unconfigured device: {}", deviceId);
- } else {
- ForwardingObjective fwdObj = mcastUtils.fwdObjBuilder(mcastIp, assignedVlan, nextObj.id()).remove(context);
- srManager.flowObjectiveService.forward(deviceId, fwdObj);
- }
- mcastNextObjStore.remove(mcastStoreKey);
- }
-
- private void installPath(IpAddress mcastIp, ConnectPoint source, List<Link> links) {
- if (links.isEmpty()) {
- log.warn("There is no link that can be used. Stopping installation.");
- return;
- }
- // Setup new ingress mcast role
- mcastRoleStore.put(new McastRoleStoreKey(mcastIp, links.get(0).src().deviceId(), source),
- INGRESS);
- // For each link, modify the next on the source device adding the src port
- // and a new filter objective on the destination port
- links.forEach(link -> {
- addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp,
- mcastUtils.assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null));
- McastFilteringObjStoreKey mcastFilterObjStoreKey = new McastFilteringObjStoreKey(link.dst(),
- mcastUtils.assignedVlan(null), mcastIp.isIp4());
- addFilterToDevice(mcastFilterObjStoreKey, mcastIp, null);
- });
- // Setup mcast role for the transit
- links.stream()
- .filter(link -> !link.src().deviceId().equals(source.deviceId()))
- .forEach(link -> mcastRoleStore.put(new McastRoleStoreKey(mcastIp, link.src().deviceId(), source),
- TRANSIT));
- }
-
- /**
- * Gets a path from src to dst.
- * If a path was allocated before, returns the allocated path.
- * Otherwise, randomly pick one from available paths.
- *
- * @param src source device ID
- * @param dst destination device ID
- * @param mcastIp multicast group
- * @param allPaths paths list
- *
- * @return an optional path from src to dst
- */
- private Optional<Path> getPath(DeviceId src, DeviceId dst,
- IpAddress mcastIp, List<Path> allPaths) {
- if (allPaths == null) {
- allPaths = mcastUtils.getPaths(src, dst, Collections.emptySet());
- }
- if (allPaths.isEmpty()) {
- return Optional.empty();
- }
- // Create a map index of suitability-to-list of paths. For example
- // a path in the list associated to the index 1 shares only one link
- // and it is less suitable of a path belonging to the index 2
- Map<Integer, List<Path>> eligiblePaths = Maps.newHashMap();
- int score;
- // Let's build the multicast tree
- Set<List<Link>> storedPaths = getStoredPaths(mcastIp);
- Set<Link> storedTree = storedPaths.stream()
- .flatMap(Collection::stream).collect(Collectors.toSet());
- log.trace("Stored tree {}", storedTree);
- Set<Link> pathLinks;
- for (Path path : allPaths) {
- if (!src.equals(path.links().get(0).src().deviceId())) {
- continue;
- }
- pathLinks = Sets.newHashSet(path.links());
- score = Sets.intersection(pathLinks, storedTree).size();
- // score defines the index
- if (score > 0) {
- eligiblePaths.compute(score, (index, paths) -> {
- paths = paths == null ? Lists.newArrayList() : paths;
- paths.add(path);
- return paths;
- });
- }
- }
- if (eligiblePaths.isEmpty()) {
- log.trace("No eligiblePath(s) found from {} to {}", src, dst);
- Collections.shuffle(allPaths);
- return allPaths.stream().findFirst();
- }
- // Let's take the best ones
- Integer bestIndex = eligiblePaths.keySet().stream()
- .sorted(Comparator.reverseOrder()).findFirst().orElse(null);
- List<Path> bestPaths = eligiblePaths.get(bestIndex);
- log.trace("{} eligiblePath(s) found from {} to {}",
- bestPaths.size(), src, dst);
- Collections.shuffle(bestPaths);
- return bestPaths.stream().findFirst();
- }
-
- /**
- * Gets stored paths of the group.
- *
- * @param mcastIp group address
- * @return a collection of paths
- */
- private Set<List<Link>> getStoredPaths(IpAddress mcastIp) {
- return mcastPathStore.stream()
- .filter(entry -> entry.getKey().mcastIp().equals(mcastIp))
- .map(Entry::getValue)
- .collect(Collectors.toSet());
- }
-
- /**
- * Gets device(s) of given role and of given source in given multicast tree.
- *
- * @param mcastIp multicast IP
- * @param role multicast role
- * @param source source connect point
- * @return set of device ID or empty set if not found
- */
- private Set<DeviceId> getDevice(IpAddress mcastIp, McastRole role, ConnectPoint source) {
- return mcastRoleStore.entrySet().stream()
- .filter(entry -> entry.getKey().mcastIp().equals(mcastIp) &&
- entry.getKey().source().equals(source) &&
- entry.getValue().value() == role)
- .map(Entry::getKey).map(McastRoleStoreKey::deviceId).collect(Collectors.toSet());
- }
-
- /**
- * Gets device(s) of given role in given multicast group.
- *
- * @param mcastIp multicast IP
- * @param role multicast role
- * @return set of device ID or empty set if not found
- */
- private Set<DeviceId> getDevice(IpAddress mcastIp, McastRole role) {
- return mcastRoleStore.entrySet().stream()
- .filter(entry -> entry.getKey().mcastIp().equals(mcastIp) &&
- entry.getValue().value() == role)
- .map(Entry::getKey).map(McastRoleStoreKey::deviceId).collect(Collectors.toSet());
- }
-
- /**
- * Gets source(s) of given multicast group.
- *
- * @param mcastIp multicast IP
- * @return set of device ID or empty set if not found
- */
- private Set<ConnectPoint> getSources(IpAddress mcastIp) {
- return mcastRoleStore.entrySet().stream()
- .filter(entry -> entry.getKey().mcastIp().equals(mcastIp))
- .map(Entry::getKey).map(McastRoleStoreKey::source).collect(Collectors.toSet());
- }
-
- /**
- * Gets sink(s) of given multicast group.
- *
- * @param mcastIp multicast IP
- * @return set of connect point or empty set if not found
- */
- private Set<ConnectPoint> getSinks(IpAddress mcastIp, DeviceId device, ConnectPoint source) {
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
- mcastPathStore.get(pathStoreKey), Lists.newArrayList());
- VlanId assignedVlan = mcastUtils.assignedVlan(device.equals(source.deviceId()) ? source : null);
- McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, device, assignedVlan);
- NextObjective nextObjective = Versioned.valueOrNull(mcastNextObjStore.get(mcastStoreKey));
- ImmutableSet.Builder<ConnectPoint> cpBuilder = ImmutableSet.builder();
- if (nextObjective != null) {
- Set<PortNumber> outputPorts = mcastUtils.getPorts(nextObjective.next());
- outputPorts.forEach(portNumber -> cpBuilder.add(new ConnectPoint(device, portNumber)));
- }
- Set<ConnectPoint> egressCp = cpBuilder.build();
- return egressCp.stream()
- .filter(connectPoint -> !mcastUtils.isInfraPort(connectPoint, storedPaths))
- .collect(Collectors.toSet());
- }
-
-
-
- /**
- * Gets groups which is affected by the link down event.
- *
- * @param link link going down
- * @return a set of multicast IpAddress
- */
- private Set<IpAddress> getAffectedGroups(Link link) {
- DeviceId deviceId = link.src().deviceId();
- PortNumber port = link.src().port();
- return mcastNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(deviceId) &&
- mcastUtils.getPorts(entry.getValue().value().next()).contains(port))
- .map(Entry::getKey).map(McastStoreKey::mcastIp).collect(Collectors.toSet());
- }
-
- /**
- * Gets groups which are affected by the device down event.
- *
- * @param deviceId device going down
- * @return a set of multicast IpAddress
- */
- private Set<IpAddress> getAffectedGroups(DeviceId deviceId) {
- return mcastNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(deviceId))
- .map(Entry::getKey).map(McastStoreKey::mcastIp)
- .collect(Collectors.toSet());
- }
-
- /**
- * Verify if a given connect point is sink for this group.
- *
- * @param mcastIp group address
- * @param connectPoint connect point to be verified
- * @param source source connect point
- * @return true if the connect point is sink of the group
- */
- private boolean isSinkForGroup(IpAddress mcastIp, ConnectPoint connectPoint,
- ConnectPoint source) {
- VlanId assignedVlan = mcastUtils.assignedVlan(connectPoint.deviceId().equals(source.deviceId()) ?
- source : null);
- McastStoreKey mcastStoreKey = new McastStoreKey(mcastIp, connectPoint.deviceId(), assignedVlan);
- if (!mcastNextObjStore.containsKey(mcastStoreKey)) {
- return false;
- }
- NextObjective mcastNext = mcastNextObjStore.get(mcastStoreKey).value();
- return mcastUtils.getPorts(mcastNext.next()).contains(connectPoint.port());
- }
-
- /**
- * Verify if a given connect point is sink for this group and for this source.
- *
- * @param mcastIp group address
- * @param connectPoint connect point to be verified
- * @param source source connect point
- * @return true if the connect point is sink of the group
- */
- private boolean isSinkForSource(IpAddress mcastIp, ConnectPoint connectPoint,
- ConnectPoint source) {
- boolean isSink = isSinkForGroup(mcastIp, connectPoint, source);
- DeviceId device;
- if (connectPoint.deviceId().equals(source.deviceId())) {
- device = getDevice(mcastIp, INGRESS, source).stream()
- .filter(deviceId -> deviceId.equals(connectPoint.deviceId()))
- .findFirst().orElse(null);
- } else {
- device = getDevice(mcastIp, EGRESS, source).stream()
- .filter(deviceId -> deviceId.equals(connectPoint.deviceId()))
- .findFirst().orElse(null);
- }
- return isSink && device != null;
- }
-
- /**
- * Verify if a sink is reachable from this source.
- *
- * @param mcastIp group address
- * @param sink connect point to be verified
- * @param source source connect point
- * @return true if the connect point is reachable from the source
- */
- private boolean isSinkReachable(IpAddress mcastIp, ConnectPoint sink,
- ConnectPoint source) {
- return sink.deviceId().equals(source.deviceId()) ||
- getPath(source.deviceId(), sink.deviceId(), mcastIp, null).isPresent();
- }
-
- /**
- * Updates filtering objective for given device and port.
- * It is called in general when the mcast config has been
- * changed.
- *
- * @param deviceId device ID
- * @param portNum ingress port number
- * @param vlanId assigned VLAN ID
- * @param install true to add, false to remove
- */
- public void updateFilterToDevice(DeviceId deviceId, PortNumber portNum,
- VlanId vlanId, boolean install) {
- mcastWorker.execute(() -> updateFilterToDeviceInternal(deviceId, portNum, vlanId, install));
- }
-
- private void updateFilterToDeviceInternal(DeviceId deviceId, PortNumber portNum,
- VlanId vlanId, boolean install) {
- lastMcastChange.set(Instant.now());
- // Iterates over the route and updates properly the filtering objective on the source device.
- srManager.multicastRouteService.getRoutes().forEach(mcastRoute -> {
- log.debug("Update filter for {}", mcastRoute.group());
- if (!mcastUtils.isLeader(mcastRoute.group())) {
- log.debug("Skip {} due to lack of leadership", mcastRoute.group());
- return;
- }
- // Get the sources and for each one update properly the filtering objectives
- Set<ConnectPoint> sources = srManager.multicastRouteService.sources(mcastRoute);
- sources.forEach(source -> {
- if (source.deviceId().equals(deviceId) && source.port().equals(portNum)) {
- if (install) {
- McastFilteringObjStoreKey mcastFilterObjStoreKey = new McastFilteringObjStoreKey(source,
- vlanId, mcastRoute.group().isIp4());
- addFilterToDevice(mcastFilterObjStoreKey, mcastRoute.group(), INGRESS);
- } else {
- mcastUtils.removeFilterToDevice(deviceId, portNum, vlanId, mcastRoute.group(), null);
- }
- }
- });
- });
- }
-
- /**
- * Add filtering to the device if needed.
- *
- * @param filterObjStoreKey the filtering obj key
- * @param mcastIp the multicast group
- * @param mcastRole the multicast role
- */
- private void addFilterToDevice(McastFilteringObjStoreKey filterObjStoreKey,
- IpAddress mcastIp,
- McastRole mcastRole) {
- if (!containsFilterInTheDevice(filterObjStoreKey)) {
- // if this is the first sink for this group/device
- // match additionally on mac
- log.debug("Filtering not available for device {}, vlan {} and {}",
- filterObjStoreKey.ingressCP().deviceId(), filterObjStoreKey.vlanId(),
- filterObjStoreKey.isIpv4() ? "IPv4" : "IPv6");
- mcastUtils.addFilterToDevice(filterObjStoreKey.ingressCP().deviceId(),
- filterObjStoreKey.ingressCP().port(),
- filterObjStoreKey.vlanId(), mcastIp,
- mcastRole, true);
- mcastFilteringObjStore.add(filterObjStoreKey);
- } else if (!mcastFilteringObjStore.contains(filterObjStoreKey)) {
- // match only vlan
- log.debug("Filtering not available for connect point {}, vlan {} and {}",
- filterObjStoreKey.ingressCP(), filterObjStoreKey.vlanId(),
- filterObjStoreKey.isIpv4() ? "IPv4" : "IPv6");
- mcastUtils.addFilterToDevice(filterObjStoreKey.ingressCP().deviceId(),
- filterObjStoreKey.ingressCP().port(),
- filterObjStoreKey.vlanId(), mcastIp,
- mcastRole, false);
- mcastFilteringObjStore.add(filterObjStoreKey);
- } else {
- // do nothing
- log.debug("Filtering already present for connect point {}, vlan {} and {}. Abort",
- filterObjStoreKey.ingressCP(), filterObjStoreKey.vlanId(),
- filterObjStoreKey.isIpv4() ? "IPv4" : "IPv6");
- }
- }
-
- /**
- * Verify if there are related filtering obj in the device.
- *
- * @param filteringKey the filtering obj key
- * @return true if related filtering obj are found
- */
- private boolean containsFilterInTheDevice(McastFilteringObjStoreKey filteringKey) {
- // check if filters are already added on the device
- McastFilteringObjStoreKey key = mcastFilteringObjStore.stream()
- .filter(mcastFilteringKey ->
- mcastFilteringKey.ingressCP().deviceId().equals(filteringKey.ingressCP().deviceId())
- && mcastFilteringKey.isIpv4() == filteringKey.isIpv4()
- && mcastFilteringKey.vlanId().equals(filteringKey.vlanId())
- ).findFirst().orElse(null);
- // we are interested to filt obj on the same device, same vlan and same ip type
- return key != null;
- }
-
- /**
- * Update the filtering objective store upon device failure.
- *
- * @param affectedDevice the affected device
- */
- private void updateFilterObjStoreByDevice(DeviceId affectedDevice) {
- // purge the related filter objective key
- Set<McastFilteringObjStoreKey> filterObjs = Sets.newHashSet(mcastFilteringObjStore);
- Iterator<McastFilteringObjStoreKey> filterIterator = filterObjs.iterator();
- McastFilteringObjStoreKey filterKey;
- while (filterIterator.hasNext()) {
- filterKey = filterIterator.next();
- if (filterKey.ingressCP().deviceId().equals(affectedDevice)) {
- mcastFilteringObjStore.remove(filterKey);
- }
- }
- }
-
- /**
- * Update the filtering objective store upon port failure.
- *
- * @param affectedPort the affected port
- */
- private void updateFilterObjStoreByPort(ConnectPoint affectedPort) {
- // purge the related filter objective key
- Set<McastFilteringObjStoreKey> filterObjs = Sets.newHashSet(mcastFilteringObjStore);
- Iterator<McastFilteringObjStoreKey> filterIterator = filterObjs.iterator();
- McastFilteringObjStoreKey filterKey;
- while (filterIterator.hasNext()) {
- filterKey = filterIterator.next();
- if (filterKey.ingressCP().equals(affectedPort)) {
- mcastFilteringObjStore.remove(filterKey);
- }
- }
- }
-
- /**
- * Performs bucket verification operation for all mcast groups in the devices.
- * Firstly, it verifies that mcast is stable before trying verification operation.
- * Verification consists in creating new nexts with VERIFY operation. Actually,
- * the operation is totally delegated to the driver.
- */
- private final class McastBucketCorrector implements Runnable {
- private final AtomicInteger verifyOnFlight = new AtomicInteger(0);
- // Define the context used for the back pressure mechanism
- private final ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> {
- synchronized (verifyOnFlight) {
- log.trace("Verify {} done", objective.id());
- verifyOnFlight.updateAndGet(i -> i > 0 ? i - 1 : i);
- verifyOnFlight.notify();
- }
- },
- (objective, error) -> {
- synchronized (verifyOnFlight) {
- log.trace("Verify {} error {}", objective.id(), error);
- verifyOnFlight.updateAndGet(i -> i > 0 ? i - 1 : i);
- verifyOnFlight.notify();
- }
- });
-
- @Override
- public void run() {
- try {
- // Iterates over the routes and verify the related next objectives
- for (McastRoute mcastRoute : srManager.multicastRouteService.getRoutes()) {
- if (!isMcastStable() || wasBktCorrRunning()) {
- return;
- }
- IpAddress mcastIp = mcastRoute.group();
- log.trace("Running mcast buckets corrector for mcast group: {}", mcastIp);
- // Verify leadership on the operation
- if (!mcastUtils.isLeader(mcastIp)) {
- log.trace("Skip {} due to lack of leadership", mcastIp);
- continue;
- }
- // Get sources and sinks from Mcast Route Service and warn about errors
- Set<ConnectPoint> sources = mcastUtils.getSources(mcastIp);
- Set<ConnectPoint> sinks = mcastUtils.getSinks(mcastIp).values().stream()
- .flatMap(Collection::stream).collect(Collectors.toSet());
- // Do not proceed if sources of this group are missing
- if (sources.isEmpty()) {
- if (!sinks.isEmpty()) {
- log.warn("Unable to run buckets corrector. " +
- "Missing source {} for group {}", sources, mcastIp);
- }
- continue;
- }
- // For each group we get current information in the store
- // and issue a check of the next objectives in place
- Set<McastStoreKey> processedKeys = Sets.newHashSet();
- for (ConnectPoint source : sources) {
- Set<DeviceId> ingressDevices = getDevice(mcastIp, INGRESS, source);
- Set<DeviceId> transitDevices = getDevice(mcastIp, TRANSIT, source);
- Set<DeviceId> egressDevices = getDevice(mcastIp, EGRESS, source);
- // Do not proceed if ingress devices are missing
- if (ingressDevices.isEmpty()) {
- if (!sinks.isEmpty()) {
- log.warn("Unable to run buckets corrector. " +
- "Missing ingress {} for source {} and for group {}",
- ingressDevices, source, mcastIp);
- }
- continue;
- }
- // Create the set of the devices to be processed
- ImmutableSet.Builder<DeviceId> devicesBuilder = ImmutableSet.builder();
- devicesBuilder.addAll(ingressDevices);
- if (!transitDevices.isEmpty()) {
- devicesBuilder.addAll(transitDevices);
- }
- if (!egressDevices.isEmpty()) {
- devicesBuilder.addAll(egressDevices);
- }
- Set<DeviceId> devicesToProcess = devicesBuilder.build();
- for (DeviceId deviceId : devicesToProcess) {
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.trace("Skipping Bucket corrector for unconfigured device {}", deviceId);
- continue;
- }
- synchronized (verifyOnFlight) {
- while (verifyOnFlight.get() == MAX_VERIFY_ON_FLIGHT) {
- verifyOnFlight.wait();
- }
- }
- VlanId assignedVlan = mcastUtils.assignedVlan(deviceId.equals(source.deviceId()) ?
- source : null);
- McastStoreKey currentKey = new McastStoreKey(mcastIp, deviceId, assignedVlan);
- // Check if we already processed this next - trees merge at some point
- if (processedKeys.contains(currentKey)) {
- continue;
- }
- // Verify the nextobjective or skip to next device
- if (mcastNextObjStore.containsKey(currentKey)) {
- NextObjective currentNext = mcastNextObjStore.get(currentKey).value();
- // Rebuild the next objective using assigned vlan
- currentNext = mcastUtils.nextObjBuilder(mcastIp, assignedVlan,
- mcastUtils.getPorts(currentNext.next()), currentNext.id()).verify(context);
- // Send to the flowobjective service
- srManager.flowObjectiveService.next(deviceId, currentNext);
- verifyOnFlight.incrementAndGet();
- log.trace("Verify on flight {}", verifyOnFlight);
- processedKeys.add(currentKey);
- } else {
- log.warn("Unable to run buckets corrector. " +
- "Missing next for {}, for source {} and for group {}",
- deviceId, source, mcastIp);
- }
- }
- }
- // Let's wait the group before start the next one
- synchronized (verifyOnFlight) {
- while (verifyOnFlight.get() > 0) {
- verifyOnFlight.wait();
- }
- }
- }
- } catch (InterruptedException e) {
- log.warn("BktCorr has been interrupted");
- } finally {
- lastBktCorrExecution.set(Instant.now());
- }
- }
- }
-
- /**
- * Returns the associated next ids to the mcast groups or to the single
- * group if mcastIp is present.
- *
- * @param mcastIp the group ip
- * @return the mapping mcastIp-device to next id
- */
- public Map<McastStoreKey, Integer> getNextIds(IpAddress mcastIp) {
- log.info("mcastNexts {}", mcastNextObjStore.size());
- if (mcastIp != null) {
- return mcastNextObjStore.entrySet().stream()
- .filter(mcastEntry -> mcastIp.equals(mcastEntry.getKey().mcastIp()))
- .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().value().id()));
- }
- return mcastNextObjStore.entrySet().stream()
- .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().value().id()));
- }
-
- /**
- * Removes given next ID from mcast next id store.
- *
- * @param nextId next id
- */
- public void removeNextId(int nextId) {
- mcastNextObjStore.entrySet().forEach(e -> {
- if (e.getValue().value().id() == nextId) {
- mcastNextObjStore.remove(e.getKey());
- }
- });
- }
-
- /**
- * Build the mcast paths.
- *
- * @param storedPaths mcast tree
- * @param mcastIp the group ip
- * @param source the source
- */
- private Map<ConnectPoint, List<ConnectPoint>> buildMcastPaths(Collection<? extends List<Link>> storedPaths,
- IpAddress mcastIp, ConnectPoint source) {
- Map<ConnectPoint, List<ConnectPoint>> mcastTree = Maps.newHashMap();
- // Local sinks
- Set<ConnectPoint> localSinks = getSinks(mcastIp, source.deviceId(), source);
- localSinks.forEach(localSink -> mcastTree.put(localSink, Lists.newArrayList(localSink, source)));
- // Remote sinks
- storedPaths.forEach(path -> {
- List<Link> links = path;
- DeviceId egressDevice = links.get(links.size() - 1).dst().deviceId();
- Set<ConnectPoint> remoteSinks = getSinks(mcastIp, egressDevice, source);
- List<ConnectPoint> connectPoints = Lists.newArrayList(source);
- links.forEach(link -> {
- connectPoints.add(link.src());
- connectPoints.add(link.dst());
- });
- Collections.reverse(connectPoints);
- remoteSinks.forEach(remoteSink -> {
- List<ConnectPoint> finalPath = Lists.newArrayList(connectPoints);
- finalPath.add(0, remoteSink);
- mcastTree.put(remoteSink, finalPath);
- });
- });
- return mcastTree;
- }
-
- /**
- * Returns the associated roles to the mcast groups.
- *
- * @param mcastIp the group ip
- * @param sourcecp the source connect point
- * @return the mapping mcastIp-device to mcast role
- */
- public Map<McastRoleStoreKey, McastRole> getMcastRoles(IpAddress mcastIp,
- ConnectPoint sourcecp) {
- log.info("mcastRoles {}", mcastRoleStore.size());
- if (mcastIp != null) {
- Map<McastRoleStoreKey, McastRole> roles = mcastRoleStore.entrySet().stream()
- .filter(mcastEntry -> mcastIp.equals(mcastEntry.getKey().mcastIp()))
- .collect(Collectors.toMap(entry -> new McastRoleStoreKey(entry.getKey().mcastIp(),
- entry.getKey().deviceId(), entry.getKey().source()), entry -> entry.getValue().value()));
- if (sourcecp != null) {
- roles = roles.entrySet().stream()
- .filter(mcastEntry -> sourcecp.equals(mcastEntry.getKey().source()))
- .collect(Collectors.toMap(entry -> new McastRoleStoreKey(entry.getKey().mcastIp(),
- entry.getKey().deviceId(), entry.getKey().source()), Entry::getValue));
- }
- return roles;
- }
- return mcastRoleStore.entrySet().stream()
- .collect(Collectors.toMap(entry -> new McastRoleStoreKey(entry.getKey().mcastIp(),
- entry.getKey().deviceId(), entry.getKey().source()), entry -> entry.getValue().value()));
- }
-
- /**
- * Returns the associated trees to the mcast group.
- *
- * @param mcastIp the group ip
- * @param sourcecp the source connect point
- * @return the mapping egress point to mcast path
- */
- public Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
- ConnectPoint sourcecp) {
- // TODO remove
- log.info("{}", getStoredPaths(mcastIp));
- Multimap<ConnectPoint, List<ConnectPoint>> mcastTrees = HashMultimap.create();
- Set<ConnectPoint> sources = mcastUtils.getSources(mcastIp);
- if (sourcecp != null) {
- sources = sources.stream()
- .filter(source -> source.equals(sourcecp)).collect(Collectors.toSet());
- }
- if (!sources.isEmpty()) {
- sources.forEach(source -> {
- McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
- Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(
- mcastPathStore.get(pathStoreKey), Lists.newArrayList());
- // TODO remove
- log.info("Paths for group {} and source {} - {}", mcastIp, source, storedPaths.size());
- Map<ConnectPoint, List<ConnectPoint>> mcastTree = buildMcastPaths(storedPaths, mcastIp, source);
- mcastTree.forEach(mcastTrees::put);
- });
- }
- return mcastTrees;
- }
-
- /**
- * Return the leaders of the mcast groups.
- *
- * @param mcastIp the group ip
- * @return the mapping group-node
- */
- public Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp) {
- return mcastUtils.getMcastLeaders(mcastIp);
- }
-
- /**
- * Returns the mcast filtering obj.
- *
- * @return the mapping group-node
- */
- public Map<DeviceId, List<McastFilteringObjStoreKey>> getMcastFilters() {
- // TODO remove
- log.info("mcastFilters {}", mcastFilteringObjStore.size());
- Map<DeviceId, List<McastFilteringObjStoreKey>> mapping = Maps.newHashMap();
- Set<McastFilteringObjStoreKey> currentKeys = Sets.newHashSet(mcastFilteringObjStore);
- currentKeys.forEach(filteringObjStoreKey ->
- mapping.compute(filteringObjStoreKey.ingressCP().deviceId(), (k, v) -> {
- List<McastFilteringObjStoreKey> values = v;
- if (values == null) {
- values = Lists.newArrayList();
- }
- values.add(filteringObjStoreKey);
- return values;
- })
- );
- return mapping;
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java
deleted file mode 100644
index 76f46fe..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKey.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Key of multicast path store.
- */
-public class McastPathStoreKey {
- // Identify path using group address and source
- private final IpAddress mcastIp;
- private final ConnectPoint source;
-
- /**
- * Constructs the key of multicast path store.
- *
- * @param mcastIp multicast group IP address
- * @param source source connect point
- */
- public McastPathStoreKey(IpAddress mcastIp, ConnectPoint source) {
- checkNotNull(mcastIp, "mcastIp cannot be null");
- checkNotNull(source, "source cannot be null");
- checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
- this.mcastIp = mcastIp;
- this.source = source;
- }
-
- // Constructor for serialization
- private McastPathStoreKey() {
- this.mcastIp = null;
- this.source = null;
- }
-
- /**
- * Returns the multicast IP address of this key.
- *
- * @return multicast IP
- */
- public IpAddress mcastIp() {
- return mcastIp;
- }
-
- /**
- * Returns the device ID of this key.
- *
- * @return device ID
- */
- public ConnectPoint source() {
- return source;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof McastPathStoreKey)) {
- return false;
- }
- McastPathStoreKey that =
- (McastPathStoreKey) o;
- return (Objects.equals(this.mcastIp, that.mcastIp) &&
- Objects.equals(this.source, that.source));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mcastIp, source);
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("mcastIp", mcastIp)
- .add("source", source)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java
deleted file mode 100644
index 4ef0194..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastPathStoreKeySerializer.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-
-/**
- * Custom serializer for {@link McastPathStoreKey}.
- */
-class McastPathStoreKeySerializer extends Serializer<McastPathStoreKey> {
-
- /**
- * Creates {@link McastPathStoreKeySerializer} serializer instance.
- */
- McastPathStoreKeySerializer() {
- // non-null, immutable
- super(false, true);
- }
-
- @Override
- public void write(Kryo kryo, Output output, McastPathStoreKey object) {
- kryo.writeClassAndObject(output, object.mcastIp());
- kryo.writeClassAndObject(output, object.source());
- }
-
- @Override
- public McastPathStoreKey read(Kryo kryo, Input input, Class<McastPathStoreKey> type) {
- IpAddress mcastIp = (IpAddress) kryo.readClassAndObject(input);
- ConnectPoint source = (ConnectPoint) kryo.readClassAndObject(input);
- return new McastPathStoreKey(mcastIp, source);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRole.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRole.java
deleted file mode 100644
index 454bb5c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRole.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-/**
- * Enum that defines role in the multicast tree.
- */
-public enum McastRole {
- /**
- * The device is the ingress device of this group.
- */
- INGRESS,
- /**
- * The device is the transit device of this group.
- */
- TRANSIT,
- /**
- * The device is the egress device of this group.
- */
- EGRESS
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKey.java
deleted file mode 100644
index 26f21f2..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKey.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Key of multicast role store.
- */
-public class McastRoleStoreKey {
- // Identify role using group address, deviceId and source
- private final IpAddress mcastIp;
- private final DeviceId deviceId;
- private final ConnectPoint source;
-
- /**
- * Constructs the key of multicast role store.
- *
- * @param mcastIp multicast group IP address
- * @param deviceId device ID
- * @param source source connect point
- */
- public McastRoleStoreKey(IpAddress mcastIp, DeviceId deviceId, ConnectPoint source) {
- checkNotNull(mcastIp, "mcastIp cannot be null");
- checkNotNull(deviceId, "deviceId cannot be null");
- checkNotNull(source, "source cannot be null");
- checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
- this.mcastIp = mcastIp;
- this.deviceId = deviceId;
- this.source = source;
- }
-
- // Constructor for serialization
- private McastRoleStoreKey() {
- this.mcastIp = null;
- this.deviceId = null;
- this.source = null;
- }
-
- /**
- * Returns the multicast IP address of this key.
- *
- * @return multicast IP
- */
- public IpAddress mcastIp() {
- return mcastIp;
- }
-
- /**
- * Returns the device ID of this key.
- *
- * @return device ID
- */
- public DeviceId deviceId() {
- return deviceId;
- }
-
- /**
- * Returns the source connect point of this key.
- *
- * @return the source connect point
- */
- public ConnectPoint source() {
- return source;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof McastRoleStoreKey)) {
- return false;
- }
- final McastRoleStoreKey that = (McastRoleStoreKey) o;
-
- return Objects.equals(this.mcastIp, that.mcastIp) &&
- Objects.equals(this.deviceId, that.deviceId) &&
- Objects.equals(this.source, that.source);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mcastIp, deviceId, source);
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("mcastIp", mcastIp)
- .add("deviceId", deviceId)
- .add("source", source)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKeySerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKeySerializer.java
deleted file mode 100644
index aec7278..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastRoleStoreKeySerializer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-/**
- * Custom serializer for {@link McastRoleStoreKey}.
- */
-class McastRoleStoreKeySerializer extends Serializer<McastRoleStoreKey> {
-
- /**
- * Creates {@link McastRoleStoreKeySerializer} serializer instance.
- */
- McastRoleStoreKeySerializer() {
- // non-null, immutable
- super(false, true);
- }
-
- @Override
- public void write(Kryo kryo, Output output, McastRoleStoreKey object) {
- kryo.writeClassAndObject(output, object.mcastIp());
- output.writeString(object.deviceId().toString());
- kryo.writeClassAndObject(output, object.source());
- }
-
- @Override
- public McastRoleStoreKey read(Kryo kryo, Input input, Class<McastRoleStoreKey> type) {
- IpAddress mcastIp = (IpAddress) kryo.readClassAndObject(input);
- final String str = input.readString();
- DeviceId deviceId = DeviceId.deviceId(str);
- ConnectPoint source = (ConnectPoint) kryo.readClassAndObject(input);
- return new McastRoleStoreKey(mcastIp, deviceId, source);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKey.java
deleted file mode 100644
index aa32797..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKey.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import java.util.Objects;
-
-/**
- * Key of multicast next objective store.
- */
-public class McastStoreKey {
- // Identify a flow using group address, deviceId, and assigned vlan
- private final IpAddress mcastIp;
- private final DeviceId deviceId;
- private final VlanId vlanId;
-
- /**
- * Constructs the key of multicast next objective store.
- *
- * @param mcastIp multicast group IP address
- * @param deviceId device ID
- *
- * @deprecated in 1.12 ("Magpie") release.
- */
- @Deprecated
- public McastStoreKey(IpAddress mcastIp, DeviceId deviceId) {
- checkNotNull(mcastIp, "mcastIp cannot be null");
- checkNotNull(deviceId, "deviceId cannot be null");
- checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
- this.mcastIp = mcastIp;
- this.deviceId = deviceId;
- this.vlanId = null;
- }
-
- /**
- * Constructs the key of multicast next objective store.
- *
- * @param mcastIp multicast group IP address
- * @param deviceId device ID
- * @param vlanId vlan id
- */
- public McastStoreKey(IpAddress mcastIp, DeviceId deviceId, VlanId vlanId) {
- checkNotNull(mcastIp, "mcastIp cannot be null");
- checkNotNull(deviceId, "deviceId cannot be null");
- checkNotNull(vlanId, "vlan id cannot be null");
- checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address");
- this.mcastIp = mcastIp;
- this.deviceId = deviceId;
- // FIXME probably we should avoid not valid values
- this.vlanId = vlanId;
- }
-
- // Constructor for serialization
- private McastStoreKey() {
- this.mcastIp = null;
- this.deviceId = null;
- this.vlanId = null;
- }
-
- /**
- * Returns the multicast IP address of this key.
- *
- * @return multicast IP
- */
- public IpAddress mcastIp() {
- return mcastIp;
- }
-
- /**
- * Returns the device ID of this key.
- *
- * @return device ID
- */
- public DeviceId deviceId() {
- return deviceId;
- }
-
- /**
- * Returns the vlan ID of this key.
- *
- * @return vlan ID
- */
- public VlanId vlanId() {
- return vlanId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof McastStoreKey)) {
- return false;
- }
- McastStoreKey that =
- (McastStoreKey) o;
- return (Objects.equals(this.mcastIp, that.mcastIp) &&
- Objects.equals(this.deviceId, that.deviceId) &&
- Objects.equals(this.vlanId, that.vlanId));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mcastIp, deviceId, vlanId);
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("mcastIp", mcastIp)
- .add("deviceId", deviceId)
- .add("vlanId", vlanId)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKeySerializer.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKeySerializer.java
deleted file mode 100644
index c32b0ba..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastStoreKeySerializer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-/**
- * Custom serializer for {@link McastStoreKey}.
- */
-class McastStoreKeySerializer extends Serializer<McastStoreKey> {
-
- /**
- * Creates {@link McastStoreKeySerializer} serializer instance.
- */
- McastStoreKeySerializer() {
- // non-null, immutable
- super(false, true);
- }
-
- @Override
- public void write(Kryo kryo, Output output, McastStoreKey object) {
- kryo.writeClassAndObject(output, object.mcastIp());
- output.writeString(object.deviceId().toString());
- kryo.writeClassAndObject(output, object.vlanId());
- }
-
- @Override
- public McastStoreKey read(Kryo kryo, Input input, Class<McastStoreKey> type) {
- IpAddress mcastIp = (IpAddress) kryo.readClassAndObject(input);
- final String str = input.readString();
- DeviceId deviceId = DeviceId.deviceId(str);
- VlanId vlanId = (VlanId) kryo.readClassAndObject(input);
- return new McastStoreKey(mcastIp, deviceId, vlanId);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
deleted file mode 100644
index 396b998..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.mcast;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.hash.HashFunction;
-import com.google.common.hash.Hashing;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.basics.McastConfig;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.topology.LinkWeigher;
-import org.onosproject.net.topology.Topology;
-import org.onosproject.net.topology.TopologyService;
-import org.onosproject.segmentrouting.SRLinkWeigher;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Utility class for Multicast Handler.
- */
-class McastUtils {
- // Internal reference to the log
- private final Logger log;
- // Internal reference to SR Manager and topology service
- private final SegmentRoutingManager srManager;
- private final TopologyService topologyService;
- // Internal reference to the app id
- private ApplicationId coreAppId;
- // Hashing function for the multicast hasher
- private static final HashFunction HASH_FN = Hashing.md5();
- // Read only cache of the Mcast leader
- private Map<IpAddress, NodeId> mcastLeaderCache;
-
- /**
- * Builds a new McastUtils object.
- *
- * @param srManager the SR manager
- * @param coreAppId the core application id
- * @param log log reference of the McastHandler
- */
- McastUtils(SegmentRoutingManager srManager, ApplicationId coreAppId, Logger log) {
- this.srManager = srManager;
- this.topologyService = srManager.topologyService;
- this.coreAppId = coreAppId;
- this.log = log;
- this.mcastLeaderCache = Maps.newConcurrentMap();
- }
-
- /**
- * Clean up when deactivating the application.
- */
- void terminate() {
- mcastLeaderCache.clear();
- }
-
- /**
- * Get router mac using application config and the connect point.
- *
- * @param deviceId the device id
- * @param port the port number
- * @return the router mac if the port is configured, otherwise null
- */
- private MacAddress getRouterMac(DeviceId deviceId, PortNumber port) {
- // Do nothing if the port is configured as suppressed
- ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
- SegmentRoutingAppConfig appConfig = srManager.cfgService
- .getConfig(srManager.appId(), SegmentRoutingAppConfig.class);
- if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
- log.info("Ignore suppressed port {}", connectPoint);
- return MacAddress.NONE;
- }
- // Get the router mac using the device configuration
- MacAddress routerMac;
- try {
- routerMac = srManager.deviceConfiguration().getDeviceMac(deviceId);
- } catch (DeviceConfigNotFoundException dcnfe) {
- log.warn("Failed to get device MAC since the device {} is not configured", deviceId);
- return null;
- }
- return routerMac;
- }
-
- /**
- * Adds filtering objective for given device and port.
- *
- * @param deviceId device ID
- * @param port ingress port number
- * @param assignedVlan assigned VLAN ID
- * @param mcastIp the group address
- * @param mcastRole the role of the device
- * @param matchOnMac match or not on macaddress
- */
- void addFilterToDevice(DeviceId deviceId, PortNumber port, VlanId assignedVlan,
- IpAddress mcastIp, McastRole mcastRole, boolean matchOnMac) {
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("skip update of fitering objective for unconfigured device: {}", deviceId);
- return;
- }
- MacAddress routerMac = getRouterMac(deviceId, port);
-
- if (MacAddress.NONE.equals(routerMac)) {
- return;
- }
- FilteringObjective.Builder filtObjBuilder = filterObjBuilder(port, assignedVlan, mcastIp,
- routerMac, mcastRole, matchOnMac);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Successfully add filter on {}/{}, vlan {}",
- deviceId, port.toLong(), assignedVlan),
- (objective, error) ->
- log.warn("Failed to add filter on {}/{}, vlan {}: {}",
- deviceId, port.toLong(), assignedVlan, error));
- srManager.flowObjectiveService.filter(deviceId, filtObjBuilder.add(context));
- }
-
- /**
- * Removes filtering objective for given device and port.
- *
- * @param deviceId device ID
- * @param port ingress port number
- * @param assignedVlan assigned VLAN ID
- * @param mcastIp multicast IP address
- * @param mcastRole the multicast role of the device
- */
- void removeFilterToDevice(DeviceId deviceId, PortNumber port, VlanId assignedVlan,
- IpAddress mcastIp, McastRole mcastRole) {
- if (!srManager.deviceConfiguration().isConfigured(deviceId)) {
- log.debug("skip update of fitering objective for unconfigured device: {}", deviceId);
- return;
- }
- MacAddress routerMac = getRouterMac(deviceId, port);
-
- if (MacAddress.NONE.equals(routerMac)) {
- return;
- }
- FilteringObjective.Builder filtObjBuilder =
- filterObjBuilder(port, assignedVlan, mcastIp, routerMac, mcastRole, false);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Successfully removed filter on {}/{}, vlan {}",
- deviceId, port.toLong(), assignedVlan),
- (objective, error) ->
- log.warn("Failed to remove filter on {}/{}, vlan {}: {}",
- deviceId, port.toLong(), assignedVlan, error));
- srManager.flowObjectiveService.filter(deviceId, filtObjBuilder.remove(context));
- }
-
- /**
- * Gets ingress VLAN from McastConfig.
- *
- * @return ingress VLAN or VlanId.NONE if not configured
- */
- private VlanId ingressVlan() {
- McastConfig mcastConfig =
- srManager.cfgService.getConfig(coreAppId, McastConfig.class);
- return (mcastConfig != null) ? mcastConfig.ingressVlan() : VlanId.NONE;
- }
-
- /**
- * Gets egress VLAN from McastConfig.
- *
- * @return egress VLAN or VlanId.NONE if not configured
- */
- private VlanId egressVlan() {
- McastConfig mcastConfig =
- srManager.cfgService.getConfig(coreAppId, McastConfig.class);
- return (mcastConfig != null) ? mcastConfig.egressVlan() : VlanId.NONE;
- }
-
- /**
- * Gets assigned VLAN according to the value of egress VLAN.
- * If connect point is specified, try to reuse the assigned VLAN on the connect point.
- *
- * @param cp connect point; Can be null if not specified
- * @return assigned VLAN ID
- */
- VlanId assignedVlan(ConnectPoint cp) {
- // Use the egressVlan if it is tagged
- if (!egressVlan().equals(VlanId.NONE)) {
- return egressVlan();
- }
- // Reuse unicast VLAN if the port has subnet configured
- if (cp != null) {
- VlanId untaggedVlan = srManager.getInternalVlanId(cp);
- return (untaggedVlan != null) ? untaggedVlan
- : srManager.getDefaultInternalVlan();
- }
- // Use DEFAULT_VLAN if none of the above matches
- return srManager.getDefaultInternalVlan();
- }
-
-
-
- /**
- * Gets sources connect points of given multicast group.
- *
- * @param mcastIp multicast IP
- * @return sources connect points or empty set if not found
- */
- Set<ConnectPoint> getSources(IpAddress mcastIp) {
- // TODO we should support different types of routes
- McastRoute mcastRoute = srManager.multicastRouteService.getRoutes().stream()
- .filter(mcastRouteInternal -> mcastRouteInternal.group().equals(mcastIp))
- .findFirst().orElse(null);
- return mcastRoute == null ? ImmutableSet.of() :
- srManager.multicastRouteService.sources(mcastRoute);
- }
-
- /**
- * Gets sinks of given multicast group.
- *
- * @param mcastIp multicast IP
- * @return map of sinks or empty map if not found
- */
- Map<HostId, Set<ConnectPoint>> getSinks(IpAddress mcastIp) {
- // TODO we should support different types of routes
- McastRoute mcastRoute = srManager.multicastRouteService.getRoutes().stream()
- .filter(mcastRouteInternal -> mcastRouteInternal.group().equals(mcastIp))
- .findFirst().orElse(null);
- return mcastRoute == null ?
- ImmutableMap.of() :
- srManager.multicastRouteService.routeData(mcastRoute).sinks();
- }
-
- /**
- * Get sinks affected by this egress device.
- *
- * @param egressDevice the egress device
- * @param mcastIp the mcast ip address
- * @return the map of the sinks affected
- */
- Map<HostId, Set<ConnectPoint>> getAffectedSinks(DeviceId egressDevice,
- IpAddress mcastIp) {
- return getSinks(mcastIp).entrySet()
- .stream()
- .filter(hostIdSetEntry -> hostIdSetEntry.getValue().stream()
- .map(ConnectPoint::deviceId)
- .anyMatch(deviceId -> deviceId.equals(egressDevice))
- ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
- }
-
- /**
- * Creates a next objective builder for multicast.
- *
- * @param mcastIp multicast group
- * @param assignedVlan assigned VLAN ID
- * @param outPorts set of output port numbers
- * @param nextId the next id
- * @return next objective builder
- */
- NextObjective.Builder nextObjBuilder(IpAddress mcastIp, VlanId assignedVlan,
- Set<PortNumber> outPorts, Integer nextId) {
- // If nextId is null allocate a new one
- if (nextId == null) {
- nextId = srManager.flowObjectiveService.allocateNextId();
- }
- // Build the meta selector with the fwd objective info
- TrafficSelector metadata =
- DefaultTrafficSelector.builder()
- .matchVlanId(assignedVlan)
- .matchIPDst(mcastIp.toIpPrefix())
- .build();
- // Define the nextobjective type
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.BROADCAST)
- .fromApp(srManager.appId())
- .withMeta(metadata);
- // Add the output ports
- outPorts.forEach(port -> {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (egressVlan().equals(VlanId.NONE)) {
- tBuilder.popVlan();
- }
- tBuilder.setOutput(port);
- nextObjBuilder.addTreatment(tBuilder.build());
- });
- // Done return the complete builder
- return nextObjBuilder;
- }
-
- /**
- * Creates a forwarding objective builder for multicast.
- *
- * @param mcastIp multicast group
- * @param assignedVlan assigned VLAN ID
- * @param nextId next ID of the L3 multicast group
- * @return forwarding objective builder
- */
- ForwardingObjective.Builder fwdObjBuilder(IpAddress mcastIp,
- VlanId assignedVlan, int nextId) {
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- // Let's the matching on the group address
- // TODO SSM support in future
- if (mcastIp.isIp6()) {
- sbuilder.matchEthType(Ethernet.TYPE_IPV6);
- sbuilder.matchIPv6Dst(mcastIp.toIpPrefix());
- } else {
- sbuilder.matchEthType(Ethernet.TYPE_IPV4);
- sbuilder.matchIPDst(mcastIp.toIpPrefix());
- }
- // Then build the meta selector
- TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
- metabuilder.matchVlanId(assignedVlan);
- // Finally return the completed builder
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder();
- fwdBuilder.withSelector(sbuilder.build())
- .withMeta(metabuilder.build())
- .nextStep(nextId)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(srManager.appId())
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
- return fwdBuilder;
- }
-
- /**
- * Creates a filtering objective builder for multicast.
- *
- * @param ingressPort ingress port of the multicast stream
- * @param assignedVlan assigned VLAN ID
- * @param mcastIp the group address
- * @param routerMac router MAC. This is carried in metadata and used from some switches that
- * need to put unicast entry before multicast entry in TMAC table.
- * @param mcastRole the Multicast role
- * @param matchOnMac match or not on macaddress
- * @return filtering objective builder
- */
- private FilteringObjective.Builder filterObjBuilder(PortNumber ingressPort, VlanId assignedVlan,
- IpAddress mcastIp, MacAddress routerMac, McastRole mcastRole,
- boolean matchOnMac) {
- FilteringObjective.Builder filtBuilder = DefaultFilteringObjective.builder();
- // Let's add the in port matching and the priority
- filtBuilder.withKey(Criteria.matchInPort(ingressPort))
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
- // According to the mcast role we match on the proper vlan
- // If the role is null we are on the transit or on the egress
- if (mcastRole == null) {
- filtBuilder.addCondition(Criteria.matchVlanId(egressVlan()));
- } else {
- filtBuilder.addCondition(Criteria.matchVlanId(ingressVlan()));
- }
- // Add vlan info to the treatment builder
- TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder()
- .pushVlan().setVlanId(assignedVlan);
- // Additionally match on mac address and augment the treatment
- if (matchOnMac) {
- // According to the IP type we set the proper match on the mac address
- if (mcastIp.isIp4()) {
- filtBuilder.addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST,
- MacAddress.IPV4_MULTICAST_MASK));
- } else {
- filtBuilder.addCondition(Criteria.matchEthDstMasked(MacAddress.IPV6_MULTICAST,
- MacAddress.IPV6_MULTICAST_MASK));
- }
- // We set mac address to the treatment
- if (routerMac != null && !routerMac.equals(MacAddress.NONE)) {
- ttb.setEthDst(routerMac);
- }
- }
- // We finally build the meta treatment
- TrafficTreatment tt = ttb.build();
- filtBuilder.withMeta(tt);
- // Done, we return a permit filtering objective
- return filtBuilder.permit().fromApp(srManager.appId());
- }
-
- /**
- * Gets output ports information from treatments.
- *
- * @param treatments collection of traffic treatments
- * @return set of output port numbers
- */
- Set<PortNumber> getPorts(Collection<TrafficTreatment> treatments) {
- ImmutableSet.Builder<PortNumber> builder = ImmutableSet.builder();
- treatments.forEach(treatment -> treatment.allInstructions().stream()
- .filter(instr -> instr instanceof Instructions.OutputInstruction)
- .forEach(instr -> builder.add(((Instructions.OutputInstruction) instr).port())));
- return builder.build();
- }
-
- /**
- * Returns the hash of the group address.
- *
- * @param ipAddress the ip address
- * @return the hash of the address
- */
- private Long hasher(IpAddress ipAddress) {
- return HASH_FN.newHasher()
- .putBytes(ipAddress.toOctets())
- .hash()
- .asLong();
- }
-
- /**
- * Given a multicast group define a leader for it.
- *
- * @param mcastIp the group address
- * @return true if the instance is the leader of the group
- */
- boolean isLeader(IpAddress mcastIp) {
- // Get our id
- final NodeId currentNodeId = srManager.clusterService.getLocalNode().id();
- // Get the leader for this group using the ip address as key
- final NodeId leader = srManager.workPartitionService.getLeader(mcastIp, this::hasher);
- // If there is not a leader, let's send an error
- if (leader == null) {
- log.error("Fail to elect a leader for {}.", mcastIp);
- return false;
- }
- // Update cache and return operation result
- mcastLeaderCache.put(mcastIp, leader);
- return currentNodeId.equals(leader);
- }
-
- /**
- * Given a multicast group withdraw its leader.
- *
- * @param mcastIp the group address
- */
- void withdrawLeader(IpAddress mcastIp) {
- // For now just update the cache
- mcastLeaderCache.remove(mcastIp);
- }
-
- Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp) {
- // If mcast ip is present
- if (mcastIp != null) {
- return mcastLeaderCache.entrySet().stream()
- .filter(entry -> entry.getKey().equals(mcastIp))
- .collect(Collectors.toMap(Map.Entry::getKey,
- Map.Entry::getValue));
- }
- // Otherwise take all the groups
- return ImmutableMap.copyOf(mcastLeaderCache);
- }
-
- /**
- * Go through all the paths, looking for shared links to be used
- * in the final path computation.
- *
- * @param egresses egress devices
- * @param availablePaths all the available paths towards the egress
- * @return shared links between egress devices
- */
- private Set<Link> exploreMcastTree(Set<DeviceId> egresses,
- Map<DeviceId, List<Path>> availablePaths) {
- int minLength = Integer.MAX_VALUE;
- int length;
- List<Path> currentPaths;
- // Verify the source can still reach all the egresses
- for (DeviceId egress : egresses) {
- // From the source we cannot reach all the sinks
- // just continue and let's figure out after
- currentPaths = availablePaths.get(egress);
- if (currentPaths.isEmpty()) {
- continue;
- }
- // Get the length of the first one available, update the min length
- length = currentPaths.get(0).links().size();
- if (length < minLength) {
- minLength = length;
- }
- }
- // If there are no paths
- if (minLength == Integer.MAX_VALUE) {
- return Collections.emptySet();
- }
- int index = 0;
- Set<Link> sharedLinks = Sets.newHashSet();
- Set<Link> currentSharedLinks;
- Set<Link> currentLinks;
- DeviceId egressToRemove = null;
- // Let's find out the shared links
- while (index < minLength) {
- // Initialize the intersection with the paths related to the first egress
- currentPaths = availablePaths.get(egresses.stream().findFirst().orElse(null));
- currentSharedLinks = Sets.newHashSet();
- // Iterate over the paths and take the "index" links
- for (Path path : currentPaths) {
- currentSharedLinks.add(path.links().get(index));
- }
- // Iterate over the remaining egress
- for (DeviceId egress : egresses) {
- // Iterate over the paths and take the "index" links
- currentLinks = Sets.newHashSet();
- for (Path path : availablePaths.get(egress)) {
- currentLinks.add(path.links().get(index));
- }
- // Do intersection
- currentSharedLinks = Sets.intersection(currentSharedLinks, currentLinks);
- // If there are no shared paths exit and record the device to remove
- // we have to retry with a subset of sinks
- if (currentSharedLinks.isEmpty()) {
- egressToRemove = egress;
- index = minLength;
- break;
- }
- }
- sharedLinks.addAll(currentSharedLinks);
- index++;
- }
- // If the shared links is empty and there are egress let's retry another time with less sinks,
- // we can still build optimal subtrees
- if (sharedLinks.isEmpty() && egresses.size() > 1 && egressToRemove != null) {
- egresses.remove(egressToRemove);
- sharedLinks = exploreMcastTree(egresses, availablePaths);
- }
- return sharedLinks;
- }
-
- /**
- * Build Mcast tree having as root the given source and as leaves the given egress points.
- *
- * @param mcastIp multicast group
- * @param source source of the tree
- * @param sinks leaves of the tree
- * @return the computed Mcast tree
- */
- Map<ConnectPoint, List<Path>> computeSinkMcastTree(IpAddress mcastIp,
- DeviceId source,
- Set<ConnectPoint> sinks) {
- // Get the egress devices, remove source from the egress if present
- Set<DeviceId> egresses = sinks.stream().map(ConnectPoint::deviceId)
- .filter(deviceId -> !deviceId.equals(source)).collect(Collectors.toSet());
- Map<DeviceId, List<Path>> mcastTree = computeMcastTree(mcastIp, source, egresses);
- final Map<ConnectPoint, List<Path>> finalTree = Maps.newHashMap();
- // We need to put back the source if it was originally present
- sinks.forEach(sink -> {
- List<Path> sinkPaths = mcastTree.get(sink.deviceId());
- finalTree.put(sink, sinkPaths != null ? sinkPaths : ImmutableList.of());
- });
- return finalTree;
- }
-
- /**
- * Build Mcast tree having as root the given source and as leaves the given egress.
- *
- * @param mcastIp multicast group
- * @param source source of the tree
- * @param egresses leaves of the tree
- * @return the computed Mcast tree
- */
- private Map<DeviceId, List<Path>> computeMcastTree(IpAddress mcastIp,
- DeviceId source,
- Set<DeviceId> egresses) {
- log.debug("Computing tree for Multicast group {}, source {} and leafs {}",
- mcastIp, source, egresses);
- // Pre-compute all the paths
- Map<DeviceId, List<Path>> availablePaths = Maps.newHashMap();
- egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
- Collections.emptySet())));
- // Explore the topology looking for shared links amongst the egresses
- Set<Link> linksToEnforce = exploreMcastTree(Sets.newHashSet(egresses), availablePaths);
- // Build the final paths enforcing the shared links between egress devices
- availablePaths.clear();
- egresses.forEach(egress -> availablePaths.put(egress, getPaths(source, egress,
- linksToEnforce)));
- return availablePaths;
- }
-
- /**
- * Gets path from src to dst computed using the custom link weigher.
- *
- * @param src source device ID
- * @param dst destination device ID
- * @param linksToEnforce links to be enforced
- * @return list of paths from src to dst
- */
- List<Path> getPaths(DeviceId src, DeviceId dst, Set<Link> linksToEnforce) {
- final Topology currentTopology = topologyService.currentTopology();
- final LinkWeigher linkWeigher = new SRLinkWeigher(srManager, src, linksToEnforce);
- List<Path> allPaths = Lists.newArrayList(topologyService.getPaths(currentTopology, src, dst, linkWeigher));
- log.trace("{} path(s) found from {} to {}", allPaths.size(), src, dst);
- return allPaths;
- }
-
- /**
- * Gets a stored path having dst as egress.
- *
- * @param dst destination device ID
- * @param storedPaths paths list
- * @return an optional path
- */
- Optional<? extends List<Link>> getStoredPath(DeviceId dst, Collection<? extends List<Link>> storedPaths) {
- return storedPaths.stream()
- .filter(path -> path.get(path.size() - 1).dst().deviceId().equals(dst))
- .findFirst();
- }
-
- /**
- * Returns a set of affected paths by the failed element.
- *
- * @param paths the paths to check
- * @param failedElement the failed element
- * @return the affected paths
- */
- Set<List<Link>> getAffectedPaths(Set<List<Link>> paths, Object failedElement) {
- if (failedElement instanceof DeviceId) {
- return getAffectedPathsByDevice(paths, failedElement);
- }
- return getAffectedPathsByLink(paths, failedElement);
- }
-
- private Set<List<Link>> getAffectedPathsByDevice(Set<List<Link>> paths, Object failedElement) {
- DeviceId affectedDevice = (DeviceId) failedElement;
- Set<List<Link>> affectedPaths = Sets.newHashSet();
- paths.forEach(path -> {
- if (path.stream().anyMatch(link -> link.src().deviceId().equals(affectedDevice))) {
- affectedPaths.add(path);
- }
- });
- return affectedPaths;
- }
-
- private Set<List<Link>> getAffectedPathsByLink(Set<List<Link>> paths, Object failedElement) {
- Link affectedLink = (Link) failedElement;
- Set<List<Link>> affectedPaths = Sets.newHashSet();
- paths.forEach(path -> {
- if (path.contains(affectedLink)) {
- affectedPaths.add(path);
- }
- });
- return affectedPaths;
- }
-
- /**
- * Checks if the failure is affecting the transit device.
- *
- * @param devices the transit devices
- * @param failedElement the failed element
- * @return true if the failed element is affecting the transit devices
- */
- boolean isInfraFailure(Set<DeviceId> devices, Object failedElement) {
- if (failedElement instanceof DeviceId) {
- return isInfraFailureByDevice(devices, failedElement);
- }
- return true;
- }
-
- private boolean isInfraFailureByDevice(Set<DeviceId> devices, Object failedElement) {
- DeviceId affectedDevice = (DeviceId) failedElement;
- return devices.contains(affectedDevice);
- }
-
- /**
- * Checks if a port is an infra port.
- *
- * @param connectPoint port to be checked
- * @param storedPaths paths to be checked against
- * @return true if the port is an infra port. False otherwise.
- */
- boolean isInfraPort(ConnectPoint connectPoint, Collection<? extends List<Link>> storedPaths) {
- for (List<Link> path : storedPaths) {
- if (path.stream().anyMatch(link -> link.src().equals(connectPoint) ||
- link.dst().equals(connectPoint))) {
- return true;
- }
- }
- return false;
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/package-info.java
deleted file mode 100644
index dfdd39a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Trellis Multicast service.
- */
-package org.onosproject.segmentrouting.mcast;
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/package-info.java
deleted file mode 100644
index 137ba3c..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Segment routing application components.
- */
-package org.onosproject.segmentrouting;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/OsgiPropertyConstants.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/OsgiPropertyConstants.java
deleted file mode 100644
index cdeb8a2..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/OsgiPropertyConstants.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.api;
-
-/**
- * Constants for default values of configurable properties.
- */
-public final class OsgiPropertyConstants {
- private OsgiPropertyConstants() {}
-
- public static final String PROP_PHASED_RECOVERY = "phasedRecovery";
- public static final boolean PHASED_RECOVERY_DEFAULT = false;
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/Phase.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/Phase.java
deleted file mode 100644
index 7f18685..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/Phase.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.api;
-
-/**
- * Phases of recovering devices.
- */
-public enum Phase {
-
- /**
- * Device is waiting for ports to be reported.
- */
- PENDING,
-
- /**
- * Pair port enabled. This is the initial state for paired devices.
- */
- PAIR,
-
- /**
- * Infrastructure ports enabled.
- */
- INFRA,
-
- /**
- * Edge ports enabled. This is the initial state for non-paired and spine devices.
- */
- EDGE
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/PhasedRecoveryService.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/PhasedRecoveryService.java
deleted file mode 100644
index 705ecb7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/PhasedRecoveryService.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.api;
-
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Service that provides functionality related to phased recovery.
- */
-public interface PhasedRecoveryService {
-
- // TODO Make timeout values configurable via Component Config Service
- /**
- * Timeout for PAIR phase in seconds.
- */
- int PAIR_TIMEOUT = 30;
-
- /**
- * Timeout for INFRA phase in seconds.
- */
- int INFRA_TIMEOUT = 30;
-
- /**
- * Timeout for EDGE phase in seconds.
- */
- int EDGE_TIMEOUT = 30;
-
- //
- // Phased recovery APIs.
- //
-
-
- /**
- * Returns true if phased recovery is enabled.
- *
- * @return true if phased recovery is enabled.
- */
- boolean isEnabled();
-
- /**
- * Initializes a device. Only the master of the device is allowed to do this.
- *
- * @param deviceId device ID
- * @return true if the device is initialized successfully and the caller should proceed,
- * false if the device initialization has failed and the caller should abort.
- */
- boolean init(DeviceId deviceId);
-
- /**
- * Resets a device. Only the master of the device is allowed to do this.
- *
- * @param deviceId device ID
- * @return true if the device is reset successfully.
- * false if the device has not been previously initialized.
- */
- boolean reset(DeviceId deviceId);
-
- /**
- * Gets recovery phase of every devices.
- *
- * @return a map between device ID and recovery phase
- */
- Map<DeviceId, Phase> getPhases();
-
- /**
- * Gets recovery phase of given device.
- *
- * @param deviceId device ID
- * @return current phase or null if the device wasn't seen before
- */
- Phase getPhase(DeviceId deviceId);
-
- /**
- * Sets given device with given recovery phase. Only the master of the device is allowed to do this.
- *
- * @param deviceId device ID
- * @param newPhase recovery phase
- * @return new phase if transition succeeded, otherwise return current phase.
- */
- Phase setPhase(DeviceId deviceId, Phase newPhase);
-
- //
- // Port manipulation APIs.
- //
-
- /**
- * Enables every ports on the given device.
- *
- * @param deviceId device id
- * @param enabled true to enable, false to disable
- * @return ports that have been enabled
- */
- Set<PortNumber> changeAllPorts(DeviceId deviceId, boolean enabled);
-
- /**
- * Enables pair port on the given device.
- *
- * @param deviceId device id
- * @param enabled true to enable, false to disable
- * @return ports that have been enabled
- */
- Set<PortNumber> changePairPort(DeviceId deviceId, boolean enabled);
-
- /**
- * Enables infrastructure ports on the given device.
- *
- * @param deviceId device id
- * @param enabled true to enable, false to disable
- * @return ports that have been enabled
- */
- Set<PortNumber> changeInfraPorts(DeviceId deviceId, boolean enabled);
-
- /**
- * Enables edge ports on the given device.
- *
- * @param deviceId device id
- * @param enabled true to enable, false to disable
- * @return ports that have been enabled
- */
- Set<PortNumber> changeEdgePorts(DeviceId deviceId, boolean enabled);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/package-info.java
deleted file mode 100644
index cc556be..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/api/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Phased recovery API.
- */
-package org.onosproject.segmentrouting.phasedrecovery.api;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/PhasedRecoveryManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/PhasedRecoveryManager.java
deleted file mode 100644
index 5e25015..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/PhasedRecoveryManager.java
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.phasedrecovery.impl;
-
-import com.google.common.collect.Sets;
-import org.onlab.util.KryoNamespace;
-import org.onlab.util.Tools;
-import org.onosproject.cfg.ComponentConfigService;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceAdminService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.phasedrecovery.api.Phase;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.Versioned;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Modified;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Dictionary;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.segmentrouting.phasedrecovery.api.OsgiPropertyConstants.PHASED_RECOVERY_DEFAULT;
-import static org.onosproject.segmentrouting.phasedrecovery.api.OsgiPropertyConstants.PROP_PHASED_RECOVERY;
-
-@Component(
- immediate = true,
- service = PhasedRecoveryService.class,
- property = {
- PROP_PHASED_RECOVERY + ":Boolean=" + PHASED_RECOVERY_DEFAULT
- }
-)
-public class PhasedRecoveryManager implements PhasedRecoveryService {
- private static final Logger log = LoggerFactory.getLogger(PhasedRecoveryManager.class);
- private static final String APP_NAME = "org.onosproject.phasedrecovery";
-
- // TODO Make these configurable via Component Config
- // Amount of time delayed to wait for port description (in second)
- private static final int PORT_CHECKER_INTERVAL = 1;
- // Max number of retry for port checker
- private static final int PORT_CHECKER_RETRIES = 5;
- // RoutingStableChecker interval (in second)
- private static final int ROUTING_CHECKER_DELAY = 3;
- // RoutingStableChecker timeout (in second)
- private static final int ROUTING_CHECKER_TIMEOUT = 15;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private ComponentConfigService compCfgService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private DeviceAdminService deviceAdminService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private MastershipService mastershipService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private StorageService storageService;
-
- @Reference(cardinality = ReferenceCardinality.OPTIONAL)
- volatile SegmentRoutingService srService;
-
- /** Enabling phased recovery. */
- boolean phasedRecovery = PHASED_RECOVERY_DEFAULT;
-
- private ApplicationId appId;
- private ConsistentMap<DeviceId, Phase> phasedRecoveryStore;
- private ScheduledExecutorService executor = Executors.newScheduledThreadPool(
- Runtime.getRuntime().availableProcessors(), groupedThreads("onos/sr/pr", "executor"));
-
- @Activate
- protected void activate(ComponentContext context) {
- appId = coreService.registerApplication(APP_NAME);
-
- KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
- .register(KryoNamespaces.API)
- .register(Phase.class);
- phasedRecoveryStore = storageService.<DeviceId, Phase>consistentMapBuilder()
- .withName("onos-sr-phasedrecovery")
- .withRelaxedReadConsistency()
- .withSerializer(Serializer.using(serializer.build()))
- .build();
-
- compCfgService.registerProperties(getClass());
- modified(context);
- log.info("Started");
- }
-
- @Deactivate
- protected void deactivate() {
- phasedRecoveryStore.destroy();
- compCfgService.unregisterProperties(getClass(), false);
- log.info("Stopped");
- }
-
- @Modified
- protected void modified(ComponentContext context) {
- Dictionary<?, ?> properties = context.getProperties();
- if (properties == null) {
- return;
- }
-
- String strPhasedRecovery = Tools.get(properties, PROP_PHASED_RECOVERY);
- boolean expectPhasedRecovery = Boolean.parseBoolean(strPhasedRecovery);
- if (expectPhasedRecovery != phasedRecovery) {
- phasedRecovery = expectPhasedRecovery;
- log.info("{} phased recovery", phasedRecovery ? "Enabling" : "Disabling");
- }
- }
-
- @Override
- public boolean isEnabled() {
- return phasedRecovery;
- }
-
- @Override
- public boolean init(DeviceId deviceId) {
- if (this.srService == null) {
- log.info("SegmentRoutingService is not ready");
- return false;
- }
- if (!mastershipService.isLocalMaster(deviceId)) {
- log.info("Not master of {}", deviceId);
- return false;
- }
-
- Phase phase = Optional.ofNullable(phasedRecoveryStore.putIfAbsent(deviceId, Phase.PENDING))
- .map(Versioned::value).orElse(null);
-
- if (phase != null) {
- log.info("{} has been initialized already. Skipping.", deviceId);
- return false;
- } else {
- Phase nextPhase = (phasedRecovery && this.srService.getPairDeviceId(deviceId).isPresent()) ?
- Phase.PAIR : Phase.EDGE;
- if (nextPhase == Phase.PAIR) {
- // Wait for the PORT_STAT before entering next phase.
- // Note: Unlikely, when the device init fails due to PORT_STATS timeout,
- // it requires operator to manually move the device to the next phase by CLI command.
- executor.schedule(new PortChecker(deviceId, PORT_CHECKER_RETRIES),
- PORT_CHECKER_INTERVAL, TimeUnit.SECONDS);
- } else {
- // We assume that all ports will be reported as enabled on devices that don't require phased recovery
- setPhase(deviceId, Phase.EDGE);
- }
- return true;
- }
- }
-
- @Override
- public boolean reset(DeviceId deviceId) {
- if (this.srService == null) {
- log.info("SegmentRoutingService is not ready");
- return false;
- }
- // FIXME Skip mastership checking since master will not be available when a device goes offline
- // Improve this when persistent mastership is introduced
-
- Phase result = Optional.ofNullable(phasedRecoveryStore.remove(deviceId))
- .map(Versioned::value).orElse(null);
- if (result != null) {
- log.info("{} is reset", deviceId);
- }
- return result != null;
- }
-
- @Override
- public Map<DeviceId, Phase> getPhases() {
- return phasedRecoveryStore.asJavaMap();
- }
-
- @Override
- public Phase getPhase(DeviceId deviceId) {
- return Optional.ofNullable(phasedRecoveryStore.get(deviceId)).map(Versioned::value).orElse(null);
- }
-
- @Override
- public Phase setPhase(DeviceId deviceId, Phase newPhase) {
- if (this.srService == null) {
- log.info("SegmentRoutingService is not ready");
- return null;
- }
- if (!mastershipService.isLocalMaster(deviceId)) {
- log.info("Not master of {}", deviceId);
- return null;
- }
-
- return Optional.ofNullable(phasedRecoveryStore.compute(deviceId, (k, v) -> {
- if (v == null && newPhase == Phase.PENDING) {
- log.info("Initializing {}", deviceId);
- return newPhase;
- } else if (v == Phase.PENDING && newPhase == Phase.PAIR) {
- srService.initHost(deviceId);
- // RouteHandler init is intentionally skipped when phased recovery is on.
- // Edge ports remain down in this phase. Therefore, no nexthop will be discovered on the given device.
- // The flow on given device will be programmed later by hostHandler.processHostMovedEvent()
- changePairPort(deviceId, true);
- log.info("Transitioning {} from PENDING to PAIR", deviceId);
- return newPhase;
- } else if (v == Phase.PAIR && newPhase == Phase.INFRA) {
- changeInfraPorts(deviceId, true);
- srService.initRoute(deviceId);
- log.info("Transitioning {} from PAIR to INFRA", deviceId);
- monitorRoutingStability(deviceId);
- return newPhase;
- } else if (v == Phase.INFRA && newPhase == Phase.EDGE) {
- changeEdgePorts(deviceId, true);
- log.info("Transitioning {} from INFRA to EDGE", deviceId);
- return newPhase;
- } else if (v == Phase.PENDING && newPhase == Phase.EDGE) {
- changeAllPorts(deviceId, true);
- srService.initHost(deviceId);
- srService.initRoute(deviceId);
- log.info("Transitioning {} from PENDING to EDGE", deviceId);
- return newPhase;
- } else {
- log.debug("Ignore illegal state transition on {} from {} to {}", deviceId, v, newPhase);
- return v;
- }
- })).map(Versioned::value).orElse(null);
- }
-
- private void monitorRoutingStability(DeviceId deviceId) {
- CompletableFuture<Void> checkerFuture = new CompletableFuture<>();
- CompletableFuture<Void> timeoutFuture =
- Tools.completeAfter(ROUTING_CHECKER_TIMEOUT, TimeUnit.SECONDS);
- RoutingStabilityChecker checker = new RoutingStabilityChecker(checkerFuture);
-
- checkerFuture.runAfterEitherAsync(timeoutFuture, () -> {
- if (checkerFuture.isDone()) {
- log.info("Routing stable. Move {} to the next phase", deviceId);
- } else {
- log.info("Timeout reached. Move {} to the next phase", deviceId);
- // Mark the future as completed to signify the termination of periodical checker
- checkerFuture.complete(null);
- }
- setPhase(deviceId, Phase.EDGE);
- });
-
- executor.schedule(checker, ROUTING_CHECKER_DELAY, TimeUnit.SECONDS);
- }
-
- @Override
- public Set<PortNumber> changeAllPorts(DeviceId deviceId, boolean enabled) {
- if (this.srService == null) {
- log.warn("SegmentRoutingService is not ready. Unable to changeAllPorts({}) to {}", deviceId, enabled);
- return Sets.newHashSet();
- }
- Set<PortNumber> portsToBeEnabled = deviceAdminService.getPorts(deviceId)
- .stream().map(Port::number).collect(Collectors.toSet());
- changePorts(deviceId, portsToBeEnabled, enabled);
- return portsToBeEnabled;
- }
-
- @Override
- public Set<PortNumber> changePairPort(DeviceId deviceId, boolean enabled) {
- if (this.srService == null) {
- log.warn("SegmentRoutingService is not ready. Unable to changePairPort({}) to {}", deviceId, enabled);
- return Sets.newHashSet();
- }
- Set<PortNumber> portsToBeEnabled = this.srService.getPairLocalPort(deviceId)
- .map(Sets::newHashSet).orElse(Sets.newHashSet());
- changePorts(deviceId, portsToBeEnabled, enabled);
- return portsToBeEnabled;
- }
-
- @Override
- public Set<PortNumber> changeInfraPorts(DeviceId deviceId, boolean enabled) {
- if (this.srService == null) {
- log.warn("SegmentRoutingService is not ready. Unable to changeInfraPorts({}) to {}", deviceId, enabled);
- return Sets.newHashSet();
- }
- Set<PortNumber> portsToBeEnabled = this.srService.getInfraPorts(deviceId);
- changePorts(deviceId, portsToBeEnabled, enabled);
- return portsToBeEnabled;
- }
-
- @Override
- public Set<PortNumber> changeEdgePorts(DeviceId deviceId, boolean enabled) {
- if (this.srService == null) {
- log.warn("SegmentRoutingService is not ready. Unable to changeEdgePorts({}) to {}", deviceId, enabled);
- return Sets.newHashSet();
- }
- Set<PortNumber> portsToBeEnabled = this.srService.getEdgePorts(deviceId);
- changePorts(deviceId, portsToBeEnabled, enabled);
- return portsToBeEnabled;
- }
-
- private void changePorts(DeviceId deviceId, Set<PortNumber> portNumbers, boolean enabled) {
- log.info("{} {} on {}", enabled ? "Enabled" : "Disabled", portNumbers, deviceId);
- portNumbers.forEach(portNumber ->
- deviceAdminService.changePortState(deviceId, portNumber, enabled));
- }
-
- private class PortChecker implements Runnable {
- int retries;
- DeviceId deviceId;
-
- PortChecker(DeviceId deviceId, int retries) {
- this.deviceId = deviceId;
- this.retries = retries;
- }
-
- @Override
- public void run() {
- retries -= 1;
- if (retries < 0) {
- log.warn("PORT_STATS timeout. Unable to initialize {}", deviceId);
- return;
- }
-
- if (!deviceAdminService.getPorts(deviceId).isEmpty()) {
- log.info("{} reported PORT_STATS", deviceId);
- setPhase(deviceId, Phase.PAIR);
- }
- log.info("{} still waiting for PORT_STATS", deviceId);
- executor.schedule(this, PORT_CHECKER_INTERVAL, TimeUnit.SECONDS);
- }
- }
-
- private class RoutingStabilityChecker implements Runnable {
- private final CompletableFuture<Void> future;
-
- RoutingStabilityChecker(CompletableFuture<Void> future) {
- this.future = future;
- }
-
- @Override
- public void run() {
- // Do not continue if the future has been completed
- if (future.isDone()) {
- log.trace("RouteStabilityChecker is done. Stop checking");
- return;
- }
-
- if (srService.isRoutingStable()) {
- log.trace("Routing is stable");
- future.complete(null);
- } else {
- log.trace("Routing is not yet stable");
- executor.schedule(this, ROUTING_CHECKER_DELAY, TimeUnit.SECONDS);
- }
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/package-info.java
deleted file mode 100644
index 3788085..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/phasedrecovery/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Phased recovery implementation.
- */
-package org.onosproject.segmentrouting.phasedrecovery.impl;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java
deleted file mode 100644
index 417a795..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2Tunnel.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-
-import com.google.common.base.MoreObjects;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.Link;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Implementation of the default l2 tunnel.
- */
-public class DefaultL2Tunnel implements L2Tunnel {
-
- /**
- * Mode of the pseudo wire.
- */
- private L2Mode pwMode;
- /**
- * Service delimiting tag.
- */
- private VlanId sdTag;
- /**
- * Tunnel id.
- */
- private long tunnelId;
- /**
- * Pseudo wire label.
- */
- private MplsLabel pwLabel;
- /**
- * Inter-CO label.
- */
- private MplsLabel interCoLabel;
-
- private List<Link> pathUsed;
-
- /**
- * Vlan which will be used for the encapsualted
- * vlan traffic.
- */
- private VlanId transportVlan;
-
- /**
- * Creates a inter-co l2 tunnel using the
- * supplied parameters.
- *
- * @param mode the tunnel mode
- * @param sdtag the service delimiting tag
- * @param tunnelId the tunnel id
- * @param pwLabel the pseudo wire label
- * @param interCoLabel the inter central office label
- */
- public DefaultL2Tunnel(L2Mode mode, VlanId sdtag, long tunnelId, MplsLabel pwLabel, MplsLabel interCoLabel) {
- checkNotNull(mode);
- checkArgument(tunnelId > 0);
- checkNotNull(pwLabel);
- checkNotNull(interCoLabel);
-
- this.pwMode = mode;
- this.sdTag = sdtag;
- this.tunnelId = tunnelId;
- this.pwLabel = pwLabel;
- this.interCoLabel = interCoLabel;
- }
-
- /**
- * Creates a l2Tunnel from a given tunnel.
- *
- * @param l2Tunnel to replicate
- */
- public DefaultL2Tunnel(DefaultL2Tunnel l2Tunnel) {
-
- this.pwMode = l2Tunnel.pwMode();
- this.sdTag = l2Tunnel.sdTag();
- this.tunnelId = l2Tunnel.tunnelId();
- this.pwLabel = l2Tunnel.pwLabel();
- this.interCoLabel = l2Tunnel.interCoLabel();
- this.pathUsed = l2Tunnel.pathUsed();
- this.transportVlan = l2Tunnel.transportVlan;
- }
-
- /**
- * Creates a intra-co l2 tunnel using the
- * supplied parameters.
- *
- * @param mode the tunnel mode
- * @param sdtag the service delimiting tag
- * @param tunnelId the tunnel id
- * @param pwLabel the pseudo wire label
- */
- public DefaultL2Tunnel(L2Mode mode, VlanId sdtag, long tunnelId, MplsLabel pwLabel) {
- this(mode, sdtag, tunnelId, pwLabel, MplsLabel.mplsLabel(MplsLabel.MAX_MPLS));
- }
-
-
- /**
- * Creates an empty l2 tunnel.
- **/
- public DefaultL2Tunnel() {
- this.pwMode = null;
- this.sdTag = null;
- this.tunnelId = 0;
- this.pwLabel = null;
- this.interCoLabel = null;
- }
-
- /**
- * Returns the mode of the pseudo wire.
- *
- * @return the pseudo wire mode
- */
- @Override
- public L2Mode pwMode() {
- return pwMode;
- }
-
- /**
- * Returns the service delimitation
- * tag.
- *
- * @return the service delimitation vlan id
- */
- @Override
- public VlanId sdTag() {
- return sdTag;
- }
-
- /**
- * Returns the tunnel id of the pseudo wire.
- *
- * @return the pseudo wire tunnel id
- */
- @Override
- public long tunnelId() {
- return tunnelId;
- }
-
- /**
- * Returns the pw label.
- *
- * @return the mpls pw label
- */
- @Override
- public MplsLabel pwLabel() {
- return pwLabel;
- }
-
- /**
- * Set the path for the pseudowire.
- *
- * @param path The path to set
- */
- @Override
- public void setPath(List<Link> path) {
- pathUsed = new ArrayList<>(path);
- }
-
- /**
- * Set the transport vlan for the pseudowire.
- *
- * @param vlan the vlan to use.
- */
- @Override
- public void setTransportVlan(VlanId vlan) {
- transportVlan = vlan;
- }
-
- /**
- * Returns the used path of the pseudowire.
- *
- * @return pathUsed
- */
- @Override
- public List<Link> pathUsed() {
- return pathUsed;
- }
-
- @Override
- public VlanId transportVlan() {
- return transportVlan;
- }
-
-
- /**
- * Returns the inter-co label.
- *
- * @return the mpls inter-co label
- */
- @Override
- public MplsLabel interCoLabel() {
- return interCoLabel;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(this.tunnelId, this.pwMode, this.sdTag, this.pwLabel, this.interCoLabel);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o instanceof DefaultL2Tunnel) {
- DefaultL2Tunnel that = (DefaultL2Tunnel) o;
- return this.tunnelId == that.tunnelId &&
- this.pwMode.equals(that.pwMode) &&
- this.sdTag.equals(that.sdTag) &&
- this.pwLabel.equals(that.pwLabel) &&
- this.interCoLabel.equals(that.interCoLabel);
- }
-
- return false;
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("pwMode", pwMode())
- .add("sdTag", sdTag())
- .add("tunnelId", tunnelId())
- .add("pwLabel", pwLabel())
- .add("interCoLabel", interCoLabel())
- .add("transportVlan", transportVlan())
- .toString();
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java
deleted file mode 100644
index 7a47972..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelDescription.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-import com.google.common.base.MoreObjects;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Helper class to carry the l2 tunnel
- * and its policy.
- */
-public class DefaultL2TunnelDescription implements L2TunnelDescription {
-
- /**
- * The l2 tunnel.
- */
- private L2Tunnel l2Tunnel;
-
- /**
- * The l2 tunnel policy.
- */
- private L2TunnelPolicy l2TunnelPolicy;
-
- /**
- * Creates a l2 tunnel description using the given info.
- *
- * @param l2Tunnel the l2 tunnel
- * @param l2TunnelPolicy the l2 tunnel description
- */
- public DefaultL2TunnelDescription(L2Tunnel l2Tunnel,
- L2TunnelPolicy l2TunnelPolicy) {
- checkNotNull(l2Tunnel);
- checkNotNull(l2TunnelPolicy);
-
- this.l2Tunnel = l2Tunnel;
- this.l2TunnelPolicy = l2TunnelPolicy;
- }
-
- /**
- * Creates an empty l2 tunnel description.
- */
- public DefaultL2TunnelDescription() {
- this.l2Tunnel = null;
- this.l2TunnelPolicy = null;
- }
-
- @Override
- public L2Tunnel l2Tunnel() {
- return l2Tunnel;
- }
-
- @Override
- public L2TunnelPolicy l2TunnelPolicy() {
- return l2TunnelPolicy;
- }
-
- @Override
- public void setL2Tunnel(L2Tunnel tunnel) {
- l2Tunnel = tunnel;
- }
-
- @Override
- public void setL2TunnelPolicy(L2TunnelPolicy policy) {
- l2TunnelPolicy = policy;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(this.l2Tunnel, this.l2TunnelPolicy);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o instanceof DefaultL2TunnelDescription) {
- DefaultL2TunnelDescription that = (DefaultL2TunnelDescription) o;
- // Equality is based on tunnel id and pw label
- // which is always the last label.
- return this.l2Tunnel.equals(that.l2Tunnel) &&
- this.l2TunnelPolicy.equals(that.l2TunnelPolicy);
- }
-
- return false;
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("l2Tunnel", l2Tunnel())
- .add("l2TunnelPolicy", l2TunnelPolicy())
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
deleted file mode 100644
index 99ff091..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelHandler.java
+++ /dev/null
@@ -1,1490 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import org.apache.commons.lang3.RandomUtils;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.topology.LinkWeigher;
-import org.onosproject.segmentrouting.SRLinkWeigher;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.DistributedLock;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.StorageException;
-import org.onosproject.store.service.Versioned;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
-
-import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.INITIATION;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.TERMINATION;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result.*;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.FWD;
-import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.REV;
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
-
-/**
- * Handler for pseudowire management.
- */
-public class DefaultL2TunnelHandler implements L2TunnelHandler {
-
- private static final String LOCK_NAME = "l2-tunnel-handler-lock";
- private static final Logger log = LoggerFactory.getLogger(DefaultL2TunnelHandler.class);
-
- private final SegmentRoutingManager srManager;
- /**
- * To store the next objectives related to the initiation.
- */
- private final ConsistentMap<String, NextObjective> l2InitiationNextObjStore;
- /**
- * To store the next objectives related to the termination.
- */
- private final ConsistentMap<String, NextObjective> l2TerminationNextObjStore;
-
- /**
- * To store policies.
- */
- private final ConsistentMap<String, L2TunnelPolicy> l2PolicyStore;
-
- /**
- * To store tunnels.
- */
- private final ConsistentMap<String, L2Tunnel> l2TunnelStore;
-
- /**
- * To store pending tunnels that need to be installed.
- */
- private final ConsistentMap<String, L2Tunnel> pendingL2TunnelStore;
-
- /**
- * To store pending policies that need to be installed.
- */
- private final ConsistentMap<String, L2TunnelPolicy> pendingL2PolicyStore;
-
- private final KryoNamespace.Builder l2TunnelKryo;
-
- /**
- * Lock used when creating or removing pseudowires.
- */
- private final DistributedLock pwLock;
-
- private static final long LOCK_TIMEOUT = 2000;
-
- /**
- * Create a l2 tunnel handler for the deploy and
- * for the tear down of pseudo wires.
- *
- * @param segmentRoutingManager the segment routing manager
- */
- public DefaultL2TunnelHandler(SegmentRoutingManager segmentRoutingManager) {
- srManager = segmentRoutingManager;
- l2TunnelKryo = new KryoNamespace.Builder()
- .register(KryoNamespaces.API)
- .register(L2Tunnel.class,
- L2TunnelPolicy.class,
- DefaultL2Tunnel.class,
- DefaultL2TunnelPolicy.class,
- L2Mode.class,
- MplsLabel.class,
- VlanId.class,
- ConnectPoint.class);
-
- l2InitiationNextObjStore = srManager.
- storageService.
- <String, NextObjective>consistentMapBuilder().
- withName("onos-l2initiation-nextobj-store").
- withSerializer(Serializer.using(l2TunnelKryo.build())).
- build();
-
- l2TerminationNextObjStore = srManager.storageService.
- <String, NextObjective>consistentMapBuilder()
- .withName("onos-l2termination-nextobj-store")
- .withSerializer(Serializer.using(l2TunnelKryo.build()))
- .build();
-
- l2PolicyStore = srManager.storageService
- .<String, L2TunnelPolicy>consistentMapBuilder()
- .withName("onos-l2-policy-store")
- .withSerializer(Serializer.using(l2TunnelKryo.build()))
- .build();
-
- l2TunnelStore = srManager.storageService
- .<String, L2Tunnel>consistentMapBuilder()
- .withName("onos-l2-tunnel-store")
- .withSerializer(Serializer.using(l2TunnelKryo.build()))
- .build();
-
- pendingL2PolicyStore = srManager.storageService
- .<String, L2TunnelPolicy>consistentMapBuilder()
- .withName("onos-l2-pending-policy-store")
- .withSerializer(Serializer.using(l2TunnelKryo.build()))
- .build();
-
- pendingL2TunnelStore = srManager.storageService
- .<String, L2Tunnel>consistentMapBuilder()
- .withName("onos-l2-pending-tunnel-store")
- .withSerializer(Serializer.using(l2TunnelKryo.build()))
- .build();
-
- pwLock = srManager.storageService.lockBuilder()
- .withName(LOCK_NAME)
- .build()
- .asLock(LOCK_TIMEOUT);
- }
-
- /**
- * Used by manager only in initialization.
- */
- @Override
- public void init() {
- // Since we have no pseudowires in netcfg there
- // is nothing to do in initialization.
- // I leave it here because potentially we might need to
- // use it in the future.
- }
-
- @Override
- public Set<L2TunnelDescription> getL2Descriptions(boolean pending) {
- // get pending tunnels/policies OR installed tunnels/policies
- List<L2Tunnel> tunnels = pending ? getL2PendingTunnels() : getL2Tunnels();
- List<L2TunnelPolicy> policies = pending ? getL2PendingPolicies() : getL2Policies();
- return tunnels.stream()
- .map(l2Tunnel -> {
- L2TunnelPolicy policy = null;
- for (L2TunnelPolicy l2Policy : policies) {
- if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
- policy = l2Policy;
- break;
- }
- }
-
- return new DefaultL2TunnelDescription(l2Tunnel, policy);
- })
- .collect(Collectors.toSet());
- }
-
- @Override
- public List<L2TunnelPolicy> getL2Policies() {
- return new ArrayList<>(l2PolicyStore
- .values()
- .stream()
- .map(Versioned::value)
- .collect(Collectors.toList()));
- }
-
- @Override
- public List<L2Tunnel> getL2Tunnels() {
- return new ArrayList<>(l2TunnelStore
- .values()
- .stream()
- .map(Versioned::value)
- .collect(Collectors.toList()));
- }
-
- @Override
- public List<L2TunnelPolicy> getL2PendingPolicies() {
- return new ArrayList<>(pendingL2PolicyStore
- .values()
- .stream()
- .map(Versioned::value)
- .collect(Collectors.toList()));
- }
-
- @Override
- public List<L2Tunnel> getL2PendingTunnels() {
- return new ArrayList<>(pendingL2TunnelStore
- .values()
- .stream()
- .map(Versioned::value)
- .collect(Collectors.toList()));
- }
-
- @Override
- public Result verifyGlobalValidity(L2TunnelDescription pwToAdd) {
-
- // get both added and pending pseudowires
- List<L2TunnelDescription> newPseudowires = new ArrayList<>();
- newPseudowires.addAll(getL2Descriptions(false));
- newPseudowires.addAll(getL2Descriptions(true));
- // add the new one
- newPseudowires.add(pwToAdd);
-
- return configurationValidity(newPseudowires);
- }
-
- @Override
- public ImmutableMap<String, NextObjective> getInitNext() {
- if (l2InitiationNextObjStore != null) {
- return ImmutableMap.copyOf(l2InitiationNextObjStore.asJavaMap());
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public ImmutableMap<String, NextObjective> getTermNext() {
- if (l2TerminationNextObjStore != null) {
- return ImmutableMap.copyOf(l2TerminationNextObjStore.asJavaMap());
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public void removeNextId(int nextId) {
- l2InitiationNextObjStore.entrySet().forEach(e -> {
- if (e.getValue().value().id() == nextId) {
- l2InitiationNextObjStore.remove(e.getKey());
- }
- });
-
- l2TerminationNextObjStore.entrySet().forEach(e -> {
- if (e.getValue().value().id() == nextId) {
- l2TerminationNextObjStore.remove(e.getKey());
- }
- });
- }
-
- /**
- * Returns the new vlan id for an ingress point of a
- * pseudowire. For double tagged, it is the outer,
- * For single tagged it is the single tag, and for
- * inner it is None.
- *
- * @param ingressOuter vlanid of ingress outer
- * @param ingressInner vlanid of ingress inner
- * @param egressOuter vlanid of egress outer
- * @param egressInner vlanid of egress inner
- * @return returns the vlan id which will be installed at vlan table 1.
- */
- private VlanId determineEgressVlan(VlanId ingressOuter, VlanId ingressInner,
- VlanId egressOuter, VlanId egressInner) {
- // validity of vlan combinations was checked at verifyPseudowire
- if (!(ingressOuter.equals(VlanId.NONE))) {
- return egressOuter;
- } else if (!(ingressInner.equals(VlanId.NONE))) {
- return egressInner;
- } else {
- return VlanId.vlanId("None");
- }
- }
-
- /**
- * Returns the devices existing on a given path.
- *
- * @param path The path to traverse.
- * @return The devices on the path with the order they
- * are traversed.
- */
- private List<DeviceId> getDevicesOnPath(List<Link> path) {
-
- // iterate over links and get all devices in the order
- // we find them
- List<DeviceId> deviceList = new ArrayList<>();
- for (Link link : path) {
- if (!deviceList.contains(link.src().deviceId())) {
- deviceList.add(link.src().deviceId());
- }
- if (!deviceList.contains(link.dst().deviceId())) {
- deviceList.add(link.dst().deviceId());
- }
- }
-
- return deviceList;
- }
-
- /**
- * Returns true if path is valid according to the current logic.
- * For example : leaf to spine pseudowires can be either leaf-spine or
- * leaf-spine-spine. However, in the configuration we might specify spine device
- * first which will result in spine-spine-leaf. If leafSpinePw == true we have one of these
- * two cases and need to provision for them.
- *
- * If we have a leaf to leaf pseudowire then all the intermediate devices must
- * be spines. However, in case of paired switches we can have two leafs interconnected
- * with each other directly.
- *
- * @param path the chosen path
- * @param leafSpinePw if it is a leaf to spine pseudowire
- * @return True if path size is valid, false otherwise.
- */
- private boolean isValidPath(List<Link> path, boolean leafSpinePw) {
-
- log.debug("Checking path validity for pseudowire.");
- List<DeviceId> devices = getDevicesOnPath(path);
- if (devices.size() < 2) {
- log.error("Path size for pseudowire should be greater than 1!");
- return false;
- }
-
- try {
- if (leafSpinePw) {
- // can either be leaf-spine-spine or leaf-spine
- // first device is leaf, all other must be spines
- log.debug("Devices on path are {} for leaf to spine pseudowire", devices);
- // if first device is a leaf then all other must be spines
- if (srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
- devices.remove(0);
- for (DeviceId devId : devices) {
- log.debug("Device {} should be a spine!", devId);
- if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
- return false;
- }
- }
- } else {
- // if first device is spine, last device must be a leaf
- // all other devices must be spines
- if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
- return false;
- }
- devices.remove(devices.size() - 1);
- for (DeviceId devId : devices) {
- log.debug("Device {} should be a spine!", devId);
- if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
- return false;
- }
- }
- }
- } else {
- // can either be leaf-leaf (paired leafs) / leaf-spine-leaf
- // or leaf-spine-spine-leaf
- log.debug("Devices on path are {} for leaf to leaf pseudowire", devices);
- // check first device, needs to be a leaf
- if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
- return false;
- }
- // check last device, needs to be a leaf
- if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
- return false;
- }
- // remove these devices, rest must all be spines
- devices.remove(0);
- devices.remove(devices.size() - 1);
- for (DeviceId devId : devices) {
- log.debug("Device {} should be a spine!", devId);
- if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
- return false;
- }
- }
-
- }
- } catch (DeviceConfigNotFoundException e) {
- log.error("Device not found in configuration : {}", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Adds a single pseudowire.
- *
- * @param pw The pseudowire to deploy
- * @return result of pseudowire deployment
- */
- public Result deployPseudowire(L2TunnelDescription pw) {
-
- try {
- // take the lock
- pwLock.lock();
- Result result;
- long l2TunnelId;
- log.debug("Pseudowire with {} deployment started, check log for any errors in this process!",
- pw.l2Tunnel().tunnelId());
- l2TunnelId = pw.l2Tunnel().tunnelId();
- // The tunnel id cannot be 0.
- if (l2TunnelId == 0) {
- log.warn("Tunnel id id must be > 0 in {}", l2TunnelId);
- return Result.WRONG_PARAMETERS
- .appendError("Tunnel id id must be > 0");
- }
-
- result = verifyGlobalValidity(pw);
- if (result != SUCCESS) {
- log.error("Global validity for pseudowire {} is wrong!", l2TunnelId);
- return result;
- }
-
- // leafSpinePw determines if this is a leaf-leaf
- // or leaf-spine pseudowire
- boolean leafSpinePw;
- ConnectPoint cp1 = pw.l2TunnelPolicy().cP1();
- ConnectPoint cp2 = pw.l2TunnelPolicy().cP2();
- try {
- // differentiate between leaf-leaf pseudowires and leaf-spine
- if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
- !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
- log.error("Can not deploy pseudowire {} from spine to spine!", l2TunnelId);
- return Result.WRONG_PARAMETERS
- .appendError("Can not deploy pseudowire from spine to spine!");
- } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
- srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
- leafSpinePw = false;
- } else {
- leafSpinePw = true;
- }
- } catch (DeviceConfigNotFoundException e) {
- log.error("Device for pseudowire {} connection points does not exist in the configuration", l2TunnelId);
- return Result.INTERNAL_ERROR
- .appendError("Device for pseudowire connection points does not exist in the configuration");
- }
-
- // reverse the policy in order for leaf switch to be at CP1
- // this will help us for re-using SRLinkWeigher for computing valid paths
- L2TunnelPolicy reversedPolicy = reverseL2TunnelPolicy(pw.l2TunnelPolicy());
- if (reversedPolicy == null) {
- log.error("Error in reversing policy, device configuration was not found for pseudowire {}.",
- l2TunnelId);
- return INTERNAL_ERROR
- .appendError("Device configuration not found when reversing the policy.");
- }
- pw.setL2TunnelPolicy(reversedPolicy);
-
- // get path here, need to use the same for fwd and rev direction
- List<Link> path = getPath(pw.l2TunnelPolicy().cP1(),
- pw.l2TunnelPolicy().cP2());
- if (path == null || path.isEmpty()) {
- log.error("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
- return PATH_NOT_FOUND.appendError("No path between the connection points for pseudowire!");
- }
-
- Link fwdNextHop;
- Link revNextHop;
- if (!isValidPath(path, leafSpinePw)) {
- log.error("Deploying process : Path for pseudowire {} is not valid", l2TunnelId);
- return INTERNAL_ERROR.appendError("Internal error : path for pseudowire is not valid!");
- }
- // oneHope flag is used to determine if we need to
- // install transit mpls rules
- boolean oneHop = true;
- if (path.size() > 1) {
- oneHop = false;
- }
-
- fwdNextHop = path.get(0);
- revNextHop = reverseLink(path.get(path.size() - 1));
-
- pw.l2Tunnel().setPath(path);
- pw.l2Tunnel().setTransportVlan(srManager.getPwTransportVlan());
-
- // next hops for next objectives
- log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
-
- VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
- pw.l2TunnelPolicy().cP1InnerTag(),
- pw.l2TunnelPolicy().cP2OuterTag(),
- pw.l2TunnelPolicy().cP2InnerTag());
- result = deployPseudoWireInit(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP1(),
- pw.l2TunnelPolicy().cP2(),
- FWD,
- fwdNextHop,
- oneHop,
- egressVlan);
- if (result != SUCCESS) {
- log.error("Deploying process : Error in deploying pseudowire {} initiation for CP1", l2TunnelId);
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire initiation for CP1");
- }
-
- result = deployPolicy(l2TunnelId,
- pw.l2TunnelPolicy().cP1(),
- pw.l2TunnelPolicy().cP1InnerTag(),
- pw.l2TunnelPolicy().cP1OuterTag(),
- egressVlan,
- result.getNextId());
- if (result != SUCCESS) {
- log.error("Deploying process : Error in deploying pseudowire {} policy for CP1", l2TunnelId);
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire policy for CP1");
- }
-
- result = deployPseudoWireTerm(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP2(),
- egressVlan,
- FWD,
- oneHop);
-
- if (result != SUCCESS) {
- log.error("Deploying process : Error in deploying pseudowire {} termination for CP1", l2TunnelId);
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP1");
- }
-
- // We establish the reverse tunnel.
- log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);
- egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
- pw.l2TunnelPolicy().cP2InnerTag(),
- pw.l2TunnelPolicy().cP1OuterTag(),
- pw.l2TunnelPolicy().cP1InnerTag());
-
- result = deployPseudoWireInit(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP2(),
- pw.l2TunnelPolicy().cP1(),
- REV,
- revNextHop,
- oneHop,
- egressVlan);
- if (result != SUCCESS) {
- log.error("Deploying process : Error in deploying pseudowire {} initiation for CP2", l2TunnelId);
- return Result.INTERNAL_ERROR
- .appendError("Error in deploying pseudowire initiation for CP2");
- }
-
- result = deployPolicy(l2TunnelId,
- pw.l2TunnelPolicy().cP2(),
- pw.l2TunnelPolicy().cP2InnerTag(),
- pw.l2TunnelPolicy().cP2OuterTag(),
- egressVlan,
- result.getNextId());
- if (result != SUCCESS) {
- log.error("Deploying process : Error in deploying policy {} for CP2", l2TunnelId);
- return Result.INTERNAL_ERROR
- .appendError("Deploying process : Error in deploying policy for CP2");
- }
-
- result = deployPseudoWireTerm(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP1(),
- egressVlan,
- REV,
- oneHop);
-
- if (result != SUCCESS) {
- log.error("Deploying process : Error in deploying pseudowire {} termination for CP2", l2TunnelId);
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP2");
- }
-
- log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);
-
- // Populate stores as the final step of the process
- l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
- l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());
-
- return Result.SUCCESS;
- } catch (StorageException.Timeout e) {
- log.error("Can not acquire distributed lock for pseudowire {}!", pw.l2Tunnel().tunnelId());
- return Result.INTERNAL_ERROR.appendError("Can not acquire distributed lock!");
- } finally {
- // release the lock
- pwLock.unlock();
- }
- }
-
- @Override
- public Result checkIfPwExists(long tunnelId, boolean pending) {
-
- List<L2TunnelDescription> pseudowires = getL2Descriptions(pending)
- .stream()
- .filter(pw -> pw.l2Tunnel().tunnelId() == tunnelId)
- .collect(Collectors.toList());
-
- if (pseudowires.size() == 0) {
- String store = ((pending) ? "pending" : "installed");
- log.debug("Pseudowire {} does not exist in {} store", tunnelId, store);
- return Result.WRONG_PARAMETERS.
- appendError("Pseudowire " + tunnelId + " does not exist in " + store);
- } else {
- return SUCCESS;
- }
- }
-
- /**
- * Tears down connection points of pseudowires. We can either tear down both connection points,
- * or each one of them.
- *
- * @param l2TunnelId The tunnel id for this pseudowire.
- * @param tearDownFirst Boolean, true if we want to tear down cp1
- * @param tearDownSecond Boolean, true if we want to tear down cp2
- * @param pending Boolean, if true remove only pseudowire from pending stores since no flows/groups
- * in the network, else remove flows/groups in the devices also.
- * @return Result of tearing down the pseudowire, SUCCESS if everything was ok
- * a descriptive error otherwise.
- */
- private Result tearDownConnectionPoints(long l2TunnelId, boolean tearDownFirst,
- boolean tearDownSecond, boolean pending) {
-
- Result res;
- CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
- CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
- CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
- CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
-
- if (l2TunnelId == 0) {
- log.error("Removal process : Tunnel id cannot be 0");
- return Result.WRONG_PARAMETERS.appendError("Pseudowire id can not be 0.");
- }
-
- res = checkIfPwExists(l2TunnelId, pending);
- if (res != Result.SUCCESS) {
- return res;
- }
-
- // remove and get the tunnel and the policy from the appropriate store
- // if null, return error.
- Versioned<L2Tunnel> l2TunnelVersioned = pending ?
- pendingL2TunnelStore.remove(Long.toString(l2TunnelId)) :
- l2TunnelStore.remove(Long.toString(l2TunnelId));
- Versioned<L2TunnelPolicy> l2TunnelPolicyVersioned = pending ?
- pendingL2PolicyStore.remove(Long.toString(l2TunnelId)) :
- l2PolicyStore.remove(Long.toString(l2TunnelId));
- if ((l2TunnelVersioned == null) || (l2TunnelPolicyVersioned == null)) {
- log.warn("Removal process : Policy and/or tunnel missing for tunnel id {}", l2TunnelId);
- return Result.INTERNAL_ERROR
- .appendError("Policy and/or tunnel missing for pseudowire!");
- }
-
- L2TunnelDescription pwToRemove = new DefaultL2TunnelDescription(l2TunnelVersioned.value(),
- l2TunnelPolicyVersioned.value());
-
- if (pending) {
- // no need to remove flows / groups for a pseudowire
- // in pending state
- return Result.SUCCESS;
- }
-
- // remove flows/groups involving with this pseudowire
- if (tearDownFirst) {
- log.info("Removal process : Tearing down forward direction of pseudowire {}", l2TunnelId);
-
- VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP1OuterTag(),
- pwToRemove.l2TunnelPolicy().cP1InnerTag(),
- pwToRemove.l2TunnelPolicy().cP2OuterTag(),
- pwToRemove.l2TunnelPolicy().cP2InnerTag());
- deletePolicy(l2TunnelId,
- pwToRemove.l2TunnelPolicy().cP1(),
- pwToRemove.l2TunnelPolicy().cP1InnerTag(),
- pwToRemove.l2TunnelPolicy().cP1OuterTag(),
- egressVlan,
- fwdInitNextFuture,
- FWD);
-
- fwdInitNextFuture.thenAcceptAsync(status -> {
- if (status == null) {
- // Finally we will tear down the pseudo wire.
- tearDownPseudoWireInit(l2TunnelId,
- pwToRemove.l2TunnelPolicy().cP1(),
- fwdTermNextFuture,
- FWD);
- }
- });
-
- fwdTermNextFuture.thenAcceptAsync(status -> {
- if (status == null) {
- tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
- pwToRemove.l2TunnelPolicy().cP2(),
- null,
- FWD);
- }
- });
- }
-
- if (tearDownSecond) {
- log.info("Removal process : Tearing down reverse direction of pseudowire {}", l2TunnelId);
-
- VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP2OuterTag(),
- pwToRemove.l2TunnelPolicy().cP2InnerTag(),
- pwToRemove.l2TunnelPolicy().cP1OuterTag(),
- pwToRemove.l2TunnelPolicy().cP1InnerTag());
-
- // We do the same operations on the reverse side.
- deletePolicy(l2TunnelId,
- pwToRemove.l2TunnelPolicy().cP2(),
- pwToRemove.l2TunnelPolicy().cP2InnerTag(),
- pwToRemove.l2TunnelPolicy().cP2OuterTag(),
- egressVlan,
- revInitNextFuture,
- REV);
-
- revInitNextFuture.thenAcceptAsync(status -> {
- if (status == null) {
- tearDownPseudoWireInit(l2TunnelId,
- pwToRemove.l2TunnelPolicy().cP2(),
- revTermNextFuture,
- REV);
- }
- });
-
- revTermNextFuture.thenAcceptAsync(status -> {
- if (status == null) {
- tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
- pwToRemove.l2TunnelPolicy().cP1(),
- null,
- REV);
- }
- });
- }
-
- return Result.SUCCESS;
- }
-
- /**
- * Helper function for removing a single pseudowire.
- *
- * Tries to remove pseudowire from any store it might reside (pending or installed).
- *
- * @param l2TunnelId the id of the pseudowire to tear down
- * @return Returns SUCCESS if no error is obeserved or an appropriate
- * error on a failure
- */
- public Result tearDownPseudowire(long l2TunnelId) {
-
- try {
- // take the lock
- pwLock.lock();
-
- if (checkIfPwExists(l2TunnelId, true) == Result.SUCCESS) {
- return tearDownConnectionPoints(l2TunnelId, true, true, true);
- } else if (checkIfPwExists(l2TunnelId, false) == Result.SUCCESS) {
- return tearDownConnectionPoints(l2TunnelId, true, true, false);
- } else {
- return Result.WRONG_PARAMETERS.appendError("Pseudowire with "
- + l2TunnelId
- + " did not reside in any store!");
- }
- } catch (StorageException.Timeout e) {
- log.error("Can not acquire distributed lock for pseudowire {}!", l2TunnelId);
- return Result.INTERNAL_ERROR.appendError("Can not acquire distributed lock!");
- } finally {
- // release the lock
- pwLock.unlock();
- }
- }
-
- @Override
- @Deprecated
- public void tearDown(Set<L2TunnelDescription> pwToRemove) {
-
- for (L2TunnelDescription currentL2Tunnel : pwToRemove) {
-
- long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
- log.info("Removing pseudowire {}", tunnelId);
-
- Result result = tearDownPseudowire(tunnelId);
- if (result != Result.SUCCESS) {
- log.error("Could not remove pseudowire {}!", tunnelId);
- }
- }
- }
-
- /**
- * Handles the policy establishment which consists in
- * create the filtering and forwarding objectives related
- * to the initiation and termination.
- *
- * @param tunnelId the tunnel id
- * @param ingress the ingress point
- * @param ingressInner the ingress inner tag
- * @param ingressOuter the ingress outer tag
- * @param egressVlan Vlan-id to set, depends on ingress vlan
- * combinations. For example, if pw is double tagged
- * then this is the value of the outer vlan, if single
- * tagged then it is the new value of the single tag.
- * Should be None for untagged traffic.
- * @param nextId the next objective id
- * @return the result of the operation
- */
- private Result deployPolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner,
- VlanId ingressOuter, VlanId egressVlan, int nextId) {
- log.debug("Starting deploying policy for pseudowire {}.", tunnelId);
-
- List<Objective> objectives = Lists.newArrayList();
- // We create the forwarding objective for supporting
- // the l2 tunnel.
- ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
- // We create and add objective context.
- ObjectiveContext context = new DefaultObjectiveContext((objective) ->
- log.debug("FwdObj for tunnel {} populated", tunnelId),
- (objective, error) ->
- log.warn("Failed to populate fwdObj " +
- "for tunnel {} : {}",
- tunnelId, error));
- objectives.add(fwdBuilder.add(context));
-
- // We create the filtering objective to define the
- // permit traffic in the switch
- FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
-
- // We add the metadata.
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder()
- .setTunnelId(tunnelId)
- .setVlanId(egressVlan);
- filtBuilder.withMeta(treatment.build());
-
- // We create and add objective context.
- context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for tunnel {} populated", tunnelId),
- (objective, error) -> log.warn("Failed to populate filterObj for " +
- "tunnel {} : {}",
- tunnelId, error));
- objectives.add(filtBuilder.add(context));
-
- for (Objective objective : objectives) {
- if (objective instanceof ForwardingObjective) {
- srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
- log.debug("Creating new FwdObj for initiation NextObj with id={} for tunnel {}", nextId, tunnelId);
- } else {
- srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
- log.debug("Creating new FiltObj for tunnel {}", tunnelId);
- }
- }
- return SUCCESS;
- }
-
- /**
- * Handles the tunnel establishment which consists in
- * create the next objectives related to the initiation.
- *
- * @param l2Tunnel the tunnel to deploy
- * @param ingress the ingress connect point
- * @param egress the egress connect point
- * @param direction the direction of the pw
- * @param nextHop next hop of the initiation point
- * @param oneHop if this pseudowire has only one link
- * @param termVlanId the termination vlan id
- * @return the result of the operation
- */
- private Result deployPseudoWireInit(L2Tunnel l2Tunnel, ConnectPoint ingress,
- ConnectPoint egress, Direction direction,
- Link nextHop, boolean oneHop, VlanId termVlanId) {
- log.debug("Started deploying init next objectives for pseudowire {} for tunnel {} -> {}.",
- l2Tunnel.tunnelId(), ingress, egress);
- if (nextHop == null) {
- log.warn("No path between ingress and egress connection points for tunnel {}", l2Tunnel.tunnelId());
- return WRONG_PARAMETERS;
- }
-
- // We create the next objective without the metadata
- // context and id. We check if it already exists in the
- // store. If not we store as it is in the store.
- NextObjective.Builder nextObjectiveBuilder = createNextObjective(INITIATION,
- nextHop.src(),
- nextHop.dst(),
- l2Tunnel,
- egress.deviceId(),
- oneHop,
- termVlanId);
-
- if (nextObjectiveBuilder == null) {
- return INTERNAL_ERROR;
- }
- // We set the metadata. We will use this metadata
- // to inform the driver we are doing a l2 tunnel.
- TrafficSelector metadata = DefaultTrafficSelector
- .builder()
- .matchTunnelId(l2Tunnel.tunnelId())
- .build();
- nextObjectiveBuilder.withMeta(metadata);
- int nextId = srManager.flowObjectiveService.allocateNextId();
- if (nextId < 0) {
- log.warn("Not able to allocate a next id for initiation");
- return INTERNAL_ERROR;
- }
- nextObjectiveBuilder.withId(nextId);
- String key = generateKey(l2Tunnel.tunnelId(), direction);
- l2InitiationNextObjStore.put(key, nextObjectiveBuilder.add());
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Initiation l2 tunnel rule for {} populated", l2Tunnel.tunnelId()),
- (objective, error) -> {
- log.warn("Failed to populate Initiation l2 tunnel rule for {}: {}", l2Tunnel.tunnelId(), error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObjective = nextObjectiveBuilder.add(context);
- srManager.flowObjectiveService.next(ingress.deviceId(), nextObjective);
- log.debug("Initiation next objective for {} not found. Creating new NextObj with id={}",
- l2Tunnel.tunnelId(), nextObjective.id());
- Result result = SUCCESS;
- result.setNextId(nextObjective.id());
- return result;
- }
-
- /**
- * Handles the tunnel termination, which consists in the creation
- * of a forwarding objective and a next objective.
- *
- * @param l2Tunnel the tunnel to terminate
- * @param egress the egress point
- * @param egressVlan the expected vlan at egress
- * @param direction the direction
- * @return the result of the operation
- */
- private Result deployPseudoWireTerm(L2Tunnel l2Tunnel, ConnectPoint egress,
- VlanId egressVlan, Direction direction,
- boolean oneHop) {
- log.debug("Started deploying termination objectives for pseudowire {} , direction {}.",
- l2Tunnel.tunnelId(), direction == FWD ? "forward" : "reverse");
-
- // We create the group relative to the termination.
- NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
- l2Tunnel, egress.deviceId(),
- oneHop,
- egressVlan);
- if (nextObjectiveBuilder == null) {
- return INTERNAL_ERROR;
- }
- TrafficSelector metadata = DefaultTrafficSelector
- .builder()
- .matchVlanId(egressVlan)
- .build();
- nextObjectiveBuilder.withMeta(metadata);
- int nextId = srManager.flowObjectiveService.allocateNextId();
- if (nextId < 0) {
- log.warn("Not able to allocate a next id for initiation");
- return INTERNAL_ERROR;
- }
- nextObjectiveBuilder.withId(nextId);
- String key = generateKey(l2Tunnel.tunnelId(), direction);
- l2TerminationNextObjStore.put(key, nextObjectiveBuilder.add());
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("Termination l2 tunnel rule for {} populated", l2Tunnel.tunnelId()),
- (objective, error) -> {
- log.warn("Failed to populate termination l2 tunnel rule for {}: {}", l2Tunnel.tunnelId(), error);
- srManager.invalidateNextObj(objective.id());
- });
- NextObjective nextObjective = nextObjectiveBuilder.add(context);
- srManager.flowObjectiveService.next(egress.deviceId(), nextObjective);
- log.debug("Termination next objective for {} not found. Creating new NextObj with id={}",
- l2Tunnel.tunnelId(), nextObjective.id());
-
- // We create the flow relative to the termination.
- ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(), l2Tunnel.tunnelId(),
- egress.port(), nextObjective.id());
- context = new DefaultObjectiveContext((objective) -> log.debug("FwdObj for tunnel termination {} populated",
- l2Tunnel.tunnelId()),
- (objective, error) -> log.warn("Failed to populate fwdrObj" +
- " for tunnel termination {} : {}",
- l2Tunnel.tunnelId(), error));
- srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.add(context));
- log.debug("Creating new FwdObj for termination NextObj with id={} for tunnel {}",
- nextId, l2Tunnel.tunnelId());
-
- return SUCCESS;
- }
-
-
- /**
- * Creates the filtering objective according to a given policy.
- *
- * @param inPort the in port
- * @param innerTag the inner vlan tag
- * @param outerTag the outer vlan tag
- * @return the filtering objective
- */
- private FilteringObjective.Builder createFiltObjective(PortNumber inPort, VlanId innerTag, VlanId outerTag) {
-
- log.debug("Creating connection point filtering objective for vlans {} / {}", outerTag, innerTag);
- return DefaultFilteringObjective
- .builder()
- .withKey(Criteria.matchInPort(inPort))
- .addCondition(Criteria.matchInnerVlanId(innerTag))
- .addCondition(Criteria.matchVlanId(outerTag))
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
- .permit()
- .fromApp(srManager.appId());
- }
-
- /**
- * Creates the forwarding objective for the termination.
- *
- * @param pwLabel the pseudo wire label
- * @param tunnelId the tunnel id
- * @param egressPort the egress port
- * @param nextId the next step
- * @return the forwarding objective to support the termination
- */
- private ForwardingObjective.Builder createTermFwdObjective(MplsLabel pwLabel, long tunnelId,
- PortNumber egressPort, int nextId) {
-
- log.debug("Creating forwarding objective for termination for tunnel {} : pwLabel {}, egressPort {}, nextId {}",
- tunnelId, pwLabel, egressPort, nextId);
- TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder trafficTreatment = DefaultTrafficTreatment.builder();
- // The flow has to match on the pw label and bos
- trafficSelector.matchEthType(Ethernet.MPLS_UNICAST);
- trafficSelector.matchMplsLabel(pwLabel);
- trafficSelector.matchMplsBos(true);
- // The flow has to decrement ttl, restore ttl in
- // pop mpls, set tunnel id and port.
- trafficTreatment.decMplsTtl();
- trafficTreatment.copyTtlIn();
- trafficTreatment.popMpls();
- trafficTreatment.setTunnelId(tunnelId);
- trafficTreatment.setOutput(egressPort);
-
- return DefaultForwardingObjective
- .builder()
- .fromApp(srManager.appId())
- .makePermanent()
- .nextStep(nextId)
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
- .withSelector(trafficSelector.build())
- .withTreatment(trafficTreatment.build())
- .withFlag(VERSATILE);
- }
-
- /**
- * Creates the forwarding objective for the initiation.
- *
- * @param tunnelId the tunnel id
- * @param inPort the input port
- * @param nextId the next step
- * @return the forwarding objective to support the initiation.
- */
- private ForwardingObjective.Builder createInitFwdObjective(long tunnelId, PortNumber inPort, int nextId) {
-
- log.debug("Creating forwarding objective for tunnel {} : Port {} , nextId {}", tunnelId, inPort, nextId);
- TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
-
- // The flow has to match on the mpls logical
- // port and the tunnel id.
- trafficSelector.matchTunnelId(tunnelId);
- trafficSelector.matchInPort(inPort);
-
- return DefaultForwardingObjective
- .builder()
- .fromApp(srManager.appId())
- .makePermanent()
- .nextStep(nextId)
- .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
- .withSelector(trafficSelector.build())
- .withFlag(VERSATILE);
-
- }
-
- /**
- * Creates the next objective according to a given
- * pipeline. We don't set the next id and we don't
- * create the final meta to check if we are re-using
- * the same next objective for different tunnels.
- *
- * @param pipeline the pipeline to support
- * @param srcCp the source port
- * @param dstCp the destination port
- * @param l2Tunnel the tunnel to support
- * @param egressId the egress device id
- * @param oneHop if the pw only has one hop, push only pw label
- * @param termVlanId the outer vlan id of the packet exiting a termination point
- * @return the next objective to support the pipeline
- */
- private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp,
- ConnectPoint dstCp, L2Tunnel l2Tunnel,
- DeviceId egressId, boolean oneHop,
- VlanId termVlanId) {
- log.debug("Creating {} next objective for pseudowire {}.",
- pipeline == TERMINATION ? "termination" : "inititation");
-
- NextObjective.Builder nextObjBuilder;
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
- if (pipeline == INITIATION) {
- nextObjBuilder = DefaultNextObjective
- .builder()
- .withType(NextObjective.Type.SIMPLE)
- .fromApp(srManager.appId());
- // The pw label is the bottom of stack. It has to
- // be different -1.
- if (l2Tunnel.pwLabel().toInt() == MplsLabel.MAX_MPLS) {
- log.error("Pw label not configured");
- return null;
- }
- treatmentBuilder.pushMpls();
- treatmentBuilder.setMpls(l2Tunnel.pwLabel());
- treatmentBuilder.setMplsBos(true);
- treatmentBuilder.copyTtlOut();
-
- // If the inter-co label is present we have to set the label.
- if (l2Tunnel.interCoLabel().toInt() != MplsLabel.MAX_MPLS) {
- treatmentBuilder.pushMpls();
- treatmentBuilder.setMpls(l2Tunnel.interCoLabel());
- treatmentBuilder.setMplsBos(false);
- treatmentBuilder.copyTtlOut();
- }
-
- // if not oneHop install transit mpls labels also
- if (!oneHop) {
- // We retrieve the sr label from the config
- // specific for pseudowire traffic
- // using the egress leaf device id.
- MplsLabel srLabel;
- try {
- srLabel = MplsLabel.mplsLabel(srManager.deviceConfiguration().getPWRoutingLabel(egressId));
-
- } catch (DeviceConfigNotFoundException e) {
- log.error("Sr label for pw traffic not configured");
- return null;
- }
-
- treatmentBuilder.pushMpls();
- treatmentBuilder.setMpls(srLabel);
- treatmentBuilder.setMplsBos(false);
- treatmentBuilder.copyTtlOut();
- }
-
- // We have to rewrite the src and dst mac address.
- MacAddress ingressMac;
- try {
- ingressMac = srManager.deviceConfiguration().getDeviceMac(srcCp.deviceId());
- } catch (DeviceConfigNotFoundException e) {
- log.error("Was not able to find the ingress mac");
- return null;
- }
- treatmentBuilder.setEthSrc(ingressMac);
- MacAddress neighborMac;
- try {
- neighborMac = srManager.deviceConfiguration().getDeviceMac(dstCp.deviceId());
- } catch (DeviceConfigNotFoundException e) {
- log.error("Was not able to find the neighbor mac");
- return null;
- }
- treatmentBuilder.setEthDst(neighborMac);
-
- // set the appropriate transport vlan from tunnel information
- treatmentBuilder.setVlanId(l2Tunnel.transportVlan());
- } else {
- // We create the next objective which
- // will be a simple l2 group.
- nextObjBuilder = DefaultNextObjective
- .builder()
- .withType(NextObjective.Type.SIMPLE)
- .fromApp(srManager.appId());
-
- // for termination point we use the outer vlan of the
- // encapsulated packet for the vlan
- treatmentBuilder.setVlanId(termVlanId);
- }
-
- treatmentBuilder.setOutput(srcCp.port());
- nextObjBuilder.addTreatment(treatmentBuilder.build());
- return nextObjBuilder;
- }
-
- /**
- * Reverse an l2 tunnel policy in order to have as CP1 the leaf switch,
- * in case one of the switches is a spine.
- *
- * This makes possible the usage of SRLinkWeigher for computing valid paths,
- * which cuts leaf-spine links from the path computation with a src different
- * than the source leaf.
- *
- * @param policy The policy to reverse, if needed
- * @return a l2TunnelPolicy containing the leaf at CP1, suitable for usage with
- * current SRLinkWeigher
- */
- private L2TunnelPolicy reverseL2TunnelPolicy(L2TunnelPolicy policy) {
-
- log.debug("Reversing policy for pseudowire.");
- try {
- // if cp1 is a leaf, just return
- if (srManager.deviceConfiguration().isEdgeDevice(policy.cP1().deviceId())) {
- return policy;
- } else {
- // return a policy with reversed cp1 and cp2, and also with reversed tags
- return new DefaultL2TunnelPolicy(policy.tunnelId(),
- policy.cP2(), policy.cP2InnerTag(), policy.cP2OuterTag(),
- policy.cP1(), policy.cP1InnerTag(), policy.cP1OuterTag());
-
- }
- } catch (DeviceConfigNotFoundException e) {
- // should never come here, since it has been checked before
- log.error("Configuration for device {}, does not exist!");
- return null;
- }
- }
-
- /**
- * Reverses a link.
- *
- * @param link link to be reversed
- * @return the reversed link
- */
- private Link reverseLink(Link link) {
-
- DefaultLink.Builder linkBuilder = DefaultLink.builder();
-
- linkBuilder.src(link.dst());
- linkBuilder.dst(link.src());
- linkBuilder.type(link.type());
- linkBuilder.providerId(link.providerId());
-
- return linkBuilder.build();
- }
-
- /**
- * Returns the path betwwen two connect points.
- *
- * @param srcCp source connect point
- * @param dstCp destination connect point
- * @return the path
- */
- private List<Link> getPath(ConnectPoint srcCp, ConnectPoint dstCp) {
-
- // use SRLinkWeigher to avoid pair links, and also
- // avoid going from the spine to the leaf and to the
- // spine again, we need to have the leaf as CP1 here.
- LinkWeigher srLw = new SRLinkWeigher(srManager, srcCp.deviceId(), new HashSet<Link>());
-
- Set<Path> paths = srManager.topologyService.
- getPaths(srManager.topologyService.currentTopology(),
- srcCp.deviceId(), dstCp.deviceId(), srLw);
-
- log.debug("Paths obtained from topology service {}", paths);
-
- // We randomly pick a path.
- if (paths.isEmpty()) {
- return null;
- }
- int size = paths.size();
- int index = RandomUtils.nextInt(0, size);
-
- List<Link> result = Iterables.get(paths, index).links();
- log.debug("Randomly picked a path {}", result);
-
- return result;
- }
-
- /**
- * Deletes a given policy using the parameter supplied.
- *
- * @param tunnelId the tunnel id
- * @param ingress the ingress point
- * @param ingressInner the ingress inner vlan id
- * @param ingressOuter the ingress outer vlan id
- * @param future to perform the async operation
- * @param direction the direction: forward or reverse
- */
- private void deletePolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner, VlanId ingressOuter,
- VlanId egressVlan, CompletableFuture<ObjectiveError> future, Direction direction) {
-
- String key = generateKey(tunnelId, direction);
- if (!l2InitiationNextObjStore.containsKey(key)) {
- log.error("Abort delete of policy for tunnel {}: next does not exist in the store", tunnelId);
- if (future != null) {
- future.complete(null);
- }
- return;
- }
- NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
- int nextId = nextObjective.id();
- List<Objective> objectives = Lists.newArrayList();
- // We create the forwarding objective.
- ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
- ObjectiveContext context = new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.debug("Previous fwdObj for policy {} removed", tunnelId);
- if (future != null) {
- future.complete(null);
- }
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.error("Failed to remove previous fwdObj for policy {}: {}", tunnelId, error);
- if (future != null) {
- future.complete(error);
- }
- }
- };
- objectives.add(fwdBuilder.remove(context));
- // We create the filtering objective to define the
- // permit traffic in the switch
- FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder()
- .setTunnelId(tunnelId)
- .setVlanId(egressVlan);
- filtBuilder.withMeta(treatment.build());
- context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for policy {} revoked", tunnelId),
- (objective, error) ->
- log.warn("Failed to revoke filterObj for policy {}",
- tunnelId, error));
- objectives.add(filtBuilder.remove(context));
-
- for (Objective objective : objectives) {
- if (objective instanceof ForwardingObjective) {
- srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
- } else {
- srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
- }
- }
- }
-
- /**
- * Deletes the pseudo wire initiation.
- *
- * @param l2TunnelId the tunnel id
- * @param ingress the ingress connect point
- * @param future to perform an async operation
- * @param direction the direction: reverse of forward
- */
- private void tearDownPseudoWireInit(long l2TunnelId, ConnectPoint ingress,
- CompletableFuture<ObjectiveError> future, Direction direction) {
- log.debug("Starting tearing dowing initation of pseudowire {} for direction {}.",
- l2TunnelId, direction == FWD ? "forward" : "reverse");
- String key = generateKey(l2TunnelId, direction);
- if (!l2InitiationNextObjStore.containsKey(key)) {
- log.error("Abort delete of {} for {}: next does not exist in the store", INITIATION, key);
- if (future != null) {
- future.complete(null);
- }
- return;
- }
-
- // un-comment in case you want to delete groups used by the pw
- // however, this will break the update of pseudowires cause the L2 interface group can
- // not be deleted (it is referenced by other groups)
- /*
- NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
- ObjectiveContext context = new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.debug("Previous {} next for {} removed", INITIATION, key);
- if (future != null) {
- future.complete(null);
- }
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to remove previous {} next for {}: {}", INITIATION, key, error);
- if (future != null) {
- future.complete(error);
- }
- }
- };
- srManager.flowObjectiveService.next(ingress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
- */
-
- future.complete(null);
- l2InitiationNextObjStore.remove(key);
- }
-
- /**
- * Deletes the pseudo wire termination.
- *
- * @param l2Tunnel the tunnel
- * @param egress the egress connect point
- * @param future the async task
- * @param direction the direction of the tunnel
- */
- private void tearDownPseudoWireTerm(L2Tunnel l2Tunnel,
- ConnectPoint egress,
- CompletableFuture<ObjectiveError> future,
- Direction direction) {
- log.debug("Starting tearing down termination for pseudowire {} direction {}.",
- l2Tunnel.tunnelId(), direction == FWD ? "forward" : "reverse");
- String key = generateKey(l2Tunnel.tunnelId(), direction);
- if (!l2TerminationNextObjStore.containsKey(key)) {
- log.error("Abort delete of {} for {}: next does not exist in the store", TERMINATION, key);
- if (future != null) {
- future.complete(null);
- }
- return;
- }
- NextObjective nextObjective = l2TerminationNextObjStore.get(key).value();
- ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(),
- l2Tunnel.tunnelId(),
- egress.port(),
- nextObjective.id());
- ObjectiveContext context = new DefaultObjectiveContext((objective) ->
- log.debug("FwdObj for {} {}, " +
- "direction {} removed",
- TERMINATION,
- l2Tunnel.tunnelId(),
- direction),
- (objective, error) ->
- log.warn("Failed to remove fwdObj " +
- "for {} {}" +
- ", direction {}",
- TERMINATION,
- l2Tunnel.tunnelId(),
- error,
- direction));
- srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.remove(context));
-
- // un-comment in case you want to delete groups used by the pw
- // however, this will break the update of pseudowires cause the L2 interface group can
- // not be deleted (it is referenced by other groups)
- /*
- context = new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.debug("Previous {} next for {} removed", TERMINATION, key);
- if (future != null) {
- future.complete(null);
- }
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to remove previous {} next for {}: {}", TERMINATION, key, error);
- if (future != null) {
- future.complete(error);
- }
- }
- };
- srManager.flowObjectiveService.next(egress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
- */
-
- l2TerminationNextObjStore.remove(key);
- future.complete(null);
- }
-
- /**
- * Utilities to generate pw key.
- *
- * @param tunnelId the tunnel id
- * @param direction the direction of the pw
- * @return the key of the store
- */
- private String generateKey(long tunnelId, Direction direction) {
- return String.format("%s-%s", tunnelId, direction);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java
deleted file mode 100644
index 4738744..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/DefaultL2TunnelPolicy.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-import com.google.common.base.MoreObjects;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Implementation of the default l2 tunnel policy.
- */
-public class DefaultL2TunnelPolicy implements L2TunnelPolicy {
-
- /**
- * Id of the tunnel associated to this policy.
- */
- private long tunnelId;
- /**
- * First connect point.
- */
- private ConnectPoint cP1;
- /**
- * Second connect point.
- */
- private ConnectPoint cP2;
- /**
- * cP1 inner vlan tag. Used in QinQ packets.
- */
- private VlanId cP1InnerTag;
- /**
- * cP1 outer vlan tag.
- */
- private VlanId cP1OuterTag;
- /**
- * cP2 inner vlan tag. Used in QinQ packets.
- */
- private VlanId cP2InnerTag;
- /**
- * cP2 outer vlan tag.
- */
- private VlanId cP2OuterTag;
-
- /**
- * Creates a default l2 tunnel policy using
- * the given parameters.
- *
- * @param tunnelId the tunnel id
- * @param cP1 the first connect point
- * @param cP1InnerTag the cP1 inner tag
- * @param cP1OuterTag the cP1 outer tag
- * @param cP2 the second connect point
- * @param cP2InnerTag the cP2 inner tag
- * @param cP2OuterTag the cP2 outer tag
- */
- public DefaultL2TunnelPolicy(long tunnelId,
- ConnectPoint cP1, VlanId cP1InnerTag, VlanId cP1OuterTag,
- ConnectPoint cP2, VlanId cP2InnerTag, VlanId cP2OuterTag) {
- this.cP1 = checkNotNull(cP1);
- this.cP2 = checkNotNull(cP2);
- this.tunnelId = tunnelId;
- this.cP1InnerTag = cP1InnerTag;
- this.cP1OuterTag = cP1OuterTag;
- this.cP2InnerTag = cP2InnerTag;
- this.cP2OuterTag = cP2OuterTag;
- }
-
- /**
- * Creates a default l2 policy given the provided policy.
- * @param policy L2policy to replicate
- */
- public DefaultL2TunnelPolicy(DefaultL2TunnelPolicy policy) {
-
- this.cP1 = policy.cP1;
- this.cP2 = policy.cP2;
- this.tunnelId = policy.tunnelId;
- this.cP1InnerTag = policy.cP1InnerTag;
- this.cP1OuterTag = policy.cP1OuterTag;
- this.cP2InnerTag = policy.cP2InnerTag;
- this.cP2OuterTag = policy.cP2OuterTag;
- }
-
- @Override
- public ConnectPoint cP1() {
- return cP1;
- }
-
- @Override
- public ConnectPoint cP2() {
- return cP2;
- }
-
- @Override
- public VlanId cP1InnerTag() {
- return cP1InnerTag;
- }
-
- @Override
- public VlanId cP1OuterTag() {
- return cP1OuterTag;
- }
-
- @Override
- public VlanId cP2InnerTag() {
- return cP2InnerTag;
- }
-
- @Override
- public VlanId cP2OuterTag() {
- return cP2OuterTag;
- }
-
- @Override
- public long tunnelId() {
- return this.tunnelId;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(tunnelId,
- cP1,
- cP2,
- cP1InnerTag,
- cP1OuterTag,
- cP2InnerTag,
- cP2OuterTag
- );
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o instanceof DefaultL2TunnelPolicy) {
- DefaultL2TunnelPolicy that = (DefaultL2TunnelPolicy) o;
- if (this.tunnelId == that.tunnelId &&
- this.cP1.equals(that.cP1) &&
- this.cP2.equals(that.cP2) &&
- this.cP1InnerTag.equals(that.cP1InnerTag) &&
- this.cP1OuterTag.equals(that.cP1OuterTag) &&
- this.cP2InnerTag.equals(that.cP2InnerTag) &&
- this.cP2OuterTag.equals(that.cP2OuterTag)) {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("tunnelId", tunnelId())
- .add("cP1", cP1())
- .add("cP2", cP2())
- .add("cP1InnerTag", cP1InnerTag())
- .add("cP1OuterTag", cP1OuterTag())
- .add("cP2InnerTag", cP2InnerTag())
- .add("cP2OuterTag", cP2OuterTag())
- .toString();
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Mode.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Mode.java
deleted file mode 100644
index 685a606..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Mode.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-/**
- * Enum to identify mode of the pwaas.
- */
-public enum L2Mode {
- /**
- * Raw mode.
- */
- RAW,
- /**
- * Tagged mode. In this case the packet need
- * the sd tag.
- */
- TAGGED
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java
deleted file mode 100644
index 3e98480..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2Tunnel.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.Link;
-
-import java.util.List;
-
-public interface L2Tunnel {
-
- /**
- * Return the mode of the l2 tunnel.
- *
- * @return The pw mode.
- */
- L2Mode pwMode();
-
- /**
- * Returns the service delimiting tag.
- *
- * @return the sd tag
- */
- VlanId sdTag();
-
- /**
- * Returns the id of the tunnel.
- *
- * @return the tunnel id
- */
- long tunnelId();
-
- /**
- * Return the label of the pseudowire.
- *
- * @return the pw label.
- */
- MplsLabel pwLabel();
-
- /**
- * Returns the path used by the pseudowire.
- *
- * @return The path that is used
- */
- List<Link> pathUsed();
-
- /**
- * Returns the transport vlan used by the pseudowire.
- *
- * @return The transport vlan
- */
- VlanId transportVlan();
-
- /**
- * Returns the inter-co label used by the pseudowire.
- *
- * @return The inter CO label.
- */
- MplsLabel interCoLabel();
-
- /**
- * Sets the path that this pw uses.
- *
- * @param path The apth to use
- */
- void setPath(List<Link> path);
-
- /**
- * Set the transport vlan that this pw will use.
- *
- * @param vlan The vlan to use.
- */
- void setTransportVlan(VlanId vlan);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java
deleted file mode 100644
index 7be187a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelDescription.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-public interface L2TunnelDescription {
-
- /**
- * Returns the l2 tunnel.
- *
- * @return the l2 tunnel
- */
- L2Tunnel l2Tunnel();
-
- /**
- * Returns the l2 tunnel policy.
- *
- * @return the l2 tunnel policy.
- */
- L2TunnelPolicy l2TunnelPolicy();
-
- /**
- * Sets the l2 tunnel.
- *
- * @param tunnel the l2 tunnel to set.
- */
- void setL2Tunnel(L2Tunnel tunnel);
-
- /**
- * Sets the l2 policy.
- *
- * @param policy the policy to set.
- */
- void setL2TunnelPolicy(L2TunnelPolicy policy);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
deleted file mode 100644
index 2a003b3..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.flowobjective.NextObjective;
-
-import java.util.List;
-import java.util.Set;
-
-public interface L2TunnelHandler {
- void init();
-
- /**
- * Combines policies and tunnels to create descriptions.
- *
- * @param pending if it is true return pending to be installed pseudowires
- * from the appropriate store, else return installed pseudowires
- * @return Set of l2 tunnel descriptions.
- */
- Set<L2TunnelDescription> getL2Descriptions(boolean pending);
-
- /**
- * Returns a copy of the l2 policies that exist in the store.
- *
- * @return The l2 policies
- */
- List<L2TunnelPolicy> getL2Policies();
-
- /**
- * Returns a copy of the l2 tunnels that exist in the store.
- *
- * @return The l2 tunnels.
- */
- List<L2Tunnel> getL2Tunnels();
-
- /**
- * Returns a copy of the pending l2 policies that exist in the store.
- *
- * @return The l2 policies
- */
- List<L2TunnelPolicy> getL2PendingPolicies();
-
- /**
- * Helper function to handle the pw removal.
- * <p>
- * This method should for the mastership of the device because it is
- * used only from network configuration updates, thus we only want
- * one instance only to program each pseudowire.
- *
- * @param pwToRemove the pseudo wires to remove
- * @deprecated onos-1.12 Do not use this method.
- */
- @Deprecated
- void tearDown(Set<L2TunnelDescription> pwToRemove);
-
- /**
- * Returns a copy of the pending l2 tunnels that exist in the store.
- *
- * @return The l2 tunnels.
- */
- List<L2Tunnel> getL2PendingTunnels();
-
- /**
- * Verifies global validity for existing pseudowires, both ones in
- * the pending store and the ones installed.
- *
- * @param pwToAdd the new pseudowire to add
- * @return a Result describing the outcome
- */
- Result verifyGlobalValidity(L2TunnelDescription pwToAdd);
-
- /**
- * Check if pseudowire exists in the store.
- *
- * @param tunnelId The tunnel id to check for.
- * @param pending Check in pending store for pseudowires.
- * @return The result of the operation.
- */
- Result checkIfPwExists(long tunnelId, boolean pending);
-
- /**
- * Returns the PW init next objective store.
- *
- * @return current contents of the l2InitiationNextObjStore
- */
- ImmutableMap<String, NextObjective> getInitNext();
-
- /**
- * Returns the PW termination next objective store.
- *
- * @return current contents of the l2TerminationNextObjStore
- */
- ImmutableMap<String, NextObjective> getTermNext();
-
- /**
- * Removes given next ID from both PW init/term next obj store.
- *
- * @param nextId next ID
- */
- void removeNextId(int nextId);
-
- /**
- * Pwaas pipelines.
- */
- enum Pipeline {
- /**
- * The initiation pipeline.
- */
- INITIATION, /**
- * The termination pipeline.
- */
- TERMINATION
- }
-
- /**
- * Enum helper to carry results of various operations.
- */
- enum Result {
- /**
- * Happy ending scenario.
- */
- SUCCESS(0, "No error occurred"),
-
- /**
- * We have problems with the supplied parameters.
- */
- WRONG_PARAMETERS(1, "Wrong parameters"),
-
- /**
- * We have an internal error during the deployment
- * or removal phase.
- */
- INTERNAL_ERROR(3, "Internal error"),
-
- /**
- * No path found between the connection points.
- */
- PATH_NOT_FOUND(7, "Could not find valid path between connection points!"),
-
- /**
- * Error in global pseudowires configuration.
- */
- CONFIGURATION_ERROR(8, "Conflicting pseudowire configurations!");
-
- private final int code;
- private final String description;
-
- private String specificError;
- private int nextId;
-
- Result(int code, String description) {
- this.code = code;
- this.description = description;
- }
-
- public Result appendError(String error) {
- this.specificError = error;
- return this;
- }
-
- public String getSpecificError() {
- return specificError;
- }
-
- public String getDescription() {
- return description;
- }
-
- public int getNextId() {
- return nextId;
- }
-
- protected void setNextId(int nextId) {
- this.nextId = nextId;
- }
-
- @Override
- public String toString() {
- return code + ": " + description;
- }
- }
-
- /**
- * Enum helper for handling the direction of the pw.
- */
- enum Direction {
- /**
- * The forward direction of the pseudo wire.
- */
- FWD, /**
- * The reverse direction of the pseudo wire.
- */
- REV
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java
deleted file mode 100644
index 17be45b..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelPolicy.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-
-public interface L2TunnelPolicy {
-
- /**
- * Returns the first connect point of the policy.
- *
- * @return first connect point
- */
- ConnectPoint cP1();
-
- /**
- * Returns the second connect point of the policy.
- *
- * @return second connect point
- */
- ConnectPoint cP2();
-
- /**
- * Returns the cP1 inner vlan tag of the policy.
- *
- * @return cP1 inner vlan tag
- */
- VlanId cP1InnerTag();
-
- /**
- * Returns the cP1 outer vlan tag of the policy.
- *
- * @return cP1 outer vlan tag
- */
- VlanId cP1OuterTag();
-
- /**
- * Returns the cP2 inner vlan tag of the policy.
- *
- * @return cP2 inner vlan tag
- */
- VlanId cP2InnerTag();
-
- /**
- * Returns the cP2 outer vlan tag of the policy.
- *
- * @return cP2 outer vlan tag
- */
- VlanId cP2OuterTag();
-
- /**
- * Returns the tunnel ID of the policy.
- *
- * @return Tunnel ID
- */
- long tunnelId();
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
deleted file mode 100644
index 7cb60a6..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.pwaas;
-
-import org.onlab.osgi.ServiceNotFoundException;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.intf.InterfaceService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * Utility class with static methods that help
- * parse pseudowire related information and also
- * verify that a pseudowire combination is valid.
- */
-public final class PwaasUtil {
-
- private static final Logger log = LoggerFactory.getLogger(PwaasUtil.class);
-
- private static DeviceService deviceService;
- private static InterfaceService intfService;
-
- // Suppress ExceptionInInitializerError and simply set the value to null,
- // such that unit tests have a chance to replace the variable with mocked service
- static {
- try {
- deviceService = AbstractShellCommand.get(DeviceService.class);
- } catch (NullPointerException | ServiceNotFoundException e) {
- deviceService = null;
- }
- try {
- intfService = AbstractShellCommand.get(InterfaceService.class);
- } catch (NullPointerException | ServiceNotFoundException e) {
- intfService = null;
- }
- }
-
- static final String ERR_SERVICE_UNAVAIL = "Service %s not available";
- static final String ERR_SAME_DEV =
- "Pseudowire connection points can not reside in the same node, in pseudowire %d.";
- static final String ERR_EMPTY_INNER_WHEN_OUTER_PRESENT =
- "Inner tag should not be empty when outer tag is set for pseudowire %d for %s.";
- static final String ERR_WILDCARD_VLAN =
- "Wildcard VLAN matching not yet supported for pseudowire %d.";
- static final String ERR_DOUBLE_TO_UNTAGGED =
- "Support for double tag <-> untag is not supported for pseudowire %d.";
- static final String ERR_DOUBLE_TO_SINGLE =
- "Support for double-tag<-> single-tag is not supported for pseudowire %d.";
- static final String ERR_SINGLE_TO_UNTAGGED =
- "single-tag <-> untag is not supported for pseudowire %d.";
- static final String ERR_VLAN_TRANSLATION =
- "We do not support VLAN translation for pseudowire %d.";
- static final String ERR_DEV_NOT_FOUND =
- "Device %s does not exist for pseudowire %d.";
- static final String ERR_PORT_NOT_FOUND =
- "Port %s of device %s does not exist for pseudowire %d.";
-
- private PwaasUtil() {
-
- }
-
- /**
- * Parses a vlan as a string. Returns the VlanId if
- * provided String can be parsed as an integer or is '' / '*'
- *
- * @param vlan string as read from configuration
- * @return VlanId null if error
- */
- public static VlanId parseVlan(String vlan) {
-
- if (vlan.equals("*") || vlan.equals("Any")) {
- return VlanId.vlanId("Any");
- } else if (vlan.equals("") || vlan.equals("None")) {
- return VlanId.vlanId("None");
- } else {
- return VlanId.vlanId(vlan);
- }
- }
-
- /**
- *
- * @param mode RAW or TAGGED
- * @return the L2Mode if input is correct
- */
- public static L2Mode parseMode(String mode) {
- checkArgument(mode.equals("RAW") || mode.equals("TAGGED"),
- "Invalid pseudowire mode of operation, should be TAGGED or RAW.");
- return L2Mode.valueOf(mode);
- }
-
- /**
- *
- * @param label the mpls label of the pseudowire
- * @return the MplsLabel
- * @throws IllegalArgumentException if label is invalid
- */
- public static MplsLabel parsePWLabel(String label) {
- return MplsLabel.mplsLabel(label);
- }
-
- /**
- * Parses a string as a pseudowire id - which is an integer.
- *
- * @param id The id of pw in string form
- * @return The id of pw as an Integer or null if it failed the conversion.
- */
- public static Integer parsePwId(String id) {
- return Integer.parseInt(id);
- }
-
- /**
- * Helper method to verify if the tunnel is whether or not
- * supported.
- *
- * @param l2Tunnel the tunnel to verify
- */
- private static void verifyTunnel(L2Tunnel l2Tunnel) {
-
- // Service delimiting tag not supported yet.
- if (!l2Tunnel.sdTag().equals(VlanId.NONE)) {
- throw new IllegalArgumentException(String.format("Service delimiting tag not supported yet for " +
- "pseudowire %d.", l2Tunnel.tunnelId()));
- }
-
- // Tag mode not supported yet.
- if (l2Tunnel.pwMode() == L2Mode.TAGGED) {
- throw new IllegalArgumentException(String.format("Tagged mode not supported yet for pseudowire %d.",
- l2Tunnel.tunnelId()));
- }
-
- // Raw mode without service delimiting tag
- // is the only mode supported for now.
- }
-
- /**
- * Helper method to verify if the policy is whether or not
- * supported and if policy will be successfully instantiated in the
- * network.
- *
- * @param cP1 pseudo wire endpoint 1
- * @param cP2 pseudo wire endpoint 2
- * @param ingressInner the ingress inner tag
- * @param ingressOuter the ingress outer tag
- * @param egressInner the egress inner tag
- * @param egressOuter the egress outer tag
- * @param tunnelId tunnel ID
- */
- static void verifyPolicy(ConnectPoint cP1,
- ConnectPoint cP2,
- VlanId ingressInner,
- VlanId ingressOuter,
- VlanId egressInner,
- VlanId egressOuter,
- Long tunnelId) {
-
- if (cP1.deviceId().equals(cP2.deviceId())) {
- throw new IllegalArgumentException(String.format(ERR_SAME_DEV, tunnelId));
- }
-
- // We can have multiple tags, all of them can be NONE,
- // indicating untagged traffic, however, the outer tag can
- // not have value if the inner tag is None
- if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) {
- throw new IllegalArgumentException(String.format(ERR_EMPTY_INNER_WHEN_OUTER_PRESENT,
- tunnelId, "cp1"));
- }
-
- if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) {
- throw new IllegalArgumentException(String.format(ERR_EMPTY_INNER_WHEN_OUTER_PRESENT,
- tunnelId, "cp2"));
- }
-
- if (ingressInner.equals(VlanId.ANY) ||
- ingressOuter.equals(VlanId.ANY) ||
- egressInner.equals(VlanId.ANY) ||
- egressOuter.equals(VlanId.ANY)) {
- throw new IllegalArgumentException(String.format(ERR_WILDCARD_VLAN, tunnelId));
- }
-
- if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) &&
- (egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE)))
- || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) &&
- (!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) {
- throw new IllegalArgumentException(String.format(ERR_DOUBLE_TO_UNTAGGED, tunnelId));
- }
- if ((!ingressInner.equals(VlanId.NONE) &&
- ingressOuter.equals(VlanId.NONE) &&
- !egressOuter.equals(VlanId.NONE))
- || (egressOuter.equals(VlanId.NONE) &&
- !egressInner.equals(VlanId.NONE) &&
- !ingressOuter.equals(VlanId.NONE))) {
- throw new IllegalArgumentException(String.format(ERR_DOUBLE_TO_SINGLE, tunnelId));
- }
-
- if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE))
- || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) {
- throw new IllegalArgumentException(String.format(ERR_SINGLE_TO_UNTAGGED, tunnelId));
- }
-
- // FIXME PW VLAN translation is not supported on Dune
- // Need to explore doing that in egress table later if there is a requirement
- if (!ingressInner.equals(egressInner) || !ingressOuter.equals(egressOuter)) {
- throw new IllegalArgumentException(String.format(ERR_VLAN_TRANSLATION, tunnelId));
- }
-
- if (deviceService == null) {
- throw new IllegalStateException(String.format(ERR_SERVICE_UNAVAIL, "DeviceService"));
- }
-
- // check if cp1 and port of cp1 exist
- if (deviceService.getDevice(cP1.deviceId()) == null) {
- throw new IllegalArgumentException(String.format(ERR_DEV_NOT_FOUND, cP1.deviceId(), tunnelId));
- }
-
- if (deviceService.getPort(cP1) == null) {
- throw new IllegalArgumentException(String.format(ERR_PORT_NOT_FOUND, cP1.port(),
- cP1.deviceId(), tunnelId));
- }
-
- // check if cp2 and port of cp2 exist
- if (deviceService.getDevice(cP2.deviceId()) == null) {
- throw new IllegalArgumentException(String.format(ERR_DEV_NOT_FOUND, cP2.deviceId(), tunnelId));
- }
-
- if (deviceService.getPort(cP2) == null) {
- throw new IllegalArgumentException(String.format(ERR_PORT_NOT_FOUND, cP2.port(),
- cP2.deviceId(), tunnelId));
- }
- }
-
- /**
- * Verifies that the pseudowires will not conflict with each other.
- *
- * Further, check if vlans for connect points are already used.
- *
- * @param tunnel Tunnel for pw
- * @param policy Policy for pw
- * @param labelSet Label set used so far with this configuration
- * @param vlanSet Vlan set used with this configuration
- * @param tunnelSet Tunnel set used with this configuration
- */
- private static void verifyGlobalValidity(L2Tunnel tunnel,
- L2TunnelPolicy policy,
- Set<MplsLabel> labelSet,
- Map<ConnectPoint, Set<VlanId>> vlanSet,
- Set<Long> tunnelSet) {
-
- if (tunnelSet.contains(tunnel.tunnelId())) {
- throw new IllegalArgumentException(String.valueOf(String.format("Tunnel Id %d already used by" +
- " another pseudowire, in " +
- "pseudowire %d!",
- tunnel.tunnelId(),
- tunnel.tunnelId())));
- }
- tunnelSet.add(tunnel.tunnelId());
-
- // check if tunnel id is used again
- ConnectPoint cP1 = policy.cP1();
- ConnectPoint cP2 = policy.cP2();
-
- // insert cps to hashmap if this is the first time seen
- if (!vlanSet.containsKey(cP1)) {
- vlanSet.put(cP1, new HashSet<VlanId>());
- }
- if (!vlanSet.containsKey(cP2)) {
- vlanSet.put(cP2, new HashSet<VlanId>());
- }
-
- // if single tagged or untagged vlan is the inner
- // if double tagged vlan is the outer
- VlanId vlanToCheckCP1;
- if (policy.cP1OuterTag().equals(VlanId.NONE)) {
- vlanToCheckCP1 = policy.cP1InnerTag();
- } else {
- vlanToCheckCP1 = policy.cP1OuterTag();
- }
-
- VlanId vlanToCheckCP2;
- if (policy.cP2OuterTag().equals(VlanId.NONE)) {
- vlanToCheckCP2 = policy.cP2InnerTag();
- } else {
- vlanToCheckCP2 = policy.cP2OuterTag();
- }
-
- if (labelSet.contains(tunnel.pwLabel())) {
- throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" +
- " pseudowire, in pseudowire %d!",
- tunnel.pwLabel(), tunnel.tunnelId())));
- }
- labelSet.add(tunnel.pwLabel());
-
- if (vlanSet.get(cP1).contains(vlanToCheckCP1)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already used " +
- "by another pseudowire, in " +
- "pseudowire" +
- " %d!", vlanToCheckCP1, cP1,
- tunnel.tunnelId())));
- }
- vlanSet.get(cP1).add(vlanToCheckCP1);
-
- if (vlanSet.get(cP2).contains(vlanToCheckCP2)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already used" +
- " by another pseudowire, in" +
- " pseudowire %d!", vlanToCheckCP2,
- cP2,
- tunnel.tunnelId())));
- }
- vlanSet.get(cP2).add(vlanToCheckCP2);
-
- if (intfService == null) {
- throw new IllegalStateException(String.format(ERR_SERVICE_UNAVAIL, "InterfaceService"));
- }
-
- // check that vlans for the connect points are not used
- intfService.getInterfacesByPort(cP1).stream()
- .forEach(intf -> {
-
- // check if tagged pw affects tagged interface
- if (intf.vlanTagged().contains(vlanToCheckCP1)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already" +
- " used for this" +
- " interface, in" +
- " pseudowire %d!",
- vlanToCheckCP1, cP1,
- tunnel.tunnelId())));
- }
-
- // if vlanNative != null this interface is configured with untagged traffic also
- // check if it collides with untagged interface
- if ((intf.vlanNative() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP1 " +
- "%s already used " +
- "for this " +
- "interface, in " +
- "pseudowire " +
- "%d!", cP1,
- tunnel.tunnelId())));
- }
-
- // if vlanUntagged != null this interface is configured only with untagged traffic
- // check if it collides with untagged interface
- if ((intf.vlanUntagged() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for " +
- "cP1 %s already" +
- " used for this" +
- " interface," +
- " in pseudowire %d!",
- cP1, tunnel.tunnelId())));
- }
- });
-
- intfService.getInterfacesByPort(cP2).stream()
- .forEach(intf -> {
- if (intf.vlanTagged().contains(vlanToCheckCP2)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s " +
- " used for " +
- "this interface, " +
- "in pseudowire %d!",
- vlanToCheckCP2, cP2,
- tunnel.tunnelId())));
- }
-
- // if vlanNative != null this interface is configured with untagged traffic also
- // check if it collides with untagged interface
- if ((intf.vlanNative() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic " +
- "for cP2 %s " +
- "already " +
- "used for this" +
- " interface, " +
- "in pseudowire %d!",
- cP2, tunnel.tunnelId())));
- }
-
- // if vlanUntagged != null this interface is configured only with untagged traffic
- // check if it collides with untagged interface
- if ((intf.vlanUntagged() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
- throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s" +
- " already" +
- " used for " +
- "this interface, " +
- "in pseudowire %d!",
- cP2, tunnel.tunnelId())));
- }
- });
-
- }
-
- /**
- * Helper method to verify the integrity of the pseudo wire.
- *
- * @param l2TunnelDescription the pseudo wire description
- */
- private static void verifyPseudoWire(L2TunnelDescription l2TunnelDescription,
- Set<MplsLabel> labelSet,
- Map<ConnectPoint, Set<VlanId>> vlanset,
- Set<Long> tunnelSet) {
-
- L2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel();
- L2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy();
-
- verifyTunnel(l2Tunnel);
-
- verifyPolicy(
- l2TunnelPolicy.cP1(),
- l2TunnelPolicy.cP2(),
- l2TunnelPolicy.cP1InnerTag(),
- l2TunnelPolicy.cP1OuterTag(),
- l2TunnelPolicy.cP2InnerTag(),
- l2TunnelPolicy.cP2OuterTag(),
- l2Tunnel.tunnelId()
- );
-
- verifyGlobalValidity(l2Tunnel,
- l2TunnelPolicy,
- labelSet,
- vlanset,
- tunnelSet);
-
- }
-
- public static L2TunnelHandler.Result configurationValidity(List<L2TunnelDescription> pseudowires) {
-
- // structures to keep pw information
- // in order to see if instantiating them will create
- // problems
- Set<Long> tunIds = new HashSet<>();
- Set<MplsLabel> labelsUsed = new HashSet<>();
- Map<ConnectPoint, Set<VlanId>> vlanIds = new HashMap<>();
-
- // TODO : I know we should not use exceptions for flow control,
- // however this code was originally implemented in the configuration
- // addition where the exceptions were propagated and the configuration was
- // deemed not valid. I plan in the future to refactor the parts that
- // check the pseudowire validity.
- //
- // Ideally we would like to return a String which could also return to
- // the user issuing the rest request for adding the pseudowire.
- try {
- // check that pseudowires can be instantiated in the network
- // we try to guarantee that all the pws will work before
- // instantiating any of them
- for (L2TunnelDescription pw : pseudowires) {
- log.debug("Verifying pseudowire {}", pw);
- verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds);
- }
-
- return L2TunnelHandler.Result.SUCCESS;
- } catch (Exception e) {
- log.error("Caught exception while validating pseudowire : {}", e.getMessage());
- return L2TunnelHandler.Result.CONFIGURATION_ERROR
- .appendError(e.getMessage());
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/package-info.java
deleted file mode 100644
index 463b163..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Set of resources implementing the Pwaas.
- */
-package org.onosproject.segmentrouting.pwaas;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/DestinationSetNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/DestinationSetNextObjectiveStoreKey.java
deleted file mode 100644
index 0baa769..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/DestinationSetNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licedses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.storekey;
-
-import java.util.Objects;
-
-import org.onosproject.net.DeviceId;
-import org.onosproject.segmentrouting.grouphandler.DestinationSet;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of Destination set next objective store.
- */
-public class DestinationSetNextObjectiveStoreKey {
- private final DeviceId deviceId;
- private final DestinationSet ds;
-
- /**
- * Constructs the key of destination set next objective store.
- *
- * @param deviceId device ID
- * @param ds destination set
- */
- public DestinationSetNextObjectiveStoreKey(DeviceId deviceId,
- DestinationSet ds) {
- this.deviceId = deviceId;
- this.ds = ds;
- }
-
- /**
- * Returns the device ID in the key.
- *
- * @return device ID
- */
- public DeviceId deviceId() {
- return this.deviceId;
- }
-
- /**
- * Returns the destination set in the key.
- *
- * @return destination set
- */
- public DestinationSet destinationSet() {
- return this.ds;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof DestinationSetNextObjectiveStoreKey)) {
- return false;
- }
- DestinationSetNextObjectiveStoreKey that =
- (DestinationSetNextObjectiveStoreKey) o;
- return (Objects.equals(this.deviceId, that.deviceId) &&
- Objects.equals(this.ds, that.ds));
- }
-
- // The list of destination ids and label are used for comparison.
- @Override
- public int hashCode() {
- int result = 17;
- result = 31 * result + Objects.hashCode(this.deviceId)
- + Objects.hashCode(this.ds);
-
- return result;
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("deviceId", deviceId)
- .add("ds", ds)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/MacVlanNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/MacVlanNextObjectiveStoreKey.java
deleted file mode 100644
index 4a1ab78..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/MacVlanNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.storekey;
-
-import org.onlab.packet.VlanId;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of Device/Vlan/MacAddr to NextObjective store.
- */
-public class MacVlanNextObjectiveStoreKey {
- private final DeviceId deviceId;
- private final MacAddress macAddr;
- private final VlanId vlanId;
-
- /**
- * Constructs the key of the next objective store.
- *
- * @param deviceId device ID
- * @param macAddr mac of host
- * @param vlanId vlan of host
- */
- public MacVlanNextObjectiveStoreKey(DeviceId deviceId, MacAddress macAddr, VlanId vlanId) {
- this.deviceId = deviceId;
- this.macAddr = macAddr;
- this.vlanId = vlanId;
- }
-
- /**
- * Gets device id in this MacVlanNextObjectiveStoreKey.
- *
- * @return device id
- */
- public DeviceId deviceId() {
- return deviceId;
- }
-
- /**
- * Gets vlan information in this MacVlanNextObjectiveStoreKey.
- *
- * @return vlan information
- */
- public VlanId vlanId() {
- return vlanId;
- }
-
- /**
- * Gets mac information in this MacVlanNextObjectiveStoreKey.
- *
- * @return mac information
- */
- public MacAddress macAddr() {
- return macAddr;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof MacVlanNextObjectiveStoreKey)) {
- return false;
- }
- MacVlanNextObjectiveStoreKey that =
- (MacVlanNextObjectiveStoreKey) o;
- return (Objects.equals(this.deviceId, that.deviceId) &&
- Objects.equals(this.vlanId, that.vlanId) &&
- Objects.equals(this.macAddr, that.macAddr));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(deviceId, vlanId, macAddr);
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("deviceId", deviceId)
- .add("vlanId", vlanId)
- .add("macAddr", macAddr)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/PortNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/PortNextObjectiveStoreKey.java
deleted file mode 100644
index 1269bce..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/PortNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.storekey;
-
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of Device/Port to NextObjective store.
- *
- * Since there can be multiple next objectives to the same physical port,
- * we differentiate between them by including the treatment in the key.
- */
-public class PortNextObjectiveStoreKey {
- private final DeviceId deviceId;
- private final PortNumber portNum;
- private final TrafficTreatment treatment;
- private final TrafficSelector meta;
-
- /**
- * Constructs the key of port next objective store.
- *
- * @param deviceId device ID
- * @param portNum port number
- * @param treatment treatment that will be applied to the interface
- * @param meta optional data to pass to the driver
- */
- public PortNextObjectiveStoreKey(DeviceId deviceId, PortNumber portNum,
- TrafficTreatment treatment,
- TrafficSelector meta) {
- this.deviceId = deviceId;
- this.portNum = portNum;
- this.treatment = treatment;
- this.meta = meta;
- }
-
- /**
- * Gets device id in this PortNextObjectiveStoreKey.
- *
- * @return device id
- */
- public DeviceId deviceId() {
- return deviceId;
- }
-
- /**
- * Gets port information in this PortNextObjectiveStoreKey.
- *
- * @return port information
- */
- public PortNumber portNumber() {
- return portNum;
- }
-
- /**
- * Gets treatment information in this PortNextObjectiveStoreKey.
- *
- * @return treatment information
- */
- public TrafficTreatment treatment() {
- return treatment;
- }
-
- /**
- * Gets metadata information in this PortNextObjectiveStoreKey.
- *
- * @return meta information
- */
- public TrafficSelector meta() {
- return meta;
- }
-
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof PortNextObjectiveStoreKey)) {
- return false;
- }
- PortNextObjectiveStoreKey that =
- (PortNextObjectiveStoreKey) o;
- return (Objects.equals(this.deviceId, that.deviceId) &&
- Objects.equals(this.portNum, that.portNum) &&
- Objects.equals(this.treatment, that.treatment) &&
- Objects.equals(this.meta, that.meta));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(deviceId, portNum, treatment, meta);
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("deviceId", deviceId)
- .add("portNum", portNum)
- .add("treatment", treatment)
- .add("meta", meta)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java
deleted file mode 100644
index 55a95cd..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/VlanNextObjectiveStoreKey.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.storekey;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Key of VLAN to NextObjective store.
- */
-public class VlanNextObjectiveStoreKey {
- private final DeviceId deviceId;
- private final VlanId vlanId;
-
- /**
- * Constructs the key of VLAN next objective store.
- *
- * @param deviceId device ID
- * @param vlanId VLAN information
- */
- public VlanNextObjectiveStoreKey(DeviceId deviceId,
- VlanId vlanId) {
- this.deviceId = deviceId;
- this.vlanId = vlanId;
- }
-
- /**
- * Gets device id in this VlanNextObjectiveStoreKey.
- *
- * @return device id
- */
- public DeviceId deviceId() {
- return this.deviceId;
- }
-
- /**
- * Gets vlan information in this VlanNextObjectiveStoreKey.
- *
- * @return vlan id
- */
- public VlanId vlanId() {
- return this.vlanId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof VlanNextObjectiveStoreKey)) {
- return false;
- }
- VlanNextObjectiveStoreKey that =
- (VlanNextObjectiveStoreKey) o;
- return (Objects.equals(this.deviceId, that.deviceId) &&
- Objects.equals(this.vlanId, that.vlanId));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(deviceId, vlanId);
- }
-
- @Override
- public String toString() {
- return toStringHelper(getClass())
- .add("deviceId", deviceId)
- .add("vlanId", vlanId)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/XConnectStoreKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/XConnectStoreKey.java
deleted file mode 100644
index 0e90a22..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/XConnectStoreKey.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.storekey;
-
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Key of VLAN cross-connect next objective store.
- */
-public class XConnectStoreKey {
- private final DeviceId deviceId;
- private final VlanId vlanId;
-
- /**
- * Constructs the key of cross-connect next objective store.
- *
- * @param deviceId device ID of the VLAN cross-connection
- * @param vlanId VLAN ID of the VLAN cross-connection
- */
- public XConnectStoreKey(DeviceId deviceId, VlanId vlanId) {
- this.deviceId = deviceId;
- this.vlanId = vlanId;
- }
-
- /**
- * Returns the device ID of this key.
- *
- * @return device ID
- */
- public DeviceId deviceId() {
- return this.deviceId;
- }
-
- /**
- * Returns the VLAN ID of this key.
- *
- * @return VLAN ID
- */
- public VlanId vlanId() {
- return this.vlanId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof XConnectStoreKey)) {
- return false;
- }
- XConnectStoreKey that =
- (XConnectStoreKey) o;
- return (Objects.equals(this.deviceId, that.deviceId) &&
- Objects.equals(this.vlanId, that.vlanId));
- }
-
- // The list of neighbor ids and label are used for comparison.
- @Override
- public int hashCode() {
- return Objects.hash(deviceId, vlanId);
- }
-
- @Override
- public String toString() {
- return "Device: " + deviceId + " VlanId: " + vlanId;
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/package-info.java
deleted file mode 100644
index 44fc6a7..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/storekey/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Key data structure of various stores used by Segment Routing.
- */
-package org.onosproject.segmentrouting.storekey;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodec.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodec.java
deleted file mode 100644
index 83421bc..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodec.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.Sets;
-import org.onlab.packet.VlanId;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import org.onosproject.net.DeviceId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-
-/**
- * Codec for Xconnect.
- */
-public class XconnectCodec extends JsonCodec<XconnectDesc> {
- static final String DEVICE_ID = "deviceId";
- static final String VLAN_ID = "vlanId";
- static final String ENDPOINTS = "endpoints";
-
- private static Logger log = LoggerFactory.getLogger(XconnectCodec.class);
-
- @Override
- public ObjectNode encode(XconnectDesc desc, CodecContext context) {
- final ObjectNode result = context.mapper().createObjectNode();
- result.put(DEVICE_ID, desc.key().deviceId().toString());
- result.put(VLAN_ID, desc.key().vlanId().toShort());
- final ArrayNode portNode = result.putArray(ENDPOINTS);
- desc.endpoints().forEach(endpoint -> portNode.add(endpoint.toString()));
-
- return result;
- }
-
- @Override
- public XconnectDesc decode(ObjectNode json, CodecContext context) {
- DeviceId deviceId = DeviceId.deviceId(json.path(DEVICE_ID).asText());
- VlanId vlanId = VlanId.vlanId(json.path(VLAN_ID).asText());
-
- Set<XconnectEndpoint> endpoints = Sets.newHashSet();
- JsonNode endpointNodes = json.get(ENDPOINTS);
- if (endpointNodes != null) {
- endpointNodes.forEach(endpointNode -> endpoints.add(XconnectEndpoint.fromString(endpointNode.asText())));
- }
-
- XconnectKey key = new XconnectKey(deviceId, vlanId);
- return new XconnectDesc(key, endpoints);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectDesc.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectDesc.java
deleted file mode 100644
index a47823a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectDesc.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-import com.google.common.base.MoreObjects;
-
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Xconnect description.
- */
-public class XconnectDesc {
- private XconnectKey key;
- private Set<XconnectEndpoint> endpoints;
-
- /**
- * Constructs new Xconnect description with given device ID and VLAN ID.
- *
- * @param key Xconnect key
- * @param endpoints set of endpoints
- */
- public XconnectDesc(XconnectKey key, Set<XconnectEndpoint> endpoints) {
- this.key = key;
- this.endpoints = endpoints;
- }
-
- /**
- * Gets Xconnect key.
- *
- * @return Xconnect key
- */
- public XconnectKey key() {
- return key;
- }
-
- /**
- * Gets endpoints.
- *
- * @return set of endpoints
- */
- public Set<XconnectEndpoint> endpoints() {
- return endpoints;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof XconnectDesc)) {
- return false;
- }
- final XconnectDesc other = (XconnectDesc) obj;
- return Objects.equals(this.key, other.key) &&
- Objects.equals(this.endpoints, other.endpoints);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(key, endpoints);
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(getClass())
- .add("key", key)
- .add("endpoints", endpoints)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectEndpoint.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectEndpoint.java
deleted file mode 100644
index c7a2242..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectEndpoint.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-/**
- * Represents cross connect endpoint.
- */
-public abstract class XconnectEndpoint {
- public static final String LB_KEYWORD = "LB:";
- static final String PORT_PATTERN = "^\\d+$";
- static final String LOAD_BALANCER_PATTERN = "^" + LB_KEYWORD + "\\d+$";
-
- /**
- * Types of endpoint.
- */
- public enum Type {
- /**
- * The endpoint is specified by an port number.
- */
- PORT,
-
- /**
- * The endpoint is specified by a load balancer.
- */
- LOAD_BALANCER
- }
-
- /**
- * Type of this endpoint.
- *
- * @return type
- */
- public abstract XconnectEndpoint.Type type();
-
- /**
- * Constructs XconnectEndpoint from string.
- *
- * @param s string
- * @return XconnectEndpoint
- * @throws IllegalArgumentException if given string is in a wrong format
- */
- public static XconnectEndpoint fromString(String s) {
- if (s.matches(XconnectEndpoint.PORT_PATTERN)) {
- return XconnectPortEndpoint.fromString(s);
- } else if (s.matches(XconnectEndpoint.LOAD_BALANCER_PATTERN)) {
- return XconnectLoadBalancerEndpoint.fromString(s);
- } else {
- throw new IllegalArgumentException("Illegal endpoint format: " + s);
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectKey.java
deleted file mode 100644
index 7d433cd..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectKey.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-import com.google.common.base.MoreObjects;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Xconnect key.
- */
-public class XconnectKey {
- private DeviceId deviceId;
- private VlanId vlanId;
-
- /**
- * Constructs new XconnectKey with given device ID and VLAN ID.
- *
- * @param deviceId device ID
- * @param vlanId vlan ID
- */
- public XconnectKey(DeviceId deviceId, VlanId vlanId) {
- this.deviceId = deviceId;
- this.vlanId = vlanId;
- }
-
- /**
- * Gets device ID.
- *
- * @return device ID of the Xconnect key
- */
- public DeviceId deviceId() {
- return deviceId;
- }
-
- /**
- * Gets VLAN ID.
- *
- * @return VLAN ID of the Xconnect key
- */
- public VlanId vlanId() {
- return vlanId;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof XconnectKey)) {
- return false;
- }
- final XconnectKey other = (XconnectKey) obj;
- return Objects.equals(this.deviceId, other.deviceId) &&
- Objects.equals(this.vlanId, other.vlanId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(deviceId, vlanId);
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(getClass())
- .add("deviceId", deviceId)
- .add("vlanId", vlanId)
- .toString();
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectLoadBalancerEndpoint.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectLoadBalancerEndpoint.java
deleted file mode 100644
index 4172292f..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectLoadBalancerEndpoint.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * Represents a cross connect endpoint specified by load balancer.
- */
-public final class XconnectLoadBalancerEndpoint extends XconnectEndpoint {
- private final int key;
-
- private XconnectLoadBalancerEndpoint(int key) {
- this.key = key;
- }
-
- /**
- * Returns load balancer key.
- *
- * @return load balancer key.
- */
- public int key() {
- return key;
- }
-
- /**
- * Returns an instance of XconnectLoadBalancerEndpoint with given load balancer key.
- *
- * @param key load balancer key
- * @return an instance of XconnectLoadBalancerEndpoint
- */
- public static XconnectLoadBalancerEndpoint of(int key) {
- return new XconnectLoadBalancerEndpoint(key);
- }
-
- /**
- * Gets XconnectLoadBalancerEndpoint from string.
- *
- * @param s string
- * @return XconnectLoadBalancerEndpoint
- */
- public static XconnectLoadBalancerEndpoint fromString(String s) {
- checkArgument(s.matches(LOAD_BALANCER_PATTERN), "String {} does not match {} format", s, LOAD_BALANCER_PATTERN);
- return new XconnectLoadBalancerEndpoint(Integer.valueOf(s.replaceFirst(LB_KEYWORD, "")));
- }
-
- @Override
- public Type type() {
- return Type.LOAD_BALANCER;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(key);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj instanceof XconnectLoadBalancerEndpoint) {
- final XconnectLoadBalancerEndpoint other = (XconnectLoadBalancerEndpoint) obj;
- return Objects.equals(this.key, other.key);
- }
- return false;
- }
-
- @Override
- public String toString() {
- return LB_KEYWORD + String.valueOf(key);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectPortEndpoint.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectPortEndpoint.java
deleted file mode 100644
index f26eaf0..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectPortEndpoint.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-import org.onosproject.net.PortNumber;
-
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * Represents a cross connect endpoint specified by port number.
- */
-public final class XconnectPortEndpoint extends XconnectEndpoint {
- private final PortNumber port;
-
- private XconnectPortEndpoint(PortNumber port) {
- this.port = port;
- }
-
- /**
- * Returns port number.
- *
- * @return port number
- */
- public PortNumber port() {
- return port;
- }
-
- /**
- * Returns an instance of XconnectPortEndpoint with given port number.
- *
- * @param port port number
- * @return an instance of XconnectPortEndpoint
- */
- public static XconnectPortEndpoint of(PortNumber port) {
- return new XconnectPortEndpoint(port);
- }
-
- /**
- * Gets XconnectPortEndpoint from string.
- *
- * @param s string
- * @return XconnectPortEndpoint
- */
- public static XconnectPortEndpoint fromString(String s) {
- checkArgument(s.matches(PORT_PATTERN), "String {} does not match {} format", s, PORT_PATTERN);
- return new XconnectPortEndpoint(PortNumber.fromString(s));
- }
-
- @Override
- public XconnectEndpoint.Type type() {
- return Type.PORT;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(port);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj instanceof XconnectPortEndpoint) {
- final XconnectPortEndpoint other = (XconnectPortEndpoint) obj;
- return Objects.equals(this.port, other.port);
- }
- return false;
- }
-
- @Override
- public String toString() {
- return String.valueOf(port);
- }
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectService.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectService.java
deleted file mode 100644
index 2fe6488..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/XconnectService.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * VLAN cross connect between exactly two ports.
- */
-public interface XconnectService {
-
- /**
- * VLAN cross-connect ACL priority.
- */
- int XCONNECT_ACL_PRIORITY = 60000;
-
- /**
- * VLAN cross-connect Bridging priority.
- */
- int XCONNECT_PRIORITY = 1000;
-
- /**
- * Creates or updates Xconnect.
- *
- * @param deviceId device ID
- * @param vlanId VLAN ID
- * @param endpoints set of endpoints
- */
- void addOrUpdateXconnect(DeviceId deviceId, VlanId vlanId, Set<XconnectEndpoint> endpoints);
-
- /**
- * Deletes Xconnect.
- *
- * @param deviceId device ID
- * @param vlanId VLAN ID
- */
- void removeXonnect(DeviceId deviceId, VlanId vlanId);
-
- /**
- * Gets Xconnects.
- *
- * @return set of Xconnect descriptions
- */
- Set<XconnectDesc> getXconnects();
-
- /**
- * Check if there is Xconnect configured on given connect point.
- *
- * @param cp connect point
- * @return true if there is Xconnect configured on the connect point
- */
- boolean hasXconnect(ConnectPoint cp);
-
- /**
- * Gives xconnect VLAN of given port of a device.
- *
- * @param deviceId Device ID
- * @param port Port number
- * @return true if given VLAN vlanId is XConnect VLAN on device deviceId.
- */
- List<VlanId> getXconnectVlans(DeviceId deviceId, PortNumber port);
-
- /**
- * Checks given VLAN is XConnect VLAN in given device.
- *
- * @param deviceId Device ID
- * @param vlanId VLAN ID
- * @return true if given VLAN vlanId is XConnect VLAN on device deviceId.
- */
- boolean isXconnectVlan(DeviceId deviceId, VlanId vlanId);
-
- /**
- * Returns the Xconnect next objective store.
- *
- * @return current contents of the xconnectNextObjStore
- */
- ImmutableMap<XconnectKey, Integer> getNext();
-
- /**
- * Removes given next ID from Xconnect next objective store.
- *
- * @param nextId next ID
- */
- void removeNextId(int nextId);
-
- /**
- * Returns Xconnect next objective ID associated with group device + vlan.
- *
- * @param deviceId - Device ID
- * @param vlanId - VLAN ID
- * @return Current associated group ID
- */
- int getNextId(DeviceId deviceId, VlanId vlanId);
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/package-info.java
deleted file mode 100644
index 56df706..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/api/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * VLAN cross connect API.
- */
-package org.onosproject.segmentrouting.xconnect.api;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/XconnectManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/XconnectManager.java
deleted file mode 100644
index fecba5a..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/XconnectManager.java
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.LeadershipService;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.codec.CodecService;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerEvent;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerId;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerListener;
-import org.onosproject.portloadbalancer.api.PortLoadBalancerService;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.Port;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.DefaultNextObjective;
-import org.onosproject.net.flowobjective.DefaultNextTreatment;
-import org.onosproject.net.flowobjective.DefaultObjectiveContext;
-import org.onosproject.net.flowobjective.FilteringObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.IdNextTreatment;
-import org.onosproject.net.flowobjective.NextObjective;
-import org.onosproject.net.flowobjective.NextTreatment;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveContext;
-import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.segmentrouting.storekey.VlanNextObjectiveStoreKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectCodec;
-import org.onosproject.segmentrouting.xconnect.api.XconnectDesc;
-import org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectKey;
-import org.onosproject.segmentrouting.xconnect.api.XconnectLoadBalancerEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectPortEndpoint;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
-import org.onosproject.store.service.MapEvent;
-import org.onosproject.store.service.MapEventListener;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.Versioned;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.Iterator;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-
-@Component(immediate = true, service = XconnectService.class)
-public class XconnectManager implements XconnectService {
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private CodecService codecService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private StorageService storageService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public NetworkConfigService netCfgService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public DeviceService deviceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public FlowObjectiveService flowObjectiveService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private LeadershipService leadershipService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private ClusterService clusterService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public MastershipService mastershipService;
-
- @Reference(cardinality = ReferenceCardinality.OPTIONAL)
- public SegmentRoutingService srService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public InterfaceService interfaceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- HostService hostService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- private PortLoadBalancerService portLoadBalancerService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public NetworkConfigRegistry cfgService;
-
- private static final String APP_NAME = "org.onosproject.xconnect";
- private static final String ERROR_NOT_LEADER = "Not leader controller";
- private static final String ERROR_NEXT_OBJ_BUILDER = "Unable to construct next objective builder";
- private static final String ERROR_NEXT_ID = "Unable to get next id";
- private static final String ERROR_NOT_EDGE_ROUTER = "Device is not Edge Router";
- private static final String ERROR_PORT_NOT_RANGE = "Ports for the device are not in the range";
-
- private static Logger log = LoggerFactory.getLogger(XconnectManager.class);
-
- private ApplicationId appId;
- private ConsistentMap<XconnectKey, Set<XconnectEndpoint>> xconnectStore;
- private ConsistentMap<XconnectKey, Integer> xconnectNextObjStore;
-
- private ConsistentMap<VlanNextObjectiveStoreKey, Integer> xconnectMulticastNextStore;
- private ConsistentMap<VlanNextObjectiveStoreKey, List<PortNumber>> xconnectMulticastPortsStore;
-
- private final MapEventListener<XconnectKey, Set<XconnectEndpoint>> xconnectListener = new XconnectMapListener();
- private ExecutorService xConnectExecutor;
-
- private final DeviceListener deviceListener = new InternalDeviceListener();
- private ExecutorService deviceEventExecutor;
-
- private final HostListener hostListener = new InternalHostListener();
- private ExecutorService hostEventExecutor;
-
- // Wait time for the cache
- private static final int WAIT_TIME_MS = 15000;
- //The cache is implemented as buffer for waiting the installation of PortLoadBalancer when present
- private Cache<PortLoadBalancerId, XconnectKey> portLoadBalancerCache;
- // Executor for the cache
- private ScheduledExecutorService portLoadBalancerExecutor;
- // We need to listen for some events to properly installed the xconnect with portloadbalancer
- private final PortLoadBalancerListener portLoadBalancerListener = new InternalPortLoadBalancerListener();
-
- @Activate
- void activate() {
- appId = coreService.registerApplication(APP_NAME);
- codecService.registerCodec(XconnectDesc.class, new XconnectCodec());
-
- KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
- .register(KryoNamespaces.API)
- .register(XconnectManager.class)
- .register(XconnectKey.class)
- .register(XconnectEndpoint.class)
- .register(XconnectPortEndpoint.class)
- .register(XconnectLoadBalancerEndpoint.class)
- .register(VlanNextObjectiveStoreKey.class);
-
- xconnectStore = storageService.<XconnectKey, Set<XconnectEndpoint>>consistentMapBuilder()
- .withName("onos-sr-xconnect")
- .withRelaxedReadConsistency()
- .withSerializer(Serializer.using(serializer.build()))
- .build();
- xConnectExecutor = Executors.newSingleThreadScheduledExecutor(
- groupedThreads("sr-xconnect-event", "%d", log));
- xconnectStore.addListener(xconnectListener, xConnectExecutor);
-
- xconnectNextObjStore = storageService.<XconnectKey, Integer>consistentMapBuilder()
- .withName("onos-sr-xconnect-next")
- .withRelaxedReadConsistency()
- .withSerializer(Serializer.using(serializer.build()))
- .build();
-
- xconnectMulticastNextStore = storageService.<VlanNextObjectiveStoreKey, Integer>consistentMapBuilder()
- .withName("onos-sr-xconnect-l2multicast-next")
- .withSerializer(Serializer.using(serializer.build()))
- .build();
- xconnectMulticastPortsStore = storageService.<VlanNextObjectiveStoreKey, List<PortNumber>>consistentMapBuilder()
- .withName("onos-sr-xconnect-l2multicast-ports")
- .withSerializer(Serializer.using(serializer.build()))
- .build();
-
- deviceEventExecutor = Executors.newSingleThreadScheduledExecutor(
- groupedThreads("sr-xconnect-device-event", "%d", log));
- deviceService.addListener(deviceListener);
-
- hostEventExecutor = Executors.newSingleThreadExecutor(
- groupedThreads("sr-xconnect-host-event", "%d", log));
- hostService.addListener(hostListener);
-
- portLoadBalancerCache = CacheBuilder.newBuilder()
- .expireAfterWrite(WAIT_TIME_MS, TimeUnit.MILLISECONDS)
- .removalListener((RemovalNotification<PortLoadBalancerId, XconnectKey> notification) ->
- log.debug("PortLoadBalancer cache removal event. portLoadBalancerId={}, xConnectKey={}",
- notification.getKey(), notification.getValue())).build();
- portLoadBalancerExecutor = newScheduledThreadPool(1,
- groupedThreads("portLoadBalancerCacheWorker", "-%d", log));
- // Let's schedule the cleanup of the cache
- portLoadBalancerExecutor.scheduleAtFixedRate(portLoadBalancerCache::cleanUp, 0,
- WAIT_TIME_MS, TimeUnit.MILLISECONDS);
- portLoadBalancerService.addListener(portLoadBalancerListener);
-
- log.info("Started");
- }
-
- @Deactivate
- void deactivate() {
- xconnectStore.removeListener(xconnectListener);
- deviceService.removeListener(deviceListener);
- hostService.removeListener(hostListener);
- portLoadBalancerService.removeListener(portLoadBalancerListener);
- codecService.unregisterCodec(XconnectDesc.class);
-
- deviceEventExecutor.shutdown();
- hostEventExecutor.shutdown();
- xConnectExecutor.shutdown();
- portLoadBalancerExecutor.shutdown();
-
- log.info("Stopped");
- }
-
- @Override
- public void addOrUpdateXconnect(DeviceId deviceId, VlanId vlanId, Set<XconnectEndpoint> endpoints) {
- log.info("Adding or updating xconnect. deviceId={}, vlanId={}, endpoints={}",
- deviceId, vlanId, endpoints);
- SegmentRoutingDeviceConfig config = cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
-
- List<PortNumber> devicePorts = deviceService.getPorts(deviceId).stream()
- .map(Port::number)
- .collect(Collectors.toList());
- if (!config.isEdgeRouter()) {
- throw new IllegalArgumentException(ERROR_NOT_EDGE_ROUTER);
- } else {
- Iterator<XconnectEndpoint> itr = endpoints.iterator();
- while (itr.hasNext()) {
- XconnectEndpoint ep = itr.next();
- // Note: we don't validate an endpoint with LOAD_BALANCER type
- if (ep.type() != XconnectEndpoint.Type.PORT) {
- continue;
- }
- if (!devicePorts.contains(((XconnectPortEndpoint) ep).port())) {
- throw new IllegalArgumentException(ERROR_PORT_NOT_RANGE);
- }
- }
- }
- final XconnectKey key = new XconnectKey(deviceId, vlanId);
- xconnectStore.put(key, endpoints);
- }
-
- @Override
- public void removeXonnect(DeviceId deviceId, VlanId vlanId) {
- log.info("Removing xconnect. deviceId={}, vlanId={}",
- deviceId, vlanId);
- final XconnectKey key = new XconnectKey(deviceId, vlanId);
- xconnectStore.remove(key);
-
- // Cleanup multicasting support, if any.
- srService.getPairDeviceId(deviceId).ifPresent(pairDeviceId ->
- cleanupL2MulticastRule(pairDeviceId, srService.getPairLocalPort(pairDeviceId).get(), vlanId, true)
- );
-
- }
-
- @Override
- public Set<XconnectDesc> getXconnects() {
- return xconnectStore.asJavaMap().entrySet().stream()
- .map(e -> new XconnectDesc(e.getKey(), e.getValue()))
- .collect(Collectors.toSet());
- }
-
- @Override
- public boolean hasXconnect(ConnectPoint cp) {
- return getXconnects().stream().anyMatch(desc ->
- desc.key().deviceId().equals(cp.deviceId()) && desc.endpoints().stream().anyMatch(ep ->
- ep.type() == XconnectEndpoint.Type.PORT && ((XconnectPortEndpoint) ep).port().equals(cp.port())
- )
- );
- }
-
- @Override
- public List<VlanId> getXconnectVlans(DeviceId deviceId, PortNumber port) {
- return getXconnects().stream()
- .filter(desc -> desc.key().deviceId().equals(deviceId) && desc.endpoints().stream().anyMatch(ep ->
- ep.type() == XconnectEndpoint.Type.PORT && ((XconnectPortEndpoint) ep).port().equals(port)))
- .map(XconnectDesc::key)
- .map(XconnectKey::vlanId)
- .collect(Collectors.toList());
- }
-
- @Override
- public boolean isXconnectVlan(DeviceId deviceId, VlanId vlanId) {
- XconnectKey key = new XconnectKey(deviceId, vlanId);
- return Versioned.valueOrNull(xconnectStore.get(key)) != null;
- }
-
- @Override
- public ImmutableMap<XconnectKey, Integer> getNext() {
- if (xconnectNextObjStore != null) {
- return ImmutableMap.copyOf(xconnectNextObjStore.asJavaMap());
- } else {
- return ImmutableMap.of();
- }
- }
-
- @Override
- public int getNextId(DeviceId deviceId, VlanId vlanId) {
- return Versioned.valueOrElse(xconnectNextObjStore.get(new XconnectKey(deviceId, vlanId)), -1);
- }
-
- @Override
- public void removeNextId(int nextId) {
- xconnectNextObjStore.entrySet().forEach(e -> {
- if (e.getValue().value() == nextId) {
- xconnectNextObjStore.remove(e.getKey());
- }
- });
- }
-
- private class XconnectMapListener implements MapEventListener<XconnectKey, Set<XconnectEndpoint>> {
- @Override
- public void event(MapEvent<XconnectKey, Set<XconnectEndpoint>> event) {
- XconnectKey key = event.key();
- Set<XconnectEndpoint> ports = Versioned.valueOrNull(event.newValue());
- Set<XconnectEndpoint> oldPorts = Versioned.valueOrNull(event.oldValue());
-
- switch (event.type()) {
- case INSERT:
- populateXConnect(key, ports);
- break;
- case UPDATE:
- updateXConnect(key, oldPorts, ports);
- break;
- case REMOVE:
- revokeXConnect(key, oldPorts);
- break;
- default:
- break;
- }
- }
- }
-
- private class InternalDeviceListener implements DeviceListener {
- // Offload the execution to an executor and then process the event
- // if this instance is the leader of the device
- @Override
- public void event(DeviceEvent event) {
- deviceEventExecutor.execute(() -> {
- DeviceId deviceId = event.subject().id();
- // Just skip if we are not the leader
- if (!isLocalLeader(deviceId)) {
- log.debug("Not the leader of {}. Skip event {}", deviceId, event);
- return;
- }
- // Populate or revoke according to the device availability
- if (deviceService.isAvailable(deviceId)) {
- init(deviceId);
- } else {
- cleanup(deviceId);
- }
- });
- }
- // We want to manage only a subset of events and if we are the leader
- @Override
- public boolean isRelevant(DeviceEvent event) {
- return event.type() == DeviceEvent.Type.DEVICE_ADDED ||
- event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
- event.type() == DeviceEvent.Type.DEVICE_UPDATED;
- }
- }
-
- private class InternalHostListener implements HostListener {
- @Override
- public void event(HostEvent event) {
- hostEventExecutor.execute(() -> {
-
- switch (event.type()) {
- case HOST_ADDED:
- case HOST_REMOVED:
- case HOST_UPDATED:
- log.trace("Unhandled host event type: {} received. Ignoring.", event.type());
- break;
- case HOST_MOVED:
- log.trace("Processing host event {}", event);
-
- Host host = event.subject();
- Set<HostLocation> prevLocations = event.prevSubject().locations();
- Set<HostLocation> newLocations = host.locations();
-
- // Dual-home host port failure
- // For each old location, in failed and paired devices update L2 vlan groups
- Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
-
- Optional<DeviceId> pairDeviceId = srService.getPairDeviceId(prevLocation.deviceId());
- Optional<PortNumber> pairLocalPort = srService.getPairLocalPort(prevLocation.deviceId());
-
- if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
- .anyMatch(location -> location.deviceId().equals(pairDeviceId.get())) &&
- hasXconnect(new ConnectPoint(prevLocation.deviceId(), prevLocation.port()))) {
-
- List<VlanId> xconnectVlans = getXconnectVlans(prevLocation.deviceId(),
- prevLocation.port());
- xconnectVlans.forEach(xconnectVlan -> {
- // Add single-home host into L2 multicast group at paired device side.
- // Also append ACL rule to forward traffic from paired port to L2 multicast group.
- newLocations.stream()
- .filter(location -> location.deviceId().equals(pairDeviceId.get()))
- .forEach(location -> populateL2Multicast(location.deviceId(),
- srService.getPairLocalPort(
- location.deviceId()).get(),
- xconnectVlan,
- Collections.singletonList(
- location.port())));
- // Ensure pair-port attached to xconnect vlan flooding group
- // at dual home failed device.
- updateL2Flooding(prevLocation.deviceId(), pairLocalPort.get(), xconnectVlan, true);
- });
- }
- });
-
- // Dual-home host port restoration
- // For each new location, reverse xconnect loop prevention groups.
- Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
- final Optional<DeviceId> pairDeviceId = srService.getPairDeviceId(newLocation.deviceId());
- Optional<PortNumber> pairLocalPort = srService.getPairLocalPort(newLocation.deviceId());
- if (pairDeviceId.isPresent() && pairLocalPort.isPresent() &&
- hasXconnect((new ConnectPoint(newLocation.deviceId(), newLocation.port())))) {
-
- List<VlanId> xconnectVlans = getXconnectVlans(newLocation.deviceId(),
- newLocation.port());
- xconnectVlans.forEach(xconnectVlan -> {
- // Remove recovered dual homed port from vlan L2 multicast group
- prevLocations.stream()
- .filter(prevLocation -> prevLocation.deviceId().equals(pairDeviceId.get()))
- .forEach(prevLocation -> revokeL2Multicast(
- prevLocation.deviceId(),
- xconnectVlan,
- Collections.singletonList(newLocation.port()))
- );
-
- // Remove pair-port from vlan's flooding group at dual home
- // restored device, if needed.
- if (!hasAccessPortInMulticastGroup(new VlanNextObjectiveStoreKey(
- newLocation.deviceId(), xconnectVlan), pairLocalPort.get())) {
- updateL2Flooding(newLocation.deviceId(),
- pairLocalPort.get(),
- xconnectVlan,
- false);
-
- // Clean L2 multicast group at pair-device; also update store.
- cleanupL2MulticastRule(pairDeviceId.get(),
- srService.getPairLocalPort(pairDeviceId.get()).get(),
- xconnectVlan,
- false);
- }
- });
- }
- });
- break;
-
- default:
- log.warn("Unsupported host event type: {} received. Ignoring.", event.type());
- break;
- }
- });
- }
- }
-
- private void init(DeviceId deviceId) {
- getXconnects().stream()
- .filter(desc -> desc.key().deviceId().equals(deviceId))
- .forEach(desc -> populateXConnect(desc.key(), desc.endpoints()));
- }
-
- private void cleanup(DeviceId deviceId) {
- xconnectNextObjStore.entrySet().stream()
- .filter(entry -> entry.getKey().deviceId().equals(deviceId))
- .forEach(entry -> xconnectNextObjStore.remove(entry.getKey()));
- log.debug("{} is removed from xConnectNextObjStore", deviceId);
- }
-
- /**
- * Populates XConnect groups and flows for given key.
- *
- * @param key XConnect key
- * @param endpoints a set of endpoints to be cross-connected
- */
- private void populateXConnect(XconnectKey key, Set<XconnectEndpoint> endpoints) {
- if (!isLocalLeader(key.deviceId())) {
- log.debug("Abort populating XConnect {}: {}", key, ERROR_NOT_LEADER);
- return;
- }
-
- int nextId = populateNext(key, endpoints);
- if (nextId == -1) {
- log.warn("Fail to populateXConnect {}: {}", key, ERROR_NEXT_ID);
- return;
- }
- populateFilter(key, endpoints);
- populateFwd(key, nextId);
- populateAcl(key);
- }
-
- /**
- * Populates filtering objectives for given XConnect.
- *
- * @param key XConnect store key
- * @param endpoints XConnect endpoints
- */
- private void populateFilter(XconnectKey key, Set<XconnectEndpoint> endpoints) {
- // FIXME Improve the logic
- // If port load balancer is not involved, use filtered port. Otherwise, use unfiltered port.
- // The purpose is to make sure existing XConnect logic can still work on a configured port.
- boolean filtered = endpoints.stream()
- .map(ep -> getNextTreatment(key.deviceId(), ep, false))
- .allMatch(t -> t.type().equals(NextTreatment.Type.TREATMENT));
-
- endpoints.stream()
- .map(ep -> getPhysicalPorts(key.deviceId(), ep))
- .flatMap(Set::stream).forEach(port -> {
- FilteringObjective.Builder filtObjBuilder = filterObjBuilder(key, port, filtered);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("XConnect FilterObj for {} on port {} populated",
- key, port),
- (objective, error) ->
- log.warn("Failed to populate XConnect FilterObj for {} on port {}: {}",
- key, port, error));
- flowObjectiveService.filter(key.deviceId(), filtObjBuilder.add(context));
- });
- }
-
- /**
- * Populates next objectives for given XConnect.
- *
- * @param key XConnect store key
- * @param endpoints XConnect endpoints
- * @return next id
- */
- private int populateNext(XconnectKey key, Set<XconnectEndpoint> endpoints) {
- int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
- if (nextId != -1) {
- log.debug("NextObj for {} found, id={}", key, nextId);
- return nextId;
- } else {
- NextObjective.Builder nextObjBuilder = nextObjBuilder(key, endpoints);
- if (nextObjBuilder == null) {
- log.warn("Fail to populate {}: {}", key, ERROR_NEXT_OBJ_BUILDER);
- return -1;
- }
- ObjectiveContext nextContext = new DefaultObjectiveContext(
- // To serialize this with kryo
- (Serializable & Consumer<Objective>) (objective) ->
- log.debug("XConnect NextObj for {} added", key),
- (Serializable & BiConsumer<Objective, ObjectiveError>) (objective, error) -> {
- log.warn("Failed to add XConnect NextObj for {}: {}", key, error);
- srService.invalidateNextObj(objective.id());
- });
- NextObjective nextObj = nextObjBuilder.add(nextContext);
- flowObjectiveService.next(key.deviceId(), nextObj);
- xconnectNextObjStore.put(key, nextObj.id());
- log.debug("NextObj for {} not found. Creating new NextObj with id={}", key, nextObj.id());
- return nextObj.id();
- }
- }
-
- /**
- * Populates bridging forwarding objectives for given XConnect.
- *
- * @param key XConnect store key
- * @param nextId next objective id
- */
- private void populateFwd(XconnectKey key, int nextId) {
- ForwardingObjective.Builder fwdObjBuilder = fwdObjBuilder(key, nextId);
- ObjectiveContext fwdContext = new DefaultObjectiveContext(
- (objective) -> log.debug("XConnect FwdObj for {} populated", key),
- (objective, error) ->
- log.warn("Failed to populate XConnect FwdObj for {}: {}", key, error));
- flowObjectiveService.forward(key.deviceId(), fwdObjBuilder.add(fwdContext));
- }
-
- /**
- * Populates ACL forwarding objectives for given XConnect.
- *
- * @param key XConnect store key
- */
- private void populateAcl(XconnectKey key) {
- ForwardingObjective.Builder aclObjBuilder = aclObjBuilder(key.vlanId());
- ObjectiveContext aclContext = new DefaultObjectiveContext(
- (objective) -> log.debug("XConnect AclObj for {} populated", key),
- (objective, error) ->
- log.warn("Failed to populate XConnect AclObj for {}: {}", key, error));
- flowObjectiveService.forward(key.deviceId(), aclObjBuilder.add(aclContext));
- }
-
- /**
- * Revokes XConnect groups and flows for given key.
- *
- * @param key XConnect key
- * @param endpoints XConnect endpoints
- */
- private void revokeXConnect(XconnectKey key, Set<XconnectEndpoint> endpoints) {
- if (!isLocalLeader(key.deviceId())) {
- log.debug("Abort revoking XConnect {}: {}", key, ERROR_NOT_LEADER);
- return;
- }
-
- revokeFilter(key, endpoints);
- int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
- if (nextId != -1) {
- revokeFwd(key, nextId, null);
- revokeNext(key, endpoints, nextId, null);
- } else {
- log.warn("NextObj for {} does not exist in the store.", key);
- }
- revokeFilter(key, endpoints);
- revokeAcl(key);
- }
-
- /**
- * Revokes filtering objectives for given XConnect.
- *
- * @param key XConnect store key
- * @param endpoints XConnect endpoints
- */
- private void revokeFilter(XconnectKey key, Set<XconnectEndpoint> endpoints) {
- // FIXME Improve the logic
- // If port load balancer is not involved, use filtered port. Otherwise, use unfiltered port.
- // The purpose is to make sure existing XConnect logic can still work on a configured port.
- boolean filtered = endpoints.stream()
- .map(ep -> getNextTreatment(key.deviceId(), ep, false))
- .allMatch(t -> t.type().equals(NextTreatment.Type.TREATMENT));
-
- endpoints.stream()
- .map(ep -> getPhysicalPorts(key.deviceId(), ep)).
- flatMap(Set::stream).forEach(port -> {
- FilteringObjective.Builder filtObjBuilder = filterObjBuilder(key, port, filtered);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("XConnect FilterObj for {} on port {} revoked",
- key, port),
- (objective, error) ->
- log.warn("Failed to revoke XConnect FilterObj for {} on port {}: {}",
- key, port, error));
- flowObjectiveService.filter(key.deviceId(), filtObjBuilder.remove(context));
- });
- }
-
- /**
- * Revokes next objectives for given XConnect.
- *
- * @param key XConnect store key
- * @param endpoints XConnect endpoints
- * @param nextId next objective id
- * @param nextFuture completable future for this next objective operation
- */
- private void revokeNext(XconnectKey key, Set<XconnectEndpoint> endpoints, int nextId,
- CompletableFuture<ObjectiveError> nextFuture) {
- ObjectiveContext context = new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.debug("Previous NextObj for {} removed", key);
- if (nextFuture != null) {
- nextFuture.complete(null);
- }
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to remove previous NextObj for {}: {}", key, error);
- if (nextFuture != null) {
- nextFuture.complete(error);
- }
- srService.invalidateNextObj(objective.id());
- }
- };
-
- NextObjective.Builder nextObjBuilder = nextObjBuilder(key, endpoints, nextId);
- if (nextObjBuilder == null) {
- log.warn("Fail to revokeNext {}: {}", key, ERROR_NEXT_OBJ_BUILDER);
- return;
- }
- // Release the port load balancer if present
- endpoints.stream()
- .filter(endpoint -> endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER)
- .forEach(endpoint -> {
- String portLoadBalancerKey = String.valueOf(((XconnectLoadBalancerEndpoint) endpoint).key());
- portLoadBalancerService.release(new PortLoadBalancerId(key.deviceId(),
- Integer.parseInt(portLoadBalancerKey)), appId);
- });
- flowObjectiveService.next(key.deviceId(), nextObjBuilder.remove(context));
- xconnectNextObjStore.remove(key);
- }
-
- /**
- * Revokes bridging forwarding objectives for given XConnect.
- *
- * @param key XConnect store key
- * @param nextId next objective id
- * @param fwdFuture completable future for this forwarding objective operation
- */
- private void revokeFwd(XconnectKey key, int nextId, CompletableFuture<ObjectiveError> fwdFuture) {
- ForwardingObjective.Builder fwdObjBuilder = fwdObjBuilder(key, nextId);
- ObjectiveContext context = new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.debug("Previous FwdObj for {} removed", key);
- if (fwdFuture != null) {
- fwdFuture.complete(null);
- }
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to remove previous FwdObj for {}: {}", key, error);
- if (fwdFuture != null) {
- fwdFuture.complete(error);
- }
- }
- };
- flowObjectiveService.forward(key.deviceId(), fwdObjBuilder.remove(context));
- }
-
- /**
- * Revokes ACL forwarding objectives for given XConnect.
- *
- * @param key XConnect store key
- */
- private void revokeAcl(XconnectKey key) {
- ForwardingObjective.Builder aclObjBuilder = aclObjBuilder(key.vlanId());
- ObjectiveContext aclContext = new DefaultObjectiveContext(
- (objective) -> log.debug("XConnect AclObj for {} populated", key),
- (objective, error) ->
- log.warn("Failed to populate XConnect AclObj for {}: {}", key, error));
- flowObjectiveService.forward(key.deviceId(), aclObjBuilder.remove(aclContext));
- }
-
- /**
- * Updates XConnect groups and flows for given key.
- *
- * @param key XConnect key
- * @param prevEndpoints previous XConnect endpoints
- * @param endpoints new XConnect endpoints
- */
- private void updateXConnect(XconnectKey key, Set<XconnectEndpoint> prevEndpoints,
- Set<XconnectEndpoint> endpoints) {
- if (!isLocalLeader(key.deviceId())) {
- log.debug("Abort updating XConnect {}: {}", key, ERROR_NOT_LEADER);
- return;
- }
- // NOTE: ACL flow doesn't include port information. No need to update it.
- // Pair port is built-in and thus not going to change. No need to update it.
-
- // remove old filter
- prevEndpoints.stream().filter(prevEndpoint -> !endpoints.contains(prevEndpoint)).forEach(prevEndpoint ->
- revokeFilter(key, ImmutableSet.of(prevEndpoint)));
- // install new filter
- endpoints.stream().filter(endpoint -> !prevEndpoints.contains(endpoint)).forEach(endpoint ->
- populateFilter(key, ImmutableSet.of(endpoint)));
-
- CompletableFuture<ObjectiveError> fwdFuture = new CompletableFuture<>();
- CompletableFuture<ObjectiveError> nextFuture = new CompletableFuture<>();
-
- int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
- if (nextId != -1) {
- revokeFwd(key, nextId, fwdFuture);
-
- fwdFuture.thenAcceptAsync(fwdStatus -> {
- if (fwdStatus == null) {
- log.debug("Fwd removed. Now remove group {}", key);
- revokeNext(key, prevEndpoints, nextId, nextFuture);
- }
- });
-
- nextFuture.thenAcceptAsync(nextStatus -> {
- if (nextStatus == null) {
- log.debug("Installing new group and flow for {}", key);
- int newNextId = populateNext(key, endpoints);
- if (newNextId == -1) {
- log.warn("Fail to updateXConnect {}: {}", key, ERROR_NEXT_ID);
- return;
- }
- populateFwd(key, newNextId);
- }
- });
- } else {
- log.warn("NextObj for {} does not exist in the store.", key);
- }
- }
-
- /**
- * Creates a next objective builder for XConnect with given nextId.
- *
- * @param key XConnect key
- * @param endpoints XConnect endpoints
- * @param nextId next objective id
- * @return next objective builder
- */
- private NextObjective.Builder nextObjBuilder(XconnectKey key, Set<XconnectEndpoint> endpoints, int nextId) {
- TrafficSelector metadata =
- DefaultTrafficSelector.builder().matchVlanId(key.vlanId()).build();
- NextObjective.Builder nextObjBuilder = DefaultNextObjective
- .builder().withId(nextId)
- .withType(NextObjective.Type.BROADCAST).fromApp(appId)
- .withMeta(metadata);
-
- for (XconnectEndpoint endpoint : endpoints) {
- NextTreatment nextTreatment = getNextTreatment(key.deviceId(), endpoint, true);
- if (nextTreatment == null) {
- // If a PortLoadBalancer is used in the XConnect - putting on hold
- if (endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER) {
- log.warn("Unable to create nextObj. PortLoadBalancer not ready");
- String portLoadBalancerKey = String.valueOf(((XconnectLoadBalancerEndpoint) endpoint).key());
- portLoadBalancerCache.asMap().putIfAbsent(new PortLoadBalancerId(key.deviceId(),
- Integer.parseInt(portLoadBalancerKey)), key);
- } else {
- log.warn("Unable to create nextObj. Null NextTreatment");
- }
- return null;
- }
- nextObjBuilder.addTreatment(nextTreatment);
- }
-
- return nextObjBuilder;
- }
-
- /**
- * Creates a next objective builder for XConnect.
- *
- * @param key XConnect key
- * @param endpoints Xconnect endpoints
- * @return next objective builder
- */
- private NextObjective.Builder nextObjBuilder(XconnectKey key, Set<XconnectEndpoint> endpoints) {
- int nextId = flowObjectiveService.allocateNextId();
- return nextObjBuilder(key, endpoints, nextId);
- }
-
-
- /**
- * Creates a bridging forwarding objective builder for XConnect.
- *
- * @param key XConnect key
- * @param nextId next ID of the broadcast group for this XConnect key
- * @return forwarding objective builder
- */
- private ForwardingObjective.Builder fwdObjBuilder(XconnectKey key, int nextId) {
- /*
- * Driver should treat objectives with MacAddress.NONE and !VlanId.NONE
- * as the VLAN cross-connect broadcast rules
- */
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- sbuilder.matchVlanId(key.vlanId());
- sbuilder.matchEthDst(MacAddress.NONE);
-
- ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
- fob.withFlag(ForwardingObjective.Flag.SPECIFIC)
- .withSelector(sbuilder.build())
- .nextStep(nextId)
- .withPriority(XCONNECT_PRIORITY)
- .fromApp(appId)
- .makePermanent();
- return fob;
- }
-
- /**
- * Creates an ACL forwarding objective builder for XConnect.
- *
- * @param vlanId cross connect VLAN id
- * @return forwarding objective builder
- */
- private ForwardingObjective.Builder aclObjBuilder(VlanId vlanId) {
- TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
- sbuilder.matchVlanId(vlanId);
-
- TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
-
- ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
- fob.withFlag(ForwardingObjective.Flag.VERSATILE)
- .withSelector(sbuilder.build())
- .withTreatment(tbuilder.build())
- .withPriority(XCONNECT_ACL_PRIORITY)
- .fromApp(appId)
- .makePermanent();
- return fob;
- }
-
- /**
- * Creates a filtering objective builder for XConnect.
- *
- * @param key XConnect key
- * @param port XConnect ports
- * @param filtered true if this is a filtered port
- * @return next objective builder
- */
- private FilteringObjective.Builder filterObjBuilder(XconnectKey key, PortNumber port, boolean filtered) {
- FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
- fob.withKey(Criteria.matchInPort(port))
- .addCondition(Criteria.matchEthDst(MacAddress.NONE))
- .withPriority(XCONNECT_PRIORITY);
- if (filtered) {
- fob.addCondition(Criteria.matchVlanId(key.vlanId()));
- } else {
- fob.addCondition(Criteria.matchVlanId(VlanId.ANY));
- }
- return fob.permit().fromApp(appId);
- }
-
- /**
- * Updates L2 flooding groups; add pair link into L2 flooding group of given xconnect vlan.
- *
- * @param deviceId Device ID
- * @param port Port details
- * @param vlanId VLAN ID
- * @param install Whether to add or revoke pair link addition to flooding group
- */
- private void updateL2Flooding(DeviceId deviceId, PortNumber port, VlanId vlanId, boolean install) {
- XconnectKey key = new XconnectKey(deviceId, vlanId);
- // Ensure leadership on device
- if (!isLocalLeader(deviceId)) {
- log.debug("Abort updating L2Flood {}: {}", key, ERROR_NOT_LEADER);
- return;
- }
-
- // Locate L2 flooding group details for given xconnect vlan
- int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
- if (nextId == -1) {
- log.debug("XConnect vlan {} broadcast group for device {} doesn't exists. " +
- "Aborting pair group linking.", vlanId, deviceId);
- return;
- }
-
- // Add pairing-port group to flooding group
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- // treatment.popVlan();
- treatment.setOutput(port);
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("Pair port added/removed to vlan {} next objective {} on {}",
- vlanId, nextId, deviceId),
- (objective, error) ->
- log.warn("Failed adding/removing pair port to vlan {} next objective {} on {}." +
- "Error : {}", vlanId, nextId, deviceId, error)
- );
- NextObjective.Builder vlanNextObjectiveBuilder = DefaultNextObjective.builder()
- .withId(nextId)
- .withType(NextObjective.Type.BROADCAST)
- .fromApp(srService.appId())
- .withMeta(DefaultTrafficSelector.builder().matchVlanId(vlanId).build())
- .addTreatment(treatment.build());
- if (install) {
- flowObjectiveService.next(deviceId, vlanNextObjectiveBuilder.addToExisting(context));
- } else {
- flowObjectiveService.next(deviceId, vlanNextObjectiveBuilder.removeFromExisting(context));
- }
- log.debug("Submitted next objective {} for vlan: {} in device {}",
- nextId, vlanId, deviceId);
- }
-
- /**
- * Populate L2 multicast rule on given deviceId that matches given mac, given vlan and
- * output to given port's L2 mulitcast group.
- *
- * @param deviceId Device ID
- * @param pairPort Pair port number
- * @param vlanId VLAN ID
- * @param accessPorts List of access ports to be added into L2 multicast group
- */
- private void populateL2Multicast(DeviceId deviceId, PortNumber pairPort,
- VlanId vlanId, List<PortNumber> accessPorts) {
- // Ensure enough rights to program pair device
- if (!srService.shouldProgram(deviceId)) {
- log.debug("Abort populate L2Multicast {}-{}: {}", deviceId, vlanId, ERROR_NOT_LEADER);
- return;
- }
-
- boolean multicastGroupExists = true;
- int vlanMulticastNextId;
- VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
- // Step 1 : Populate single homed access ports into vlan's L2 multicast group
- NextObjective.Builder vlanMulticastNextObjBuilder = DefaultNextObjective
- .builder()
- .withType(NextObjective.Type.BROADCAST)
- .fromApp(srService.appId())
- .withMeta(DefaultTrafficSelector.builder().matchVlanId(vlanId)
- .matchEthDst(MacAddress.IPV4_MULTICAST).build());
- vlanMulticastNextId = getMulticastGroupNextObjectiveId(key);
- if (vlanMulticastNextId == -1) {
- // Vlan's L2 multicast group doesn't exist; create it, update store and add pair port as sub-group
- multicastGroupExists = false;
- vlanMulticastNextId = flowObjectiveService.allocateNextId();
- addMulticastGroupNextObjectiveId(key, vlanMulticastNextId);
- vlanMulticastNextObjBuilder.addTreatment(
- DefaultTrafficTreatment.builder().setOutput(pairPort).build()
- );
- }
- vlanMulticastNextObjBuilder.withId(vlanMulticastNextId);
- int nextId = vlanMulticastNextId;
- accessPorts.forEach(p -> {
- TrafficTreatment.Builder egressAction = DefaultTrafficTreatment.builder();
- // Do vlan popup action based on interface configuration
- if (interfaceService.getInterfacesByPort(new ConnectPoint(deviceId, p))
- .stream().noneMatch(i -> i.vlanTagged().contains(vlanId))) {
- egressAction.popVlan();
- }
- egressAction.setOutput(p);
- vlanMulticastNextObjBuilder.addTreatment(egressAction.build());
- addMulticastGroupPort(key, p);
- });
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("L2 multicast group installed/updated. "
- + "NextObject Id {} on {} for subnet {} ",
- nextId, deviceId, vlanId),
- (objective, error) ->
- log.warn("L2 multicast group failed to install/update. "
- + " NextObject Id {} on {} for subnet {} : {}",
- nextId, deviceId, vlanId, error)
- );
- if (!multicastGroupExists) {
- flowObjectiveService.next(deviceId, vlanMulticastNextObjBuilder.add(context));
-
- // Step 2 : Populate ACL rule; selector = vlan + pair-port, output = vlan L2 multicast group
- TrafficSelector.Builder multicastSelector = DefaultTrafficSelector.builder();
- multicastSelector.matchEthType(Ethernet.TYPE_VLAN);
- multicastSelector.matchInPort(pairPort);
- multicastSelector.matchVlanId(vlanId);
- ForwardingObjective.Builder vlanMulticastForwardingObj = DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .nextStep(vlanMulticastNextId)
- .withSelector(multicastSelector.build())
- .withPriority(100)
- .fromApp(srService.appId())
- .makePermanent();
- context = new DefaultObjectiveContext(
- (objective) -> log.debug("L2 multicasting versatile rule for device {}, port/vlan {}/{} populated",
- deviceId,
- pairPort,
- vlanId),
- (objective, error) -> log.warn("Failed to populate L2 multicasting versatile rule for device {}, " +
- "ports/vlan {}/{}: {}", deviceId, pairPort, vlanId, error));
- flowObjectiveService.forward(deviceId, vlanMulticastForwardingObj.add(context));
- } else {
- // L2_MULTICAST & BROADCAST are similar structure in subgroups; so going with BROADCAST type.
- vlanMulticastNextObjBuilder.withType(NextObjective.Type.BROADCAST);
- flowObjectiveService.next(deviceId, vlanMulticastNextObjBuilder.addToExisting(context));
- }
- }
-
- /**
- * Removes access ports from VLAN L2 multicast group on given deviceId.
- *
- * @param deviceId Device ID
- * @param vlanId VLAN ID
- * @param accessPorts List of access ports to be added into L2 multicast group
- */
- private void revokeL2Multicast(DeviceId deviceId, VlanId vlanId, List<PortNumber> accessPorts) {
- // Ensure enough rights to program pair device
- if (!srService.shouldProgram(deviceId)) {
- log.debug("Abort revoke L2Multicast {}-{}: {}", deviceId, vlanId, ERROR_NOT_LEADER);
- return;
- }
-
- VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
- int vlanMulticastNextId = getMulticastGroupNextObjectiveId(key);
- if (vlanMulticastNextId == -1) {
- return;
- }
- NextObjective.Builder vlanMulticastNextObjBuilder = DefaultNextObjective
- .builder()
- .withType(NextObjective.Type.BROADCAST)
- .fromApp(srService.appId())
- .withMeta(DefaultTrafficSelector.builder().matchVlanId(vlanId).build())
- .withId(vlanMulticastNextId);
- accessPorts.forEach(p -> {
- TrafficTreatment.Builder egressAction = DefaultTrafficTreatment.builder();
- // Do vlan popup action based on interface configuration
- if (interfaceService.getInterfacesByPort(new ConnectPoint(deviceId, p))
- .stream().noneMatch(i -> i.vlanTagged().contains(vlanId))) {
- egressAction.popVlan();
- }
- egressAction.setOutput(p);
- vlanMulticastNextObjBuilder.addTreatment(egressAction.build());
- removeMulticastGroupPort(key, p);
- });
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("L2 multicast group installed/updated. "
- + "NextObject Id {} on {} for subnet {} ",
- vlanMulticastNextId, deviceId, vlanId),
- (objective, error) ->
- log.warn("L2 multicast group failed to install/update. "
- + " NextObject Id {} on {} for subnet {} : {}",
- vlanMulticastNextId, deviceId, vlanId, error)
- );
- flowObjectiveService.next(deviceId, vlanMulticastNextObjBuilder.removeFromExisting(context));
- }
-
- /**
- * Cleans up VLAN L2 multicast group on given deviceId. ACL rules for the group will also be deleted.
- * Normally multicast group is not removed if it contains access ports; which can be forced
- * by "force" flag
- *
- * @param deviceId Device ID
- * @param pairPort Pair port number
- * @param vlanId VLAN ID
- * @param force Forceful removal
- */
- private void cleanupL2MulticastRule(DeviceId deviceId, PortNumber pairPort, VlanId vlanId, boolean force) {
-
- // Ensure enough rights to program pair device
- if (!srService.shouldProgram(deviceId)) {
- log.debug("Abort cleanup L2Multicast {}-{}: {}", deviceId, vlanId, ERROR_NOT_LEADER);
- return;
- }
-
- VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
-
- // Ensure L2 multicast group doesn't contain access ports
- if (hasAccessPortInMulticastGroup(key, pairPort) && !force) {
- return;
- }
-
- // Load L2 multicast group details
- int vlanMulticastNextId = getMulticastGroupNextObjectiveId(key);
- if (vlanMulticastNextId == -1) {
- return;
- }
-
- // Step 1 : Clear ACL rule; selector = vlan + pair-port, output = vlan L2 multicast group
- TrafficSelector.Builder l2MulticastSelector = DefaultTrafficSelector.builder();
- l2MulticastSelector.matchEthType(Ethernet.TYPE_VLAN);
- l2MulticastSelector.matchInPort(pairPort);
- l2MulticastSelector.matchVlanId(vlanId);
- ForwardingObjective.Builder vlanMulticastForwardingObj = DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .nextStep(vlanMulticastNextId)
- .withSelector(l2MulticastSelector.build())
- .withPriority(100)
- .fromApp(srService.appId())
- .makePermanent();
- ObjectiveContext context = new DefaultObjectiveContext(
- (objective) -> log.debug("L2 multicasting rule for device {}, port/vlan {}/{} deleted", deviceId,
- pairPort, vlanId),
- (objective, error) -> log.warn("Failed to delete L2 multicasting rule for device {}, " +
- "ports/vlan {}/{}: {}", deviceId, pairPort, vlanId, error));
- flowObjectiveService.forward(deviceId, vlanMulticastForwardingObj.remove(context));
-
- // Step 2 : Clear L2 multicast group associated with vlan
- NextObjective.Builder l2MulticastGroupBuilder = DefaultNextObjective
- .builder()
- .withId(vlanMulticastNextId)
- .withType(NextObjective.Type.BROADCAST)
- .fromApp(srService.appId())
- .withMeta(DefaultTrafficSelector.builder()
- .matchVlanId(vlanId)
- .matchEthDst(MacAddress.IPV4_MULTICAST).build())
- .addTreatment(DefaultTrafficTreatment.builder().popVlan().setOutput(pairPort).build());
- context = new DefaultObjectiveContext(
- (objective) ->
- log.debug("L2 multicast group with NextObject Id {} deleted on {} for subnet {} ",
- vlanMulticastNextId, deviceId, vlanId),
- (objective, error) ->
- log.warn("L2 multicast group with NextObject Id {} failed to delete on {} for subnet {} : {}",
- vlanMulticastNextId, deviceId, vlanId, error)
- );
- flowObjectiveService.next(deviceId, l2MulticastGroupBuilder.remove(context));
-
- // Finally clear store.
- removeMulticastGroup(key);
- }
-
- private int getMulticastGroupNextObjectiveId(VlanNextObjectiveStoreKey key) {
- return Versioned.valueOrElse(xconnectMulticastNextStore.get(key), -1);
- }
-
- private void addMulticastGroupNextObjectiveId(VlanNextObjectiveStoreKey key, int nextId) {
- if (nextId == -1) {
- return;
- }
- xconnectMulticastNextStore.put(key, nextId);
- }
-
- private void addMulticastGroupPort(VlanNextObjectiveStoreKey groupKey, PortNumber port) {
- xconnectMulticastPortsStore.compute(groupKey, (key, ports) -> {
- if (ports == null) {
- ports = Lists.newArrayList();
- }
- ports.add(port);
- return ports;
- });
- }
-
- private void removeMulticastGroupPort(VlanNextObjectiveStoreKey groupKey, PortNumber port) {
- xconnectMulticastPortsStore.compute(groupKey, (key, ports) -> {
- if (ports != null && !ports.isEmpty()) {
- ports.remove(port);
- }
- return ports;
- });
- }
-
- private void removeMulticastGroup(VlanNextObjectiveStoreKey groupKey) {
- xconnectMulticastPortsStore.remove(groupKey);
- xconnectMulticastNextStore.remove(groupKey);
- }
-
- private boolean hasAccessPortInMulticastGroup(VlanNextObjectiveStoreKey groupKey, PortNumber pairPort) {
- List<PortNumber> ports = Versioned.valueOrElse(xconnectMulticastPortsStore.get(groupKey), ImmutableList.of());
- return ports.stream().anyMatch(p -> !p.equals(pairPort));
- }
-
- // Custom-built function, when the device is not available we need a fallback mechanism
- private boolean isLocalLeader(DeviceId deviceId) {
- if (!mastershipService.isLocalMaster(deviceId)) {
- // When the device is available we just check the mastership
- if (deviceService.isAvailable(deviceId)) {
- return false;
- }
- // Fallback with Leadership service - device id is used as topic
- NodeId leader = leadershipService.runForLeadership(
- deviceId.toString()).leaderNodeId();
- // Verify if this node is the leader
- return clusterService.getLocalNode().id().equals(leader);
- }
- return true;
- }
-
- private Set<PortNumber> getPhysicalPorts(DeviceId deviceId, XconnectEndpoint endpoint) {
- if (endpoint.type() == XconnectEndpoint.Type.PORT) {
- PortNumber port = ((XconnectPortEndpoint) endpoint).port();
- return Sets.newHashSet(port);
- }
- if (endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER) {
- PortLoadBalancerId portLoadBalancerId = new PortLoadBalancerId(deviceId,
- ((XconnectLoadBalancerEndpoint) endpoint).key());
- Set<PortNumber> ports = portLoadBalancerService.getPortLoadBalancer(portLoadBalancerId).ports();
- return Sets.newHashSet(ports);
- }
- return Sets.newHashSet();
- }
-
- private NextTreatment getNextTreatment(DeviceId deviceId, XconnectEndpoint endpoint, boolean reserve) {
- if (endpoint.type() == XconnectEndpoint.Type.PORT) {
- PortNumber port = ((XconnectPortEndpoint) endpoint).port();
- return DefaultNextTreatment.of(DefaultTrafficTreatment.builder().setOutput(port).build());
- }
- if (endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER) {
- PortLoadBalancerId portLoadBalancerId = new PortLoadBalancerId(deviceId,
- ((XconnectLoadBalancerEndpoint) endpoint).key());
- NextTreatment idNextTreatment = IdNextTreatment.of(portLoadBalancerService
- .getPortLoadBalancerNext(portLoadBalancerId));
- // Reserve only one time during next objective creation
- if (reserve) {
- if (!portLoadBalancerService.reserve(portLoadBalancerId, appId)) {
- log.warn("Reservation failed for {}", portLoadBalancerId);
- idNextTreatment = null;
- }
- }
- return idNextTreatment;
- }
- return null;
- }
-
- private class InternalPortLoadBalancerListener implements PortLoadBalancerListener {
- // Populate xconnect once portloadbalancer is available
- @Override
- public void event(PortLoadBalancerEvent event) {
- portLoadBalancerExecutor.execute(() -> dequeue(event.subject().portLoadBalancerId()));
- }
- // When we receive INSTALLED port load balancing is ready
- @Override
- public boolean isRelevant(PortLoadBalancerEvent event) {
- return event.type() == PortLoadBalancerEvent.Type.INSTALLED;
- }
- }
-
- // Invalidate the cache and re-start the xconnect installation
- private void dequeue(PortLoadBalancerId portLoadBalancerId) {
- XconnectKey xconnectKey = portLoadBalancerCache.getIfPresent(portLoadBalancerId);
- if (xconnectKey == null) {
- log.trace("{} not present in the cache", portLoadBalancerId);
- return;
- }
- log.debug("Dequeue {}", portLoadBalancerId);
- portLoadBalancerCache.invalidate(portLoadBalancerId);
- Set<XconnectEndpoint> endpoints = Versioned.valueOrNull(xconnectStore.get(xconnectKey));
- if (endpoints == null || endpoints.isEmpty()) {
- log.warn("Endpoints not found for XConnect {}", xconnectKey);
- return;
- }
- populateXConnect(xconnectKey, endpoints);
- log.trace("PortLoadBalancer cache size {}", portLoadBalancerCache.size());
- }
-
-}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/package-info.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/package-info.java
deleted file mode 100644
index 547e3bc..0000000
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/xconnect/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * VLAN cross connect implementation.
- */
-package org.onosproject.segmentrouting.xconnect.impl;
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/AugmentedPortAuthTracker.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/AugmentedPortAuthTracker.java
deleted file mode 100644
index cc214e3..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/AugmentedPortAuthTracker.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An augmented implementation of {@link PortAuthTracker}, so that we can
- * instrument its behavior for unit test assertions.
- */
-class AugmentedPortAuthTracker extends PortAuthTracker {
-
- // instrument blocking flow activity, so we can see when we get hits
- final List<ConnectPoint> installed = new ArrayList<>();
- final List<ConnectPoint> cleared = new ArrayList<>();
-
-
- void resetMetrics() {
- installed.clear();
- cleared.clear();
- }
-
- @Override
- void installBlockingFlow(DeviceId d, PortNumber p) {
- super.installBlockingFlow(d, p);
- installed.add(new ConnectPoint(d, p));
- }
-
- @Override
- void clearBlockingFlow(DeviceId d, PortNumber p) {
- super.clearBlockingFlow(d, p);
- cleared.add(new ConnectPoint(d, p));
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java
deleted file mode 100644
index a6278b2..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.DefaultControllerNode;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.TestConsistentMap;
-import org.onosproject.store.service.TestConsistentMultimap;
-
-import java.util.Optional;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.junit.Assert.*;
-
-public class DefaultRoutingHandlerTest {
- private SegmentRoutingManager srManager;
- private DefaultRoutingHandler dfh;
-
- private static final DeviceId DEV1A = DeviceId.deviceId("of:1a");
- private static final DeviceId DEV1B = DeviceId.deviceId("of:1b");
- private static final DeviceId DEV2 = DeviceId.deviceId("of:2");
-
- private static final NodeId NODE1 = NodeId.nodeId("192.168.1.1");
- private static final NodeId NODE2 = NodeId.nodeId("192.168.1.2");
- private static final NodeId NODE3 = NodeId.nodeId("192.168.1.3");
- private static final IpAddress IP1 = IpAddress.valueOf("192.168.1.1");
- private static final IpAddress IP2 = IpAddress.valueOf("192.168.1.2");
- private static final IpAddress IP3 = IpAddress.valueOf("192.168.1.3");
-
- @Before
- public void setUp() {
- srManager = createMock(SegmentRoutingManager.class);
- srManager.storageService = createMock(StorageService.class);
- expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
- expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
- new TestConsistentMultimap.Builder<>()).anyTimes();
- replay(srManager.storageService);
- srManager.routingRulePopulator = createMock(RoutingRulePopulator.class);
- srManager.deviceService = createMock(DeviceService.class);
- srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
- srManager.mastershipService = createMock(MastershipService.class);
- srManager.clusterService = createMock(ClusterService.class);
- dfh = new DefaultRoutingHandler(srManager);
- }
-
- private void clearCache() {
- dfh.invalidateShouldProgramCache(DEV1A);
- dfh.invalidateShouldProgramCache(DEV1B);
- dfh.invalidateShouldProgramCache(DEV2);
- }
-
- // Node 1 is the master of switch 1A, 1B, and 2
- @Test
- public void testShouldHandleRoutingCase1() {
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE1).anyTimes();
- replay(srManager.mastershipService);
-
- expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
- expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
- expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
- replay(srManager);
-
- // Node 1 should program every device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertTrue(dfh.shouldProgram(DEV1A));
- assertTrue(dfh.shouldProgram(DEV1B));
- assertTrue(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 3 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
- }
-
- // Node 1 is the master of switch 1A, 1B
- // Node 2 is the master of switch 2
- @Test
- public void testShouldHandleRoutingCase2() {
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE2).anyTimes();
- replay(srManager.mastershipService);
-
- expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
- expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
- expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
- replay(srManager);
-
- // Node 1 should program 1A, 1B
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertTrue(dfh.shouldProgram(DEV1A));
- assertTrue(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program 2
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertTrue(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 3 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
- }
-
- // Node 1 is the master of switch 1A
- // Node 2 is the master of switch 1B
- // Node 3 is the master of switch 2
- @Test
- public void testShouldHandleRoutingCase3() {
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
- replay(srManager.mastershipService);
-
- expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
- expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
- expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
- replay(srManager);
-
- // Node 1 should program 1A, 1B
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertTrue(dfh.shouldProgram(DEV1A));
- assertTrue(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 3 should program 2
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertTrue(dfh.shouldProgram(DEV2));
- }
-
- // Node 3 is the master of switch 1A, 1B, 2
- // Later on, node 1 becomes the master of 1A; Node 2 becomes the master of 1B.
- @Test
- public void testShouldHandleRoutingCase4() {
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE3).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE3).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
- replay(srManager.mastershipService);
-
- expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
- expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
- expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes();
- replay(srManager);
-
- // Node 1 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 3 should program 1A, 1B and 2
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
- replay(srManager.clusterService);
- assertTrue(dfh.shouldProgram(DEV1A));
- assertTrue(dfh.shouldProgram(DEV1B));
- assertTrue(dfh.shouldProgram(DEV2));
-
- // Mastership of switch 1A moves to Node 1
- reset(srManager.mastershipService);
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
- replay(srManager.mastershipService);
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 1 should program 1A, 1B
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertTrue(dfh.shouldProgram(DEV1A));
- assertTrue(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertFalse(dfh.shouldProgram(DEV2));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 3 should program 2
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- assertTrue(dfh.shouldProgram(DEV2));
- }
-
- // Node 1 is the master of 1A. 1B has no master
- // Node 2 becomes the master of 1B later
- @Test
- public void testShouldHandleRoutingCase5() {
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes();
- replay(srManager.mastershipService);
-
- expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
- expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
- replay(srManager);
-
- // Node 1 should program both 1A and 1B
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertTrue(dfh.shouldProgram(DEV1A));
- assertTrue(dfh.shouldProgram(DEV1B));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
-
- // Mastership of switch 1B moves to Node 2
- reset(srManager.mastershipService);
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
- replay(srManager.mastershipService);
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 1 should program 1A, 1B
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertTrue(dfh.shouldProgram(DEV1A));
- assertTrue(dfh.shouldProgram(DEV1B));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
- }
-
- // Neither 1A or 1B has master
- @Test
- public void testShouldHandleRoutingCase6() {
- expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(null).anyTimes();
- expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes();
- replay(srManager.mastershipService);
-
- expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
- expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
- replay(srManager);
-
- // Node 1 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
-
- reset(srManager.clusterService);
- clearCache();
-
- // Node 2 should program no device
- expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
- replay(srManager.clusterService);
- assertFalse(dfh.shouldProgram(DEV1A));
- assertFalse(dfh.shouldProgram(DEV1B));
-
- assertFalse(dfh.shouldProgram.containsKey(Sets.newHashSet(DEV1A, DEV1B)));
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
deleted file mode 100644
index d67cb07..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.util.PredictableExecutor;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.host.HostProbingService;
-import org.onosproject.net.host.ProbeMode;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onosproject.routeservice.RouteInfo;
-import org.onosproject.routeservice.RouteService;
-import org.onosproject.routeservice.RouteTableId;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.TestConsistentMap;
-import org.onosproject.store.service.TestConsistentMultimap;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.*;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Unit test for {@link HostHandler}.
- */
-public class HostHandlerTest {
- private HostHandler hostHandler;
-
- // Mocked routing and bridging tables
- private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
- Maps.newConcurrentMap();
- private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
- Maps.newConcurrentMap();
- private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
- // Mocked Next Id
- private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
-
- // Host Mac, VLAN
- private static final ProviderId PROVIDER_ID = ProviderId.NONE;
- private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
- private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
- private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
- private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
- private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
- // Host IP
- private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
- private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
- private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
- private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
- private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
- private static final IpAddress HOST_IP33 = IpAddress.valueOf("10.0.3.3");
- // Device
- private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
- private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
- private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
- private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
- private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
- private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
- // Port
- private static final PortNumber P1 = PortNumber.portNumber(1);
- private static final PortNumber P2 = PortNumber.portNumber(2);
- private static final PortNumber P3 = PortNumber.portNumber(3);
- private static final PortNumber P9 = PortNumber.portNumber(9);
- // Connect Point
- private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
- private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
- private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
- private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
- private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
- private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
- private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
- private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
- private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
- private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
- // Connect Point for dual-homed host failover
- private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
- private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
- private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
- private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
- private static final ConnectPoint CP33 = new ConnectPoint(DEV3, P3);
- private static final HostLocation HOST_LOC33 = new HostLocation(CP33, 0);
- private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
- private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
- private static final ConnectPoint CP42 = new ConnectPoint(DEV4, P2);
- private static final HostLocation HOST_LOC42 = new HostLocation(CP42, 0);
- private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
- private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
- // Conenct Point for mastership test
- private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
- private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
- private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
- private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
- // Interface VLAN
- private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
- private static final VlanId INTF_VLAN_TAGGED_1 = VlanId.vlanId((short) 20);
- private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(INTF_VLAN_TAGGED_1);
- private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
- private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
- VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
- private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
- // Interface subnet
- private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
- private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
- private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
- private static final InterfaceIpAddress INTF_IP1 =
- new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
- private static final InterfaceIpAddress INTF_IP2 =
- new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
- private static final InterfaceIpAddress INTF_IP3 =
- new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
- // Interfaces
- private static final Interface INTF11 =
- new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF12 =
- new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF13 =
- new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
- null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
- private static final Interface INTF21 =
- new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF22 =
- new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF31 =
- new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF32 =
- new Interface(null, CP32, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF33 =
- new Interface(null, CP33, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
- INTF_VLAN_OTHER, null, null);
- private static final Interface INTF39 =
- new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- null, INTF_VLAN_PAIR, null);
- private static final Interface INTF41 =
- new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF42 =
- new Interface(null, CP42, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final Interface INTF49 =
- new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
- null, INTF_VLAN_PAIR, null);
- // Host
- private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
- HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
- false);
-
- // A set of hosts
- private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
- // A set of devices of which we have mastership
- private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
- // A set of interfaces
- private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
- INTF22, INTF31, INTF32, INTF33, INTF39, INTF41, INTF42, INTF49);
-
- private MockHostProbingService mockLocationProbingService;
-
- @Before
- public void setUp() {
- // Initialize pairDevice and pairLocalPort config
- ObjectMapper mapper = new ObjectMapper();
- ConfigApplyDelegate delegate = config -> { };
-
- SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
- JsonNode dev3Tree = mapper.createObjectNode();
- dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
- dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
-
- SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
- JsonNode dev4Tree = mapper.createObjectNode();
- dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
- dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
-
- MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
- mockNetworkConfigRegistry.applyConfig(dev3Config);
- mockNetworkConfigRegistry.applyConfig(dev4Config);
-
- // Initialize Segment Routing Manager
- SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
- srManager.storageService = createMock(StorageService.class);
- expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
- expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
- new TestConsistentMultimap.Builder<>()).anyTimes();
- replay(srManager.storageService);
- srManager.cfgService = new NetworkConfigRegistryAdapter();
- srManager.deviceConfiguration = new DeviceConfiguration(srManager);
- srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
- srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
- srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
- srManager.interfaceService = new MockInterfaceService(INTERFACES);
- srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
- srManager.hostService = new MockHostService(HOSTS);
- srManager.cfgService = mockNetworkConfigRegistry;
- mockLocationProbingService = new MockHostProbingService();
- srManager.probingService = mockLocationProbingService;
- srManager.linkHandler = new MockLinkHandler(srManager);
-
- // Not important for most of the HostHandler test case. Simply return an empty set here
- srManager.routeService = createNiceMock(RouteService.class);
- expect(srManager.routeService.getRouteTables()).andReturn(Sets.newHashSet()).anyTimes();
- replay(srManager.routeService);
-
- hostHandler = new HostHandler(srManager);
- hostHandler.hostWorkers = new PredictableExecutor(
- 0, groupedThreads("onos/sr", "h-worker-%d"), true);
-
- ROUTING_TABLE.clear();
- BRIDGING_TABLE.clear();
- }
-
- @Test
- public void init() {
- hostHandler.init(DEV1);
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- hostHandler.init(DEV2);
- assertEquals(2, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
- assertEquals(2, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testHostAddedAtWrongLocation() {
- hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
- }
-
-
- @Test()
- public void testHostAddedAtCorrectLocation() {
- hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- }
-
- @Test
- public void testHostAdded() {
- Host subject;
-
- // Untagged host discovered on untagged port
- // Expect: add one routing rule and one bridging rule
- subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Untagged host discovered on tagged/native port
- // Expect: add one routing rule and one bridging rule
- subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(2, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertEquals(2, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
-
- // Tagged host discovered on untagged port
- // Expect: ignore the host. No rule is added.
- subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(2, BRIDGING_TABLE.size());
-
- // Tagged host discovered on tagged port with the same IP
- // Expect: update existing route, add one bridging rule
- subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
- Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(2, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
- HOST_IP21.toIpPrefix())).vlanId);
- assertEquals(3, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
- }
-
- @Test
- public void testDualHomedHostAdded() {
- // Add a dual-homed host that has 2 locations
- // Expect: add two routing rules and two bridging rules
- Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(2, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
- assertEquals(2, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
- }
-
- @Test
- public void testSingleHomedHostAddedOnPairLeaf() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC33), Sets.newHashSet(HOST_IP33), false);
-
- // Add a single-homed host with one location
- // Expect: the pair link should not be utilized
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(1, ROUTING_TABLE.size());
- assertEquals(P3, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP33.toIpPrefix())).portNumber);
- assertEquals(1, BRIDGING_TABLE.size());
- assertEquals(P3, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
- }
-
- @Test
- public void testDualHomedHostAddedOneByOne() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-
- // Add a dual-homed host with one location
- // Expect: the pair link is utilized temporarily before the second location is discovered
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- // Expect probe to be sent out on pair device
- assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, ProbeMode.DISCOVER));
-
- // Add the second location of dual-homed host
- // Expect: no longer use the pair link
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- }
-
- @Test
- public void testHostRemoved() {
- Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-
- // Add a host
- // Expect: add one routing rule and one bridging rule
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Remove the host
- // Expect: add the routing rule and the bridging rule
- hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, BRIDGING_TABLE.size());
- }
-
- @Test
- public void testDualHomedHostRemoved() {
- // Add a dual-homed host that has 2 locations
- // Expect: add two routing rules and two bridging rules
- Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(2, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
- assertEquals(2, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Remove a dual-homed host that has 2 locations
- // Expect: all routing and bridging rules are removed
- hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, BRIDGING_TABLE.size());
- }
-
- @Test
- public void testHostMoved() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
- Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
-
- // Add a host
- // Expect: add one new routing rule, one new bridging rule
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Move the host to CP13, which has different subnet setting
- // Expect: remove routing rule. Change vlan in bridging rule.
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
- assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Move the host to CP21, which has same subnet setting
- // Expect: add a new routing rule. Change vlan in bridging rule.
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
- assertEquals(1, ROUTING_TABLE.size());
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
- }
-
- @Test
- public void testDualHomedHostMoved() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
- Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
- Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
- Host host5 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC12, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-
-
- // Add a host with IP11, IP12 and LOC11, LOC21
- // Expect: 4 routing rules and 2 bridging rules
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Move the host to LOC12, LOC21 and keep the IP
- // Expect: 4 routing rules and 2 bridging rules all at the new location
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host5, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Move the host to LOC12, LOC22 and keep the IP
- // Expect: 4 routing rules and 2 bridging rules all at the new location
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host5));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
- // Expect: 4 routing rules and 2 bridging rules all at the new location
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
- // Expect: 4 routing rules and 2 bridging rules all at the new location
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- }
-
- @Test
- public void testDualHomedHostMoveTransient() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-
- // Mock DefaultRoutingHandler
- DefaultRoutingHandler mockDefaultRoutingHandler = createMock(DefaultRoutingHandler.class);
- hostHandler.srManager.defaultRoutingHandler = mockDefaultRoutingHandler;
-
- // Host moved from [1A/1, 1B/1] to [1A/2, 1B/1]
- // We should expect only one bridging flow and one routing flow programmed on 1A
-
- expect(mockDefaultRoutingHandler.populateBridging(DEV3, P2, HOST_MAC, HOST_VLAN_UNTAGGED))
- .andReturn(CompletableFuture.completedFuture(null)).once();
- expect(mockDefaultRoutingHandler.populateRoute(DEV3, HOST_IP11.toIpPrefix(),
- HOST_MAC, HOST_VLAN_UNTAGGED, P2, true))
- .andReturn(CompletableFuture.completedFuture(null)).once();
- replay(mockDefaultRoutingHandler);
-
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
- verify(mockDefaultRoutingHandler);
- }
-
- @Test
- public void testHostMoveToInvalidLocation() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
-
- // Add a host
- // Expect: add one new routing rule, one new bridging rule
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Move the host to an invalid location
- // Expect: Old flow is removed. New flow is not created
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, BRIDGING_TABLE.size());
-
- // Move the host to a valid location
- // Expect: add one new routing rule, one new bridging rule
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
- }
-
- @Test
- public void testDualHomedHostMoveToInvalidLocation() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
- Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
-
- // Add a host
- // Expect: add two new routing rules, two new bridging rules
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Move first host location to an invalid location
- // Expect: One routing and one bridging flow
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
- assertEquals(1, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(1, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Move second host location to an invalid location
- // Expect: No routing or bridging rule
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, BRIDGING_TABLE.size());
-
- // Move second host location back to a valid location
- // Expect: One routing and one bridging flow
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
- assertEquals(1, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(1, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Move first host location back to a valid location
- // Expect: Two routing and two bridging flow
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- }
-
- @Test
- public void testDualHomingSingleLocationFail() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-
- // Add a host
- // Expect: add four new routing rules, two new bridging rules
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Host becomes single-homed
- // Expect: redirect flows from host location to pair link
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Host becomes dual-homed again
- // Expect: Redirect flows from pair link back to host location
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- }
-
- @Test
- public void testDualHomingBothLocationFail() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
-
- // Add a host
- // Expect: add four new routing rules, two new bridging rules
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Host becomes single-homed
- // Expect: redirect flows from host location to pair link
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Host loses both locations
- // Expect: Remove last location and all previous redirection flows
- hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, BRIDGING_TABLE.size());
- }
-
- @Test
- public void testHostUpdated() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
- Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
-
- // Add a host
- // Expect: add one new routing rule. Add one new bridging rule.
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
- INTF_VLAN_UNTAGGED)));
-
- // Update the host IP to same subnet
- // Expect: update routing rule with new IP. No change to bridging rule.
- hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
- assertEquals(1, ROUTING_TABLE.size());
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Update the host IP to different subnet
- // Expect: Remove routing rule. No change to bridging rule.
- hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- }
-
- @Test
- public void testDelayedIpAndLocation() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
- Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-
- // Add a dual-home host with only one location and no IP
- // Expect: only bridging redirection works
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Discover IP
- // Expect: routing redirection should also work
- hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- // Expect probe to be sent out on pair device
- assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
-
- // Discover location
- // Expect: cancel all redirections
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- }
-
- @Test
- public void testDelayedIpAndLocation2() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
- Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
-
- // Add a dual-home host with only one location and no IP
- // Expect: only bridging redirection works
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Discover Location
- // Expect: cancel bridging redirections
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-
- // Discover IP
- // Expect: add IP rules to both location
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
- assertEquals(2, ROUTING_TABLE.size());
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
- assertEquals(2, BRIDGING_TABLE.size());
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
- }
-
- @Test
- public void testDualHomedHostUpdated() {
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
- Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
-
- // Add a dual-homed host with two locations and two IPs
- // Expect: add four new routing rules. Add two new bridging rules
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
- assertEquals(2, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Update both host IPs
- // Expect: update routing rules with new IP. No change to bridging rule.
- hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
- assertEquals(4, ROUTING_TABLE.size());
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
- assertEquals(2, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- // Update one of the host IP to different subnet
- // Expect: update routing rule with new IP. No change to bridging rule.
- hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
- assertEquals(2, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
- assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
- assertEquals(2, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
- }
-
- @Test
- public void testVlanForPairPort() {
- assertEquals(INTF_VLAN_UNTAGGED, hostHandler.vlanForPairPort(VlanId.NONE, CP11));
- assertEquals(INTF_VLAN_NATIVE, hostHandler.vlanForPairPort(VlanId.NONE, CP13));
- assertEquals(INTF_VLAN_TAGGED_1, hostHandler.vlanForPairPort(INTF_VLAN_TAGGED_1, CP13));
- assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP11));
- assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP13));
- assertNull(hostHandler.vlanForPairPort(VlanId.NONE, CP51));
- assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP51));
- }
-
- @Test
- public void testHostRemovedWithRouteRemoved() {
- Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
-
- // Add a host
- // Expect: add one routing rule and one bridging rule
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
- assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
- assertEquals(1, BRIDGING_TABLE.size());
- assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-
- IpPrefix prefix = IpPrefix.valueOf("55.55.55.0/24");
-
- // Setting up mock route service
- RouteService routeService = hostHandler.srManager.routeService;
- reset(routeService);
-
- IpAddress nextHopIp2 = IpAddress.valueOf("20.0.0.1");
- MacAddress nextHopMac2 = MacAddress.valueOf("00:22:33:44:55:66");
- VlanId nextHopVlan2 = VlanId.NONE;
-
- Route r1 = new Route(Route.Source.STATIC, prefix, HOST_IP11);
- ResolvedRoute rr1 = new ResolvedRoute(r1, HOST_MAC, VlanId.NONE);
- Route r2 = new Route(Route.Source.STATIC, prefix, nextHopIp2);
- ResolvedRoute rr2 = new ResolvedRoute(r2, nextHopMac2, nextHopVlan2);
- RouteInfo routeInfo = new RouteInfo(prefix, rr1, Sets.newHashSet(rr1, rr2));
- RouteTableId routeTableId = new RouteTableId("ipv4");
-
- expect(routeService.getRouteTables()).andReturn(Sets.newHashSet(routeTableId));
- expect(routeService.getRoutes(routeTableId)).andReturn(Sets.newHashSet(routeInfo));
- replay(routeService);
-
- // Setting up mock device configuration
- hostHandler.srManager.deviceConfiguration = EasyMock.createNiceMock(DeviceConfiguration.class);
- DeviceConfiguration deviceConfiguration = hostHandler.srManager.deviceConfiguration;
- expect(deviceConfiguration.inSameSubnet(CP11, HOST_IP11)).andReturn(true);
- deviceConfiguration.removeSubnet(CP11, prefix);
- expectLastCall();
- replay(deviceConfiguration);
-
- // Remove the host
- // Expect: add the routing rule and the bridging rule
- hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, BRIDGING_TABLE.size());
-
- // Expect: subnet is removed from device config
- verify(deviceConfiguration);
- }
-
- @Test
- public void testHostProbing() {
- // Case: [1A/1, 1B/1] -> [1A/2, 1B/1]
- // Expect: DISCOVER probe should be sent to every port on 1B that has the same VLAN as 1A/2
- // VERIFY probe should be sent to 1B/1
- Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
- Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
- Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
- hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-
- hostHandler.srManager.probingService = createMock(HostProbingService.class);
- hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.DISCOVER);
- expectLastCall();
- hostHandler.srManager.probingService.probeHost(host2, CP42, ProbeMode.DISCOVER);
- expectLastCall();
- hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.VERIFY);
- expectLastCall();
- replay(hostHandler.srManager.probingService);
-
- hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-
- verify(hostHandler.srManager.probingService);
- }
-
- @Test
- public void testEffectiveLocations() {
- Host regularHost = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_TAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC12), Sets.newHashSet(HOST_IP11), false);
- Host auxHost = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_TAGGED,
- Sets.newHashSet(HOST_LOC11, HOST_LOC12), Sets.newHashSet(HOST_LOC21, HOST_LOC22),
- Sets.newHashSet(HOST_IP11), VlanId.NONE, EthType.EtherType.UNKNOWN.ethType(), false, false);
-
- assertEquals(Sets.newHashSet(HOST_LOC11, HOST_LOC12), hostHandler.effectiveLocations(regularHost));
- assertEquals(Sets.newHashSet(HOST_LOC21, HOST_LOC22), hostHandler.effectiveLocations(auxHost));
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java
deleted file mode 100644
index 68472de..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.MPLS;
-import org.onosproject.TestApplicationId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-
-import java.util.Collections;
-
-import static org.easymock.EasyMock.*;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
-import static org.onlab.packet.ICMP.*;
-import static org.onlab.packet.ICMP6.ECHO_REPLY;
-import static org.onosproject.segmentrouting.TestUtils.*;
-
-/**
- * Tests for IcmpHandler.
- */
-public class IcmpHandlerTest {
-
- private IcmpHandler icmpHandler;
- private MockPacketService packetService;
- private SegmentRoutingManager segmentRoutingManager;
- private ApplicationId testApplicationId = TestApplicationId.create("test");
-
- @Before
- public void setUp() {
-
- // Init
- ObjectMapper mapper = new ObjectMapper();
- ConfigApplyDelegate delegate = config -> { };
-
- // Setup configuration for app
- SegmentRoutingAppConfig appConfig = new SegmentRoutingAppConfig();
- JsonNode appTree = mapper.createObjectNode();
- appConfig.init(testApplicationId, "icmp-handler-test", appTree, mapper, delegate);
- appConfig.setSuppressSubnet(Collections.emptySet());
-
- // Setup configuration for the devices
- SegmentRoutingDeviceConfig remoteLeafConfig = new SegmentRoutingDeviceConfig();
- JsonNode remoteLeafTree = mapper.createObjectNode();
- remoteLeafConfig.init(REMOTE_LEAF, "icmp-handler-test", remoteLeafTree, mapper, delegate);
- remoteLeafConfig.setNodeSidIPv4(REMOTE_LEAF_SID4)
- .setNodeSidIPv6(REMOTE_LEAF_SID6)
- .setRouterIpv4(REMOTE_LEAF_LB4)
- .setRouterIpv6(REMOTE_LEAF_LB6)
- .setIsEdgeRouter(true)
- .setRouterMac(REMOTE_MAC.toString());
- SegmentRoutingDeviceConfig localLeafConfig = new SegmentRoutingDeviceConfig();
- JsonNode localLeafTree = mapper.createObjectNode();
- localLeafConfig.init(LOCAL_LEAF, "icmp-handler-test", localLeafTree, mapper, delegate);
- localLeafConfig.setNodeSidIPv4(LOCAL_LEAF_SID4)
- .setRouterIpv4(LOCAL_LEAF_LB4)
- .setNodeSidIPv6(LOCAL_LEAF_SID6)
- .setRouterIpv6(LOCAL_LEAF_LB6)
- .setIsEdgeRouter(true)
- .setRouterMac(LOCAL_MAC.toString());
- SegmentRoutingDeviceConfig localLeaf1Config = new SegmentRoutingDeviceConfig();
- JsonNode localLeaf1Tree = mapper.createObjectNode();
- localLeaf1Config.init(LOCAL_LEAF1, "icmp-handler-test", localLeaf1Tree, mapper, delegate);
- localLeaf1Config.setNodeSidIPv4(LOCAL_LEAF1_SID4)
- .setRouterIpv4(LOCAL_LEAF1_LB4)
- .setNodeSidIPv6(LOCAL_LEAF1_SID6)
- .setRouterIpv6(LOCAL_LEAF1_LB6)
- .setIsEdgeRouter(true)
- .setRouterMac(LOCAL_MAC1.toString())
- .setPairDeviceId(LOCAL_LEAF2)
- .setPairLocalPort(P3);
- SegmentRoutingDeviceConfig localLeaf2Config = new SegmentRoutingDeviceConfig();
- JsonNode localLeaf2Tree = mapper.createObjectNode();
- localLeaf2Config.init(LOCAL_LEAF2, "icmp-handler-test", localLeaf2Tree, mapper, delegate);
- localLeaf2Config.setNodeSidIPv4(LOCAL_LEAF2_SID4)
- .setRouterIpv4(LOCAL_LEAF2_LB4)
- .setNodeSidIPv6(LOCAL_LEAF2_SID6)
- .setRouterIpv6(LOCAL_LEAF2_LB6)
- .setIsEdgeRouter(true)
- .setRouterMac(LOCAL_MAC2.toString())
- .setPairDeviceId(LOCAL_LEAF1)
- .setPairLocalPort(P3);
-
- // Setup configuration for ports
- InterfaceConfig remoteLeafPorts1Config = new InterfaceConfig();
- ArrayNode remoteLeafPorts1Tree = mapper.createArrayNode();
- remoteLeafPorts1Config.init(CP12, "icmp-handler-test", remoteLeafPorts1Tree, mapper, delegate);
- remoteLeafPorts1Config.addInterface(INTF1);
- InterfaceConfig remoteLeafPorts2Config = new InterfaceConfig();
- ArrayNode remoteLeafPorts2Tree = mapper.createArrayNode();
- remoteLeafPorts2Config.init(CP13, "icmp-handler-test", remoteLeafPorts2Tree, mapper, delegate);
- remoteLeafPorts2Config.addInterface(INTF2);
- InterfaceConfig localLeafPortsConfig = new InterfaceConfig();
- ArrayNode localLeafPortsTree = mapper.createArrayNode();
- localLeafPortsConfig.init(CP1011, "icmp-handler-test", localLeafPortsTree, mapper, delegate);
- localLeafPortsConfig.addInterface(INTF111);
- InterfaceConfig localLeaf1PortsConfig = new InterfaceConfig();
- ArrayNode localLeaf1PortsTree = mapper.createArrayNode();
- localLeaf1PortsConfig.init(CP2011, "icmp-handler-test", localLeaf1PortsTree, mapper, delegate);
- localLeaf1PortsConfig.addInterface(INTF211);
- InterfaceConfig localLeaf2Ports1Config = new InterfaceConfig();
- ArrayNode localLeaf2Ports1Tree = mapper.createArrayNode();
- localLeaf2Ports1Config.init(CP2021, "icmp-handler-test", localLeaf2Ports1Tree, mapper, delegate);
- localLeaf2Ports1Config.addInterface(INTF212);
- InterfaceConfig localLeaf2Ports2Config = new InterfaceConfig();
- ArrayNode localLeaf2Ports2Tree = mapper.createArrayNode();
- localLeaf2Ports2Config.init(CP2024, "icmp-handler-test", localLeaf2Ports2Tree, mapper, delegate);
- localLeaf2Ports2Config.addInterface(INTF213);
-
- // Apply config
- MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
-
- mockNetworkConfigRegistry.applyConfig(remoteLeafConfig);
- mockNetworkConfigRegistry.applyConfig(remoteLeafPorts1Config);
- mockNetworkConfigRegistry.applyConfig(remoteLeafPorts2Config);
- mockNetworkConfigRegistry.applyConfig(localLeafConfig);
- mockNetworkConfigRegistry.applyConfig(localLeafPortsConfig);
- mockNetworkConfigRegistry.applyConfig(localLeaf1Config);
- mockNetworkConfigRegistry.applyConfig(localLeaf1PortsConfig);
- mockNetworkConfigRegistry.applyConfig(localLeaf2Config);
- mockNetworkConfigRegistry.applyConfig(localLeaf2Ports1Config);
- mockNetworkConfigRegistry.applyConfig(localLeaf2Ports2Config);
-
- segmentRoutingManager = new SegmentRoutingManager();
- segmentRoutingManager.appId = testApplicationId;
- packetService = new MockPacketService();
- segmentRoutingManager.packetService = packetService;
- segmentRoutingManager.cfgService = mockNetworkConfigRegistry;
- segmentRoutingManager.neighbourResolutionService = new MockNeighbourResolutionService();
- segmentRoutingManager.interfaceService = new MockInterfaceService(ImmutableSet.of(
- INTF1, INTF2, INTF111, INTF211, INTF212, INTF213));
- segmentRoutingManager.deviceConfiguration = new DeviceConfiguration(segmentRoutingManager);
- segmentRoutingManager.ipHandler = new IpHandler(segmentRoutingManager);
- segmentRoutingManager.deviceService = createMock(DeviceService.class);
- segmentRoutingManager.routeService = new MockRouteService(ROUTE_STORE);
- segmentRoutingManager.hostService = new MockHostService(Collections.emptySet());
- icmpHandler = new IcmpHandler(segmentRoutingManager);
- }
-
- // Ping to our gateway
- @Test
- public void testPing4MyGateway() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_MY, CP12);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_MY.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_MY.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_MY.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to our gateway
- @Test
- public void testPing6MyGateway() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_MY, CP12);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_MY.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_MY.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_MY.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping to a gateway attached to our leaf
- @Test
- public void testPing4LocalGateway() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_LOCAL, CP12);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOCAL.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOCAL.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOCAL.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4_LOCAL.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to a gateway attached to our leaf
- @Test
- public void testPing6LocalGateway() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOCAL, CP12);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOCAL.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOCAL.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOCAL.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_LOCAL.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping to a gateway attached only to the pair leaf (routing through spine)
- @Test
- public void testPing4RemoteGatewaySamePair() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_SAME, CP2025);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_SAME.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_SAME.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_SAME.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof MPLS);
- MPLS mpls = (MPLS) ethernet.getPayload();
- assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID4));
- assertTrue(mpls.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) mpls.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4_SAME.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to a gateway attached only to the pair leaf (routing through spine)
- @Test
- public void testPing6RemoteGatewaySamePair() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_SAME, CP2025);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_SAME.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_SAME.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_SAME.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof MPLS);
- MPLS mpls = (MPLS) ethernet.getPayload();
- assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID6));
- assertTrue(mpls.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) mpls.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_SAME.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping to a gateway but destination leaf is down
- @Test
- public void testPing4RemoteGatewayLeafDown() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF))
- .andReturn(false)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4, CP11);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4.getSourceMAC());
- assertNull(ethernet);
-
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to a gateway but destination leaf is down
- @Test
- public void testPing6RemoteGatewayLeafDown() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF))
- .andReturn(false)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6, CP11);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6.getSourceMAC());
- assertNull(ethernet);
-
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping to a gateway but one of the destination leaf is down
- @Test
- public void testPing4RemoteGatewayLeaf1Down() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(false)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV41, CP11);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV41.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV41.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV41.getSourceMAC()));
- assertThat(ethernet.getEtherType(), is(Ethernet.MPLS_UNICAST));
- assertTrue(ethernet.getPayload() instanceof MPLS);
- MPLS mpls = (MPLS) ethernet.getPayload();
- assertThat(mpls.getLabel(), is(LOCAL_LEAF2_SID4));
- assertTrue(mpls.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) mpls.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to a gateway but one of the destination leaf is down
- @Test
- public void testPing6RemoteGatewayLeaf2Down() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(false)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV61, CP11);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV61.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV61.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV61.getSourceMAC()));
- assertThat(ethernet.getEtherType(), is(Ethernet.MPLS_UNICAST));
- assertTrue(ethernet.getPayload() instanceof MPLS);
- MPLS mpls = (MPLS) ethernet.getPayload();
- assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID6));
- assertTrue(mpls.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) mpls.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to a link local address
- @Test
- public void testPing6LinkLocalAddress() {
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_LL, CP12);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LL.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LL.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LL.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_LL.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV6_LL.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- }
-
- // Ping to the looback of our leaf
- @Test
- public void testPing4Loopback() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK, CP12);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to the looback of our leaf
- @Test
- public void testPing6Loopback() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK, CP12);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping to the looback of our leaf (pair)
- @Test
- public void testPing4LoopbackPair() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2011);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to the looback of our leaf (pair)
- @Test
- public void testPing6LoopbackPair() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2021);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping to the loopback of the leaf but hashing of the bond interfaces sends to wrong leaf
- @Test
- public void testPing4LoopbackPairDifferentLeaf() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2021);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to the loopback of the leaf but hashing of the bond interfaces sends to wrong leaf
- @Test
- public void testPing6LoopbackPairDifferentLeaf() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2011);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping loopback of a destination that is down but
- // hashing of the bond interfaces sends to other leaf
- @Test
- public void testPing4LoopbackPairDifferentLeafDown() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(false)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2021);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 loopback of a destination that is down but
- // hashing of the bond interfaces sends to other leaf
- @Test
- public void testPing6LoopbackPairDifferentLeafDown() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(false)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2011);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping to a dh gateway
- @Test
- public void testPing4GatewayPair() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmp(ETH_REQ_IPV4_GATEWAY_PAIR, CP2011);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_GATEWAY_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_GATEWAY_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_GATEWAY_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv4);
- IPv4 ip = (IPv4) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV4_GATEWAY_PAIR.toInt()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
- assertTrue(ip.getPayload() instanceof ICMP);
- ICMP icmp = (ICMP) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
- assertThat(icmp.getIcmpCode(), is(CODE_ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
- // Ping6 to a dh gateway
- @Test
- public void testPing6GatewayPair() {
- // Expected behavior
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
- .andReturn(true)
- .times(1);
- expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
- .andReturn(true)
- .times(1);
- replay(segmentRoutingManager.deviceService);
-
- // Process
- icmpHandler.processIcmpv6(ETH_REQ_IPV6_GATEWAY_PAIR, CP2021);
-
- // Verify packet-out
- Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_GATEWAY_PAIR.getSourceMAC());
- assertNotNull(ethernet);
- assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_GATEWAY_PAIR.getDestinationMAC()));
- assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_GATEWAY_PAIR.getSourceMAC()));
- assertTrue(ethernet.getPayload() instanceof IPv6);
- IPv6 ip = (IPv6) ethernet.getPayload();
- assertThat(ip.getSourceAddress(), is(DST_IPV6_GATEWAY_PAIR.toOctets()));
- assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
- assertTrue(ip.getPayload() instanceof ICMP6);
- ICMP6 icmp = (ICMP6) ip.getPayload();
- assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
- // Verify behavior
- verify(segmentRoutingManager.deviceService);
- }
-
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java
deleted file mode 100644
index a90b1cf..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Mock Bridging Table Key.
- */
-class MockBridgingTableKey {
- DeviceId deviceId;
- MacAddress macAddress;
- VlanId vlanId;
-
- MockBridgingTableKey(DeviceId deviceId, MacAddress macAddress, VlanId vlanId) {
- this.deviceId = deviceId;
- this.macAddress = macAddress;
- this.vlanId = vlanId;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof MockBridgingTableKey)) {
- return false;
- }
- final MockBridgingTableKey other = (MockBridgingTableKey) obj;
- return Objects.equals(this.macAddress, other.macAddress) &&
- Objects.equals(this.deviceId, other.deviceId) &&
- Objects.equals(this.vlanId, other.vlanId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(macAddress, vlanId);
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java
deleted file mode 100644
index 68b0db8..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onosproject.net.PortNumber;
-
-import java.util.Objects;
-
-/**
- * Mock Bridging Table Value.
- */
-class MockBridgingTableValue {
- boolean popVlan;
- PortNumber portNumber;
-
- MockBridgingTableValue(boolean popVlan, PortNumber portNumber) {
- this.popVlan = popVlan;
- this.portNumber = portNumber;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof MockBridgingTableValue)) {
- return false;
- }
- final MockBridgingTableValue other = (MockBridgingTableValue) obj;
- return Objects.equals(this.popVlan, other.popVlan) &&
- Objects.equals(this.portNumber, other.portNumber);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(popVlan, portNumber);
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
deleted file mode 100644
index 0002948..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.IpPrefix;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Mock Default Routing Handler.
- */
-public class MockDefaultRoutingHandler extends DefaultRoutingHandler {
- private Map<ConnectPoint, Set<IpPrefix>> subnetTable;
- private Map<MockRoutingTableKey, MockRoutingTableValue> routingTable;
-
- MockDefaultRoutingHandler(SegmentRoutingManager srManager,
- Map<ConnectPoint, Set<IpPrefix>> subnetTable,
- Map<MockRoutingTableKey, MockRoutingTableValue> routingTable) {
- super(srManager);
- this.subnetTable = subnetTable;
- this.routingTable = routingTable;
- }
-
- @Override
- protected void populateSubnet(Set<ConnectPoint> cpts, Set<IpPrefix> subnets) {
- subnetTable.forEach((k, v) -> {
- if (!cpts.contains(k)) {
- subnetTable.get(k).removeAll(subnets);
- if (subnetTable.get(k).isEmpty()) {
- subnetTable.remove(k);
- }
- }
- });
-
- cpts.forEach(cpt -> subnetTable.put(cpt, subnets));
- }
-
- @Override
- protected boolean revokeSubnet(Set<IpPrefix> subnets) {
- for (Map.Entry<ConnectPoint, Set<IpPrefix>> entry : subnetTable.entrySet()) {
- entry.getValue().removeAll(subnets);
- if (entry.getValue().isEmpty()) {
- subnetTable.remove(entry.getKey());
- }
- }
- routingTable.entrySet().removeIf(e -> subnets.contains(e.getKey().ipPrefix));
- return true;
- }
-
- @Override
- protected boolean shouldProgram(DeviceId deviceId) {
- return true;
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDevice.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDevice.java
deleted file mode 100644
index 0abbf2a..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDevice.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import org.onosproject.net.Annotations;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.DeviceId;
-/**
- * Test fixture for the device service.
- */
-public class MockDevice extends DefaultDevice {
-
- public MockDevice(DeviceId id, Annotations annotations) {
- super(null, id, null, null, null, null, null, null, annotations);
- }
- }
-
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDeviceService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDeviceService.java
deleted file mode 100644
index 1d173f6..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockDeviceService.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Port;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceServiceAdapter;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-
-/**
- * Test fixture for the device service.
- */
-public class MockDeviceService extends DeviceServiceAdapter {
- private List<Device> devices = new LinkedList<>();
- private DeviceListener listener;
-
- public void addDevice(Device dev) {
- devices.add(dev);
- }
-
- public void addMultipleDevices(Set<Device> devicesToAdd) {
- devicesToAdd.forEach(dev -> devices.add(dev));
- }
-
- @Override
- public Device getDevice(DeviceId deviceId) {
- for (Device dev : devices) {
- if (dev.id().equals(deviceId)) {
- return dev;
- }
- }
- return null;
- }
-
- @Override
- public Port getPort(ConnectPoint cp) {
- return new DefaultPort(null, null, false);
- }
-
- @Override
- public Iterable<Device> getAvailableDevices() {
- return devices;
- }
-
- @Override
- public void addListener(DeviceListener listener) {
- this.listener = listener;
- }
-
- /**
- * Get the listener.
- */
- public DeviceListener getListener() {
- return listener;
- }
-
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java
deleted file mode 100644
index 0f2d7a9..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.Objective;
-import org.onosproject.net.flowobjective.ObjectiveError;
-
-import java.util.Map;
-
-/**
- * Mock Flow Objective Service.
- */
-public class MockFlowObjectiveService extends FlowObjectiveServiceAdapter {
- private Map<MockBridgingTableKey, MockBridgingTableValue> bridgingTable;
- private Map<Integer, TrafficTreatment> nextTable;
-
- MockFlowObjectiveService(Map<MockBridgingTableKey, MockBridgingTableValue> bridgingTable,
- Map<Integer, TrafficTreatment> nextTable) {
- this.bridgingTable = bridgingTable;
- this.nextTable = nextTable;
- }
-
- @Override
- public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
- TrafficSelector selector = forwardingObjective.selector();
- TrafficTreatment treatment = nextTable.get(forwardingObjective.nextId());
- MacAddress macAddress = ((EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST)).mac();
- VlanId vlanId = ((VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID)).vlanId();
-
- boolean popVlan = treatment.allInstructions().stream()
- .filter(instruction -> instruction.type().equals(Instruction.Type.L2MODIFICATION))
- .anyMatch(instruction -> ((L2ModificationInstruction) instruction).subtype()
- .equals(L2ModificationInstruction.L2SubType.VLAN_POP));
- PortNumber portNumber = treatment.allInstructions().stream()
- .filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT))
- .map(instruction -> ((Instructions.OutputInstruction) instruction).port()).findFirst().orElse(null);
- if (portNumber == null) {
- throw new IllegalArgumentException();
- }
-
- Objective.Operation op = forwardingObjective.op();
-
- MockBridgingTableKey btKey = new MockBridgingTableKey(deviceId, macAddress, vlanId);
- MockBridgingTableValue btValue = new MockBridgingTableValue(popVlan, portNumber);
-
- if (op.equals(Objective.Operation.ADD)) {
- bridgingTable.put(btKey, btValue);
- forwardingObjective.context().ifPresent(context -> context.onSuccess(forwardingObjective));
- } else if (op.equals(Objective.Operation.REMOVE)) {
- bridgingTable.remove(btKey, btValue);
- forwardingObjective.context().ifPresent(context -> context.onSuccess(forwardingObjective));
- } else {
- forwardingObjective.context().ifPresent(context ->
- context.onError(forwardingObjective, ObjectiveError.UNKNOWN));
- throw new IllegalArgumentException();
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostProbingService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostProbingService.java
deleted file mode 100644
index 807db0c..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostProbingService.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Lists;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-import org.onosproject.net.host.HostProbingService;
-import org.onosproject.net.host.ProbeMode;
-
-import java.util.List;
-import java.util.Objects;
-
-public class MockHostProbingService implements HostProbingService {
- List<Probe> probes;
-
- private class Probe {
- private Host host;
- private ConnectPoint connectPoint;
- private ProbeMode probeMode;
-
- Probe(Host host, ConnectPoint connectPoint, ProbeMode probeMode) {
- this.host = host;
- this.connectPoint = connectPoint;
- this.probeMode = probeMode;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof Probe)) {
- return false;
- }
- Probe that = (Probe) o;
- return (Objects.equals(this.host, that.host) &&
- Objects.equals(this.connectPoint, that.connectPoint) &&
- Objects.equals(this.probeMode, that.probeMode));
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(host, connectPoint, probeMode);
- }
- }
-
- MockHostProbingService() {
- probes = Lists.newArrayList();
- }
-
- boolean verifyProbe(Host host, ConnectPoint connectPoint, ProbeMode probeMode) {
- Probe probe = new Probe(host, connectPoint, probeMode);
- return probes.contains(probe);
- }
-
- @Override
- public void probeHost(Host host, ConnectPoint connectPoint, ProbeMode probeMode) {
- probes.add(new Probe(host, connectPoint, probeMode));
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostService.java
deleted file mode 100644
index e8c4701..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockHostService.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.host.HostServiceAdapter;
-
-import java.util.Set;
-
-/**
- * Mock Host Service.
- */
-public class MockHostService extends HostServiceAdapter {
- private Set<Host> hosts;
-
- MockHostService(Set<Host> hosts) {
- this.hosts = ImmutableSet.copyOf(hosts);
- }
-
- @Override
- public Set<Host> getHosts() {
- return hosts;
- }
-
- @Override
- public Host getHost(HostId hostId) {
- return hosts.stream().filter(host -> hostId.equals(host.id())).findFirst().orElse(null);
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java
deleted file mode 100644
index 6e170b0..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.impl.InterfaceManager;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.util.stream.Collectors.toSet;
-
-/**
- * Mock Interface Service.
- */
-public class MockInterfaceService extends InterfaceManager {
- private Set<Interface> interfaces;
-
- MockInterfaceService(Set<Interface> interfaces) {
- this.interfaces = ImmutableSet.copyOf(interfaces);
- }
-
- @Override
- public Set<Interface> getInterfacesByPort(ConnectPoint cp) {
- return interfaces.stream().filter(intf -> cp.equals(intf.connectPoint()))
- .collect(Collectors.toSet());
- }
-
- @Override
- public Set<Interface> getInterfaces() {
- return interfaces;
- }
-
- @Override
- public Interface getMatchingInterface(IpAddress ip) {
- return getMatchingInterfacesStream(ip).findFirst().orElse(null);
- }
-
- @Override
- public Set<Interface> getMatchingInterfaces(IpAddress ip) {
- return getMatchingInterfacesStream(ip).collect(toSet());
- }
-
- private Stream<Interface> getMatchingInterfacesStream(IpAddress ip) {
- return interfaces.stream()
- .filter(intf -> intf.ipAddressesList().stream()
- .anyMatch(intfIp -> intfIp.subnetAddress().contains(ip)));
- }
-
- @Override
- public boolean isConfigured(ConnectPoint connectPoint) {
- Set<Interface> intfs = getInterfacesByPort(connectPoint);
- if (intfs == null) {
- return false;
- }
- for (Interface intf : intfs) {
- if (!intf.ipAddressesList().isEmpty() || intf.vlan() != VlanId.NONE
- || intf.vlanNative() != VlanId.NONE
- || intf.vlanUntagged() != VlanId.NONE
- || !intf.vlanTagged().isEmpty()) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
deleted file mode 100644
index fe5df5d..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onosproject.net.HostLocation;
-
-/**
- * Mocks the LinkHandler in SR.
- *
- */
-public class MockLinkHandler extends LinkHandler {
-
- MockLinkHandler(SegmentRoutingManager srManager) {
- super(srManager, null);
- }
-
- @Override
- void checkUplinksForHost(HostLocation loc) {
- // currently does nothing - can be extended to be a useful mock when
- // implementing unit tests for link handling
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java
deleted file mode 100644
index 5494e27..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.mastership.MastershipServiceAdapter;
-import org.onosproject.net.DeviceId;
-
-import java.util.Set;
-
-/**
- * Mock Mastership Service.
- */
-public class MockMastershipService extends MastershipServiceAdapter {
- // A set of devices of which we have mastership.
- private Set<DeviceId> localDevices;
-
- MockMastershipService(Set<DeviceId> localDevices) {
- this.localDevices = ImmutableSet.copyOf(localDevices);
- }
-
- @Override
- public boolean isLocalMaster(DeviceId deviceId) {
- return localDevices.contains(deviceId);
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNeighbourResolutionService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNeighbourResolutionService.java
deleted file mode 100644
index 5a41149..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNeighbourResolutionService.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.neighbour.NeighbourHandlerRegistration;
-import org.onosproject.net.neighbour.NeighbourMessageHandler;
-import org.onosproject.net.neighbour.NeighbourResolutionService;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Mock Neighbour Resolution Service.
- */
-public class MockNeighbourResolutionService implements NeighbourResolutionService {
- @Override
- public void registerNeighbourHandler(ConnectPoint connectPoint,
- NeighbourMessageHandler handler, ApplicationId appId) {
-
- }
-
- @Override
- public void registerNeighbourHandler(Interface intf,
- NeighbourMessageHandler handler, ApplicationId appId) {
-
- }
-
- @Override
- public void unregisterNeighbourHandler(ConnectPoint connectPoint,
- NeighbourMessageHandler handler, ApplicationId appId) {
-
- }
-
- @Override
- public void unregisterNeighbourHandler(Interface intf,
- NeighbourMessageHandler handler, ApplicationId appId) {
-
- }
-
- @Override
- public void unregisterNeighbourHandlers(ApplicationId appId) {
-
- }
-
- @Override
- public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
- return null;
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java
deleted file mode 100644
index 12d57ea..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Mock Network Config Registry.
- */
-class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
- private Set<Config> configs = Sets.newHashSet();
-
- void applyConfig(Config config) {
- configs.add(config);
- }
-
- @Override
- public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
- Config c = configs.stream()
- .filter(config -> subject.equals(config.subject()))
- .filter(config -> configClass.equals(config.getClass()))
- .findFirst().orElse(null);
- return (C) c;
- }
-
- @Override
- public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
- Config c = configs.stream()
- .filter(config -> subject.equals(config.subject()))
- .filter(config -> configClass.equals(config.getClass()))
- .findFirst().orElseGet(() -> {
- if (configClass.equals(BasicDeviceConfig.class)) {
- BasicDeviceConfig deviceConfig = new BasicDeviceConfig();
- ObjectMapper mapper = new ObjectMapper();
- deviceConfig.init((DeviceId) subject, ((DeviceId) subject).toString(),
- JsonNodeFactory.instance.objectNode(), mapper, config -> {
- });
- return deviceConfig;
- }
- return null;
- });
- return (C) c;
- }
-
- @Override
- public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subject, Class<C> configClass) {
- ImmutableSet.Builder<S> builder = ImmutableSet.builder();
- String cName = configClass.getName();
- configs.forEach(k -> {
- if (subject.isInstance(k.subject()) && Objects.equals(cName, k.getClass().getName())) {
- builder.add((S) k.subject());
- }
- });
- return builder.build();
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockPacketService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockPacketService.java
deleted file mode 100644
index 73a8b65..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockPacketService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Maps;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.packet.DeserializationException;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.net.packet.PacketServiceAdapter;
-
-import java.util.Map;
-
-/**
- * Mock Packet Service.
- * It is used for tests related to packet-ins management.
- */
-public class MockPacketService extends PacketServiceAdapter {
-
- private final Map<MacAddress, Pair<OutboundPacket, Ethernet>> outBoundPackets = Maps.newHashMap();
-
- @Override
- public void emit(OutboundPacket packet) {
- try {
- Ethernet ethernetPacket = Ethernet.deserializer().deserialize(packet.data().array(),
- packet.data().arrayOffset(),
- packet.data().array().length);
- outBoundPackets.put(ethernetPacket.getDestinationMAC(), Pair.of(packet, ethernetPacket));
- } catch (DeserializationException e) {
-
- }
- }
-
- Ethernet getEthernetPacket(MacAddress key) {
- Pair<OutboundPacket, Ethernet> pair = outBoundPackets.get(key);
- return pair != null ? pair.getRight() : null;
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRouteService.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRouteService.java
deleted file mode 100644
index c3730dd..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRouteService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Sets;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteInfo;
-import org.onosproject.routeservice.RouteServiceAdapter;
-import org.onosproject.routeservice.RouteTableId;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Mock Route Service.
- * We assume there is only one routing table named "default".
- */
-public class MockRouteService extends RouteServiceAdapter {
- private Map<IpPrefix, Set<ResolvedRoute>> routeStore;
-
- MockRouteService(Map<IpPrefix, Set<ResolvedRoute>> routeStore) {
- this.routeStore = routeStore;
- }
-
- @Override
- public Collection<RouteInfo> getRoutes(RouteTableId id) {
- return routeStore.entrySet().stream().map(e -> {
- IpPrefix prefix = e.getKey();
- Set<ResolvedRoute> resolvedRoutes = e.getValue();
- ResolvedRoute bestRoute = resolvedRoutes.stream().findFirst().orElse(null);
- return new RouteInfo(prefix, bestRoute, resolvedRoutes);
- }).collect(Collectors.toSet());
- }
-
- @Override
- public Collection<RouteTableId> getRouteTables() {
- return Sets.newHashSet(new RouteTableId("default"));
- }
-
- @Override
- public Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip) {
- return this.routeStore.get(ip.toIpPrefix()).stream()
- .findFirst();
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java
deleted file mode 100644
index 4d222d8..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flowobjective.Objective;
-
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-/**
- * Mock Routing Rule Populator.
- */
-public class MockRoutingRulePopulator extends RoutingRulePopulator {
- private Map<MockRoutingTableKey, MockRoutingTableValue> routingTable;
-
- MockRoutingRulePopulator(SegmentRoutingManager srManager,
- Map<MockRoutingTableKey, MockRoutingTableValue> routingTable) {
- super(srManager);
- this.routingTable = routingTable;
- }
-
- @Override
- public CompletableFuture<Objective> populateRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
- VlanId hostVlanId, PortNumber outPort, boolean directHost) {
- MockRoutingTableKey rtKey = new MockRoutingTableKey(deviceId, prefix);
- MockRoutingTableValue rtValue = new MockRoutingTableValue(outPort, hostMac, hostVlanId);
- routingTable.put(rtKey, rtValue);
- return CompletableFuture.completedFuture(null);
- }
-
- @Override
- public CompletableFuture<Objective> revokeRoute(DeviceId deviceId, IpPrefix prefix,
- MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
- MockRoutingTableKey rtKey = new MockRoutingTableKey(deviceId, prefix);
- MockRoutingTableValue rtValue = new MockRoutingTableValue(outPort, hostMac, hostVlanId);
- routingTable.remove(rtKey, rtValue);
- return CompletableFuture.completedFuture(null);
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java
deleted file mode 100644
index 4f09c2a..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.IpPrefix;
-import org.onosproject.net.DeviceId;
-
-import java.util.Objects;
-
-/**
- * Mock Routing Table Key.
- */
-class MockRoutingTableKey {
- DeviceId deviceId;
- IpPrefix ipPrefix;
-
- MockRoutingTableKey(DeviceId deviceId, IpPrefix ipPrefix) {
- this.deviceId = deviceId;
- this.ipPrefix = ipPrefix;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof MockRoutingTableKey)) {
- return false;
- }
- final MockRoutingTableKey other = (MockRoutingTableKey) obj;
- return Objects.equals(this.deviceId, other.deviceId) &&
- Objects.equals(this.ipPrefix, other.ipPrefix);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(deviceId, ipPrefix);
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java
deleted file mode 100644
index 5842d2d..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.PortNumber;
-
-import java.util.Objects;
-
-/**
- * Mock Routing Table Value.
- */
-class MockRoutingTableValue {
- PortNumber portNumber;
- MacAddress macAddress;
- VlanId vlanId;
-
- MockRoutingTableValue(PortNumber portNumber, MacAddress macAddress, VlanId vlanId) {
- this.portNumber = portNumber;
- this.macAddress = macAddress;
- this.vlanId = vlanId;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof MockRoutingTableValue)) {
- return false;
- }
- final MockRoutingTableValue other = (MockRoutingTableValue) obj;
- return Objects.equals(this.portNumber, other.portNumber) &&
- Objects.equals(this.macAddress, other.macAddress) &&
- Objects.equals(this.vlanId, other.vlanId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(portNumber, macAddress, vlanId);
- }
-}
-
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java
deleted file mode 100644
index ad098b4..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import org.onosproject.core.DefaultApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Mock Segment Routing Manager.
- */
-public class MockSegmentRoutingManager extends SegmentRoutingManager {
- private Map<Integer, TrafficTreatment> nextTable;
- private AtomicInteger atomicNextId = new AtomicInteger();
-
- MockSegmentRoutingManager(Map<Integer, TrafficTreatment> nextTable) {
- appId = new DefaultApplicationId(1, SegmentRoutingManager.APP_NAME);
- this.nextTable = nextTable;
- }
-
- @Override
- public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
- TrafficTreatment treatment,
- TrafficSelector meta,
- boolean createIfMissing) {
- int nextId = atomicNextId.incrementAndGet();
- nextTable.put(nextId, treatment);
- return nextId;
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PortAuthTrackerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PortAuthTrackerTest.java
deleted file mode 100644
index 6ab4bad..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PortAuthTrackerTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.DefaultApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.segmentrouting.PortAuthTracker.BlockState;
-import org.onosproject.segmentrouting.config.BlockedPortsConfig;
-import org.onosproject.segmentrouting.config.BlockedPortsConfigTest;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.onosproject.net.ConnectPoint.deviceConnectPoint;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.onosproject.segmentrouting.PortAuthTracker.BlockState.AUTHENTICATED;
-import static org.onosproject.segmentrouting.PortAuthTracker.BlockState.BLOCKED;
-import static org.onosproject.segmentrouting.PortAuthTracker.BlockState.UNCHECKED;
-
-/**
- * Unit Tests for {@link PortAuthTracker}.
- */
-public class PortAuthTrackerTest {
- private static final ApplicationId APP_ID = new DefaultApplicationId(1, "foo");
- private static final String KEY = "blocked";
- private static final ObjectMapper MAPPER = new ObjectMapper();
- private static final String PATH_CFG = "/blocked-ports.json";
- private static final String PATH_CFG_ALT = "/blocked-ports-alt.json";
-
- private static final String DEV1 = "of:0000000000000001";
- private static final String DEV3 = "of:0000000000000003";
- private static final String DEV4 = "of:0000000000000004";
-
- private BlockedPortsConfig cfg;
- private AugmentedPortAuthTracker tracker;
-
- private void print(String s) {
- System.out.println(s);
- }
-
- private void print(Object o) {
- print(o.toString());
- }
-
- private void print(String fmt, Object... params) {
- print(String.format(fmt, params));
- }
-
- private void title(String s) {
- print("=== %s ===", s);
- }
-
- private BlockedPortsConfig makeConfig(String path) throws IOException {
- InputStream blockedPortsJson = BlockedPortsConfigTest.class
- .getResourceAsStream(path);
- JsonNode node = MAPPER.readTree(blockedPortsJson);
- BlockedPortsConfig cfg = new BlockedPortsConfig();
- cfg.init(APP_ID, KEY, node, MAPPER, null);
- return cfg;
- }
-
- ConnectPoint cp(String devId, int port) {
- return ConnectPoint.deviceConnectPoint(devId + "/" + port);
- }
-
- @Before
- public void setUp() throws IOException {
- cfg = makeConfig(PATH_CFG);
- tracker = new AugmentedPortAuthTracker();
- }
-
- private void verifyPortState(String devId, int first, BlockState... states) {
- DeviceId dev = deviceId(devId);
- int last = first + states.length;
- int pn = first;
- int i = 0;
- while (pn < last) {
- PortNumber pnum = portNumber(pn);
- BlockState actual = tracker.currentState(dev, pnum);
- print("%s/%s [%s] --> %s", devId, pn, states[i], actual);
- assertEquals("oops: " + devId + "/" + pn + "~" + actual,
- states[i], actual);
- pn++;
- i++;
- }
- }
-
- @Test
- public void basic() {
- title("basic");
- print(tracker);
- print(cfg);
-
- assertEquals("wrong entry count", 0, tracker.entryCount());
-
- // let's assume that the net config just got loaded..
- tracker.configurePortBlocking(cfg);
- assertEquals("wrong entry count", 13, tracker.entryCount());
-
- verifyPortState(DEV1, 1, BLOCKED, BLOCKED, BLOCKED, BLOCKED, UNCHECKED);
- verifyPortState(DEV1, 6, UNCHECKED, BLOCKED, BLOCKED, BLOCKED, UNCHECKED);
-
- verifyPortState(DEV3, 1, UNCHECKED, UNCHECKED, UNCHECKED);
- verifyPortState(DEV3, 6, UNCHECKED, BLOCKED, BLOCKED, BLOCKED, UNCHECKED);
-
- verifyPortState(DEV4, 1, BLOCKED, UNCHECKED, UNCHECKED, UNCHECKED, BLOCKED);
- }
-
- @Test
- public void logonLogoff() {
- title("logonLogoff");
-
- tracker.configurePortBlocking(cfg);
- assertEquals("wrong entry count", 13, tracker.entryCount());
- verifyPortState(DEV1, 1, BLOCKED, BLOCKED, BLOCKED);
-
- ConnectPoint cp = deviceConnectPoint(DEV1 + "/2");
- tracker.radiusAuthorize(cp);
- print("");
- verifyPortState(DEV1, 1, BLOCKED, AUTHENTICATED, BLOCKED);
-
- tracker.radiusLogoff(cp);
- print("");
- verifyPortState(DEV1, 1, BLOCKED, BLOCKED, BLOCKED);
- }
-
- @Test
- public void installedFlows() {
- title("installed flows");
-
- assertEquals(0, tracker.installed.size());
- tracker.configurePortBlocking(cfg);
- assertEquals(13, tracker.installed.size());
-
- assertTrue(tracker.installed.contains(cp(DEV1, 1)));
- assertTrue(tracker.installed.contains(cp(DEV3, 7)));
- assertTrue(tracker.installed.contains(cp(DEV4, 5)));
- }
-
- @Test
- public void flowsLogonLogoff() {
- title("flows logon logoff");
-
- tracker.configurePortBlocking(cfg);
-
- // let's pick a connect point from the configuration
- ConnectPoint cp = cp(DEV4, 5);
-
- assertTrue(tracker.installed.contains(cp));
- assertEquals(0, tracker.cleared.size());
-
- tracker.resetMetrics();
- tracker.radiusAuthorize(cp);
- // verify we requested the blocking flow to be cleared
- assertTrue(tracker.cleared.contains(cp));
-
- tracker.resetMetrics();
- assertEquals(0, tracker.installed.size());
- tracker.radiusLogoff(cp);
- // verify we requested the blocking flow to be reinstated
- assertTrue(tracker.installed.contains(cp));
- }
-
- @Test
- public void uncheckedPortIgnored() {
- title("unchecked port ignored");
-
- tracker.configurePortBlocking(cfg);
- tracker.resetMetrics();
-
- // let's pick a connect point NOT in the configuration
- ConnectPoint cp = cp(DEV4, 2);
- assertEquals(BlockState.UNCHECKED, tracker.currentState(cp));
-
- assertEquals(0, tracker.installed.size());
- assertEquals(0, tracker.cleared.size());
- tracker.radiusAuthorize(cp);
- assertEquals(0, tracker.installed.size());
- assertEquals(0, tracker.cleared.size());
- tracker.radiusLogoff(cp);
- assertEquals(0, tracker.installed.size());
- assertEquals(0, tracker.cleared.size());
- }
-
- @Test
- public void reconfiguration() throws IOException {
- title("reconfiguration");
-
- /* see 'blocked-ports.json' and 'blocked-ports-alt.json'
-
- cfg: "1": ["1-4", "7-9"],
- "3": ["7-9"],
- "4": ["1", "5", "9"]
-
- alt: "1": ["1-9"],
- "3": ["7"],
- "4": ["1"]
- */
- tracker.configurePortBlocking(cfg);
- // dev1: ports 5 and 6 are NOT configured in the original CFG
- assertFalse(tracker.installed.contains(cp(DEV1, 5)));
- assertFalse(tracker.installed.contains(cp(DEV1, 6)));
-
- tracker.resetMetrics();
- assertEquals(0, tracker.installed.size());
- assertEquals(0, tracker.cleared.size());
-
- BlockedPortsConfig alt = makeConfig(PATH_CFG_ALT);
- tracker.configurePortBlocking(alt);
-
- // dev1: ports 5 and 6 ARE configured in the alternate CFG
- assertTrue(tracker.installed.contains(cp(DEV1, 5)));
- assertTrue(tracker.installed.contains(cp(DEV1, 6)));
-
- // also, check for the ports that were decommissioned
- assertTrue(tracker.cleared.contains(cp(DEV3, 8)));
- assertTrue(tracker.cleared.contains(cp(DEV3, 9)));
- assertTrue(tracker.cleared.contains(cp(DEV4, 5)));
- assertTrue(tracker.cleared.contains(cp(DEV4, 9)));
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
deleted file mode 100644
index f2a439b..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onosproject.routeservice.RouteEvent;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.segmentrouting.phasedrecovery.api.PhasedRecoveryService;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.TestConsistentMap;
-import org.onosproject.store.service.TestConsistentMultimap;
-
-import java.util.Map;
-import java.util.Set;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.reset;
-import static org.junit.Assert.*;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-/**
- * Unit test for {@link RouteHandler}.
- */
-public class RouteHandlerTest {
- private SegmentRoutingManager srManager;
- private RouteHandler routeHandler;
- private HostService hostService;
-
- // Mocked routing and bridging tables
- private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
- Maps.newConcurrentMap();
- private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
- Maps.newConcurrentMap();
- private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
- // Mocked Next Id
- private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
- private static final Map<IpPrefix, Set<ResolvedRoute>> ROUTE_STORE = Maps.newConcurrentMap();
-
- private static final IpPrefix P1 = IpPrefix.valueOf("10.0.0.0/24");
-
- // Single homed router 1
- private static final IpAddress N1 = IpAddress.valueOf("10.0.1.1");
- private static final MacAddress M1 = MacAddress.valueOf("00:00:00:00:00:01");
- private static final VlanId V1 = VlanId.vlanId((short) 1);
- private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
- private static final Route R1 = new Route(Route.Source.STATIC, P1, N1);
- private static final ResolvedRoute RR1 = new ResolvedRoute(R1, M1, V1);
- private static final Route DHCP_R1 = new Route(Route.Source.DHCP, P1, N1);
- private static final ResolvedRoute DHCP_RR1 = new ResolvedRoute(DHCP_R1, M1, V1);
-
- // Single homed router 2
- private static final IpAddress N2 = IpAddress.valueOf("10.0.2.1");
- private static final MacAddress M2 = MacAddress.valueOf("00:00:00:00:00:02");
- private static final VlanId V2 = VlanId.vlanId((short) 2);
- private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000002/2");
- private static final Route R2 = new Route(Route.Source.STATIC, P1, N2);
- private static final ResolvedRoute RR2 = new ResolvedRoute(R2, M2, V2);
-
- // Dual homed router 1
- private static final IpAddress N3 = IpAddress.valueOf("10.0.3.1");
- private static final MacAddress M3 = MacAddress.valueOf("00:00:00:00:00:03");
- private static final VlanId V3 = VlanId.vlanId((short) 3);
- private static final Route R3 = new Route(Route.Source.STATIC, P1, N3);
- private static final ResolvedRoute RR3 = new ResolvedRoute(R3, M3, V3);
- private static final Route DHCP_R3 = new Route(Route.Source.DHCP, P1, N3);
- private static final ResolvedRoute DHCP_RR3 = new ResolvedRoute(DHCP_R3, M3, V3);
-
- // Single homed router 3
- private static final IpAddress N4 = IpAddress.valueOf("10.0.4.1");
- private static final MacAddress M4 = MacAddress.valueOf("00:00:00:00:00:04");
- private static final VlanId V4 = VlanId.vlanId((short) 4);
- private static final ConnectPoint CP4 = ConnectPoint.deviceConnectPoint("of:0000000000000004/4");
- private static final Route R4 = new Route(Route.Source.STATIC, P1, N4);
- private static final ResolvedRoute RR4 = new ResolvedRoute(R4, M4, V4);
-
- // Hosts
- private static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(M1, V1), M1, V1,
- Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N1), false);
- private static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(M2, V2), M2, V2,
- Sets.newHashSet(new HostLocation(CP2, 0)), Sets.newHashSet(N2), false);
- private static final Host H3D = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
- Sets.newHashSet(new HostLocation(CP1, 0), new HostLocation(CP2, 0)), Sets.newHashSet(N3), false);
- private static final Host H3S = new DefaultHost(ProviderId.NONE, HostId.hostId(M3, V3), M3, V3,
- Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N3), false);
- private static final Host H4 = new DefaultHost(ProviderId.NONE, HostId.hostId(M4, V4), M4, V4,
- Sets.newHashSet(new HostLocation(CP4, 0)), Sets.newHashSet(N4), false);
-
- // Pair Local Port
- private static final PortNumber P9 = PortNumber.portNumber(9);
-
- // A set of hosts
- private static final Set<Host> HOSTS = Sets.newHashSet(H1, H2, H3D, H4);
- private static final Set<Host> HOSTS_ONE_FAIL = Sets.newHashSet(H1, H2, H3S);
- private static final Set<Host> HOSTS_BOTH_FAIL = Sets.newHashSet(H1, H2);
- // A set of devices of which we have mastership
- private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(CP1.deviceId(), CP2.deviceId());
- // A set of interfaces
- private static final InterfaceIpAddress IF_IP1 =
- new InterfaceIpAddress(IpAddress.valueOf("10.0.1.254"), IpPrefix.valueOf("10.0.1.254/24"));
- private static final InterfaceIpAddress IF_IP3 =
- new InterfaceIpAddress(IpAddress.valueOf("10.0.3.254"), IpPrefix.valueOf("10.0.3.254/24"));
- private static final Interface IF_CP1 = new Interface("if-cp1", CP1, Lists.newArrayList(IF_IP1, IF_IP3),
- null, null, null, null, null);
- private static final Interface IF_CP2 = new Interface("if-cp2", CP2, Lists.newArrayList(IF_IP1, IF_IP3),
- null, null, null, null, null);
- private static final Set<Interface> INTERFACES = Sets.newHashSet(IF_CP1, IF_CP2);
-
- @Before
- public void setUp() {
- ObjectMapper mapper = new ObjectMapper();
- ConfigApplyDelegate delegate = config -> { };
-
- SegmentRoutingDeviceConfig dev1Config = new SegmentRoutingDeviceConfig();
- JsonNode dev1Tree = mapper.createObjectNode();
- dev1Config.init(CP1.deviceId(), "host-handler-test", dev1Tree, mapper, delegate);
- dev1Config.setPairDeviceId(CP2.deviceId()).setPairLocalPort(P9);
-
- SegmentRoutingDeviceConfig dev2Config = new SegmentRoutingDeviceConfig();
- JsonNode dev2Tree = mapper.createObjectNode();
- dev2Config.init(CP2.deviceId(), "host-handler-test", dev2Tree, mapper, delegate);
- dev2Config.setPairDeviceId(CP1.deviceId()).setPairLocalPort(P9);
-
- MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
- mockNetworkConfigRegistry.applyConfig(dev1Config);
- mockNetworkConfigRegistry.applyConfig(dev2Config);
-
- // Initialize Segment Routing Manager
- srManager = new MockSegmentRoutingManager(NEXT_TABLE);
- srManager.storageService = createMock(StorageService.class);
- expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
- expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
- new TestConsistentMultimap.Builder<>()).anyTimes();
- replay(srManager.storageService);
- srManager.cfgService = new NetworkConfigRegistryAdapter();
- srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
- srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
- srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
- srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
- srManager.interfaceService = new MockInterfaceService(INTERFACES);
- srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
- hostService = new MockHostService(HOSTS);
- srManager.hostService = hostService;
- srManager.cfgService = mockNetworkConfigRegistry;
- srManager.routeService = new MockRouteService(ROUTE_STORE);
- srManager.phasedRecoveryService = createMock(PhasedRecoveryService.class);
- expect(srManager.phasedRecoveryService.isEnabled()).andReturn(true).anyTimes();
- replay(srManager.phasedRecoveryService);
-
- routeHandler = new RouteHandler(srManager);
-
- ROUTING_TABLE.clear();
- BRIDGING_TABLE.clear();
- SUBNET_TABLE.clear();
- }
-
- @Test
- public void init() {
- ROUTE_STORE.put(P1, Sets.newHashSet(RR1));
-
- routeHandler.init(CP1.deviceId());
-
- assertEquals(1, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
-
- assertEquals(1, SUBNET_TABLE.size());
- }
-
- @Test
- public void initTwoNextHops() {
- ROUTE_STORE.put(P1, Sets.newHashSet(RR1, RR2));
-
- routeHandler.init(CP1.deviceId());
-
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M2, rtv2.macAddress);
- assertEquals(V2, rtv2.vlanId);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- }
-
- // Only one of two dual-homed next hops present.
- // Expect one routing table to be programmed with direct flow.
- // The other is not programmed, not even for subnet
- @Test
- public void initDhcpRouteSingleDualHomeNextHop() {
- ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR1));
-
- routeHandler.init(CP1.deviceId());
-
- assertEquals(1, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
-
- assertEquals(1, SUBNET_TABLE.size());
- }
-
- // Both dual-homed next hops present.
- // Expect both routing table to be programmed with direct flow
- @Test
- public void initDhcpRouteBothDualHomeNextHop() {
- ROUTE_STORE.put(P1, Sets.newHashSet(DHCP_RR3));
-
- routeHandler.init(CP1.deviceId());
-
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M3, rtv1.macAddress);
- assertEquals(V3, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
-
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M3, rtv2.macAddress);
- assertEquals(V3, rtv2.vlanId);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- }
-
- @Test
- public void processRouteAdded() {
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.addSubnet(CP1, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1));
- routeHandler.processRouteAdded(re);
-
- assertEquals(1, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
-
- assertEquals(1, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void processRouteUpdated() {
- processRouteAdded();
-
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.removeSubnet(CP1, P1);
- expectLastCall().once();
- srManager.deviceConfiguration.addSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, RR2, RR1, Sets.newHashSet(RR2),
- Sets.newHashSet(RR1));
- routeHandler.processRouteUpdated(re);
-
- // Note: We shouldn't remove the old nexthop during the occasion of route update
- // since the populate subnet will take care of it and point it to an ECMP group
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M2, rtv2.macAddress);
- assertEquals(V2, rtv2.vlanId);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(1, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void processRouteRemoved() {
- processRouteAdded();
-
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.removeSubnet(CP1, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1));
- routeHandler.processRouteRemoved(re);
-
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, SUBNET_TABLE.size());
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testTwoSingleHomedAdded() {
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.addSubnet(CP1, P1);
- expectLastCall().once();
- srManager.deviceConfiguration.addSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
- routeHandler.processRouteAdded(re);
-
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(M2, rtv2.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(V2, rtv2.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testOneDualHomedAdded() {
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.addSubnet(CP1, P1);
- expectLastCall().once();
- srManager.deviceConfiguration.addSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR3, Sets.newHashSet(RR3));
- routeHandler.processRouteAdded(re);
-
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M3, rtv1.macAddress);
- assertEquals(M3, rtv2.macAddress);
- assertEquals(V3, rtv1.vlanId);
- assertEquals(V3, rtv2.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testOneSingleHomedToTwoSingleHomed() {
- processRouteAdded();
-
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.addSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
- Sets.newHashSet(RR1, RR2), Sets.newHashSet(RR1));
- routeHandler.processAlternativeRoutesChanged(re);
-
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(M2, rtv2.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(V2, rtv2.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testTwoSingleHomedToOneSingleHomed() {
- testTwoSingleHomedAdded();
-
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.removeSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
- Sets.newHashSet(RR1), Sets.newHashSet(RR1, RR2));
- routeHandler.processAlternativeRoutesChanged(re);
-
- // Note: We shouldn't remove the old nexthop during the occasion of route update
- // since the populate subnet will take care of it and point it to an ECMP group
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
-
- assertEquals(1, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- // TODO Add test cases for two single homed next hop at same location
-
- @Test
- public void testDualHomedSingleLocationFail() {
- testOneDualHomedAdded();
-
- ROUTE_STORE.put(P1, Sets.newHashSet(RR3));
-
- reset(srManager.deviceConfiguration);
- expect(srManager.deviceConfiguration.getBatchedSubnets(H3D.id()))
- .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
- srManager.deviceConfiguration.removeSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3S, H3D);
- routeHandler.processHostMovedEvent(he);
-
- // We do not remove the route on CP2. Instead, we let the subnet population overrides it
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M3, rtv1.macAddress);
- assertEquals(V3, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
-
- // ECMP route table hasn't changed
- assertEquals(1, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testDualHomedBothLocationFail() {
- testDualHomedSingleLocationFail();
-
- hostService = new MockHostService(HOSTS_ONE_FAIL);
-
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.removeSubnet(CP1, P1);
- expectLastCall().once();
- srManager.deviceConfiguration.removeSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
- routeHandler.processRouteRemoved(re);
-
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, SUBNET_TABLE.size());
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testSingleHomedToDualHomed() {
- testDualHomedSingleLocationFail();
-
- reset(srManager.deviceConfiguration);
- expect(srManager.deviceConfiguration.getBatchedSubnets(H3S.id()))
- .andReturn(Lists.<Set<IpPrefix>>newArrayList(Sets.newHashSet(P1)));
- srManager.deviceConfiguration.addSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- HostEvent he = new HostEvent(HostEvent.Type.HOST_MOVED, H3D, H3S);
- routeHandler.processHostMovedEvent(he);
-
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M3, rtv1.macAddress);
- assertEquals(M3, rtv2.macAddress);
- assertEquals(V3, rtv1.vlanId);
- assertEquals(V3, rtv2.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testTwoSingleHomedRemoved() {
- testTwoSingleHomedAdded();
-
- hostService = new MockHostService(HOSTS_BOTH_FAIL);
-
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.removeSubnet(CP1, P1);
- expectLastCall().once();
- srManager.deviceConfiguration.removeSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1, Sets.newHashSet(RR1, RR2));
- routeHandler.processRouteRemoved(re);
-
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, SUBNET_TABLE.size());
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testOneDualHomeRemoved() {
- testOneDualHomedAdded();
-
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.removeSubnet(CP1, P1);
- expectLastCall().once();
- srManager.deviceConfiguration.removeSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR3, Sets.newHashSet(RR3));
- routeHandler.processRouteRemoved(re);
-
- assertEquals(0, ROUTING_TABLE.size());
- assertEquals(0, SUBNET_TABLE.size());
-
- verify(srManager.deviceConfiguration);
- }
-
- @Test
- public void testMoreThanTwoNextHop() {
- // next hop = CP1, CP2
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.addSubnet(CP1, P1);
- srManager.deviceConfiguration.addSubnet(CP2, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1, Sets.newHashSet(RR1, RR2));
- routeHandler.processRouteAdded(re);
-
- assertEquals(2, ROUTING_TABLE.size());
- MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
- MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M2, rtv2.macAddress);
- assertEquals(V2, rtv2.vlanId);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
- verify(srManager.deviceConfiguration);
-
- // next hop = CP1, CP2, CP4 (invalid)
- re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
- Sets.newHashSet(RR1, RR2, RR4), Sets.newHashSet(RR1, RR2));
- routeHandler.processAlternativeRoutesChanged(re);
-
- assertEquals(2, ROUTING_TABLE.size());
- rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
- assertEquals(M1, rtv1.macAddress);
- assertEquals(V1, rtv1.vlanId);
- assertEquals(CP1.port(), rtv1.portNumber);
- rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M2, rtv2.macAddress);
- assertEquals(V2, rtv2.vlanId);
- assertEquals(CP2.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
-
- // next hop = CP2, CP4
- reset(srManager.deviceConfiguration);
- srManager.deviceConfiguration.addSubnet(CP2, P1);
- srManager.deviceConfiguration.addSubnet(CP4, P1);
- expectLastCall().once();
- replay(srManager.deviceConfiguration);
-
- re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
- Sets.newHashSet(RR2, RR4), Sets.newHashSet(RR1, RR2, RR4));
- routeHandler.processAlternativeRoutesChanged(re);
-
- assertEquals(2, ROUTING_TABLE.size());
- rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
- assertEquals(M2, rtv1.macAddress);
- assertEquals(V2, rtv1.vlanId);
- assertEquals(CP2.port(), rtv1.portNumber);
- rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1));
- assertEquals(M4, rtv2.macAddress);
- assertEquals(V4, rtv2.vlanId);
- assertEquals(CP4.port(), rtv2.portNumber);
-
- assertEquals(2, SUBNET_TABLE.size());
- assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
- assertTrue(SUBNET_TABLE.get(CP4).contains(P1));
-
- verify(srManager.deviceConfiguration);
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RoutingRulePopulatorTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RoutingRulePopulatorTest.java
deleted file mode 100644
index c8afeef..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/RoutingRulePopulatorTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.segmentrouting.config.DeviceConfiguration;
-
-import java.util.List;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.*;
-
-public class RoutingRulePopulatorTest {
- private RoutingRulePopulator rrp;
- private SegmentRoutingManager srManager;
- private InterfaceService interfaceService;
- private DeviceService deviceService;
-
- private final DeviceId devId1 = DeviceId.deviceId("of:1");
- private final Device dev1 = new DefaultDevice(ProviderId.NONE, devId1, Device.Type.SWITCH,
- null, null, null, null, null);
-
- private final PortNumber p1 = PortNumber.portNumber(1);
- private final PortNumber p2 = PortNumber.portNumber(2);
- private final PortNumber p3 = PortNumber.portNumber(3);
- private final PortNumber p4 = PortNumber.portNumber(4);
- private final PortNumber p5 = PortNumber.portNumber(5);
-
- private final VlanId v10 = VlanId.vlanId((short) 10);
- private final VlanId v20 = VlanId.vlanId((short) 20);
- private VlanId vInt;
-
- private final Interface u10 = new Interface(null, new ConnectPoint(devId1, p1),
- null, null, null, v10, null, null);
- private final Interface t10 = new Interface(null, new ConnectPoint(devId1, p2),
- null, null, null, null, Sets.newHashSet(v10), null);
- private final Interface t10n20 = new Interface(null, new ConnectPoint(devId1, p3),
- null, null, null, null, Sets.newHashSet(v10), v20);
-
- @Before
- public void setUp() throws Exception {
- Set<Interface> interfaces = Sets.newHashSet(u10, t10, t10n20);
- interfaceService = new MockInterfaceService(interfaces);
- deviceService = EasyMock.createMock(DeviceService.class);
- srManager = new MockSegmentRoutingManager(Maps.newHashMap());
- srManager.deviceConfiguration = EasyMock.createMock(DeviceConfiguration.class);
- srManager.interfaceService = interfaceService;
- srManager.deviceService = deviceService;
- vInt = srManager.getDefaultInternalVlan();
- rrp = new RoutingRulePopulator(srManager);
- }
-
- // All ports are enabled
- @Test
- public void testNoMoreEnabledPortCase1() throws Exception {
- Port port1 = new DefaultPort(dev1, p1, true);
- Port port2 = new DefaultPort(dev1, p2, true);
- Port port3 = new DefaultPort(dev1, p3, true);
- Port port4 = new DefaultPort(dev1, p4, true);
- Port port5 = new DefaultPort(dev1, p5, true);
- List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
- expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
- replay(deviceService);
- assertFalse(rrp.noMoreEnabledPort(devId1, v10));
- assertFalse(rrp.noMoreEnabledPort(devId1, v20));
- assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
- }
-
- // Disable port 1
- @Test
- public void testNoMoreEnabledPortCase2() throws Exception {
- Port port1 = new DefaultPort(dev1, p1, false);
- Port port2 = new DefaultPort(dev1, p2, true);
- Port port3 = new DefaultPort(dev1, p3, true);
- Port port4 = new DefaultPort(dev1, p4, true);
- Port port5 = new DefaultPort(dev1, p5, true);
- List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
- expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
- replay(deviceService);
- assertFalse(rrp.noMoreEnabledPort(devId1, v10));
- assertFalse(rrp.noMoreEnabledPort(devId1, v20));
- assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
- }
-
- // Disable port 1 and 3
- @Test
- public void testNoMoreEnabledPortCase3() throws Exception {
- Port port1 = new DefaultPort(dev1, p1, false);
- Port port2 = new DefaultPort(dev1, p2, true);
- Port port3 = new DefaultPort(dev1, p3, false);
- Port port4 = new DefaultPort(dev1, p4, true);
- Port port5 = new DefaultPort(dev1, p5, true);
- List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
- expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
- replay(deviceService);
- assertFalse(rrp.noMoreEnabledPort(devId1, v10));
- assertTrue(rrp.noMoreEnabledPort(devId1, v20));
- assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
- }
-
- // Disable port 1 to 3
- @Test
- public void testNoMoreEnabledPortCase4() throws Exception {
- Port port1 = new DefaultPort(dev1, p1, false);
- Port port2 = new DefaultPort(dev1, p2, false);
- Port port3 = new DefaultPort(dev1, p3, false);
- Port port4 = new DefaultPort(dev1, p4, true);
- Port port5 = new DefaultPort(dev1, p5, true);
- List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
- expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
- replay(deviceService);
- assertTrue(rrp.noMoreEnabledPort(devId1, v10));
- assertTrue(rrp.noMoreEnabledPort(devId1, v20));
- assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
- }
-
- // Disable port 1 to 4
- @Test
- public void testNoMoreEnabledPortCase5() throws Exception {
- Port port1 = new DefaultPort(dev1, p1, false);
- Port port2 = new DefaultPort(dev1, p2, false);
- Port port3 = new DefaultPort(dev1, p3, false);
- Port port4 = new DefaultPort(dev1, p4, false);
- Port port5 = new DefaultPort(dev1, p5, true);
- List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
- expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
- replay(deviceService);
- assertTrue(rrp.noMoreEnabledPort(devId1, v10));
- assertTrue(rrp.noMoreEnabledPort(devId1, v20));
- assertFalse(rrp.noMoreEnabledPort(devId1, vInt));
- }
-
- // Disable all ports
- @Test
- public void testNoMoreEnabledPortCase6() throws Exception {
- Port port1 = new DefaultPort(dev1, p1, false);
- Port port2 = new DefaultPort(dev1, p2, false);
- Port port3 = new DefaultPort(dev1, p3, false);
- Port port4 = new DefaultPort(dev1, p4, false);
- Port port5 = new DefaultPort(dev1, p5, false);
- List<Port> ports = Lists.newArrayList(port1, port2, port3, port4, port5);
-
- expect(deviceService.getPorts(anyObject(DeviceId.class))).andReturn(ports).anyTimes();
- replay(deviceService);
- assertTrue(rrp.noMoreEnabledPort(devId1, v10));
- assertTrue(rrp.noMoreEnabledPort(devId1, v20));
- assertTrue(rrp.noMoreEnabledPort(devId1, vInt));
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/TestUtils.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/TestUtils.java
deleted file mode 100644
index 339b2c8..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/TestUtils.java
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ICMPEcho;
-
-import java.util.Map;
-import java.util.Set;
-
-import static org.onlab.packet.ICMP.TYPE_ECHO_REQUEST;
-import static org.onlab.packet.ICMP6.ECHO_REQUEST;
-import static org.onlab.packet.IPv4.PROTOCOL_ICMP;
-import static org.onosproject.routeservice.Route.Source.STATIC;
-
-/**
- * Utilities class for unit tests.
- */
-public final class TestUtils {
-
- private TestUtils() {
-
- }
-
- // Device configuration section
- static final DeviceId REMOTE_LEAF = DeviceId.deviceId("of:0000000000000001");
- static final int REMOTE_LEAF_SID4 = 1;
- static final String REMOTE_LEAF_LB4 = "192.168.0.1";
- static final int REMOTE_LEAF_SID6 = 10;
- static final String REMOTE_LEAF_LB6 = "2000::c0a8:1";
- private static final PortNumber P1 = PortNumber.portNumber(1);
- static final MacAddress REMOTE_MAC = MacAddress.valueOf("00:00:00:00:00:02");
-
- static final DeviceId LOCAL_LEAF = DeviceId.deviceId("of:0000000000000101");
- static final int LOCAL_LEAF_SID4 = 101;
- static final String LOCAL_LEAF_LB4 = "192.168.0.101";
- static final int LOCAL_LEAF_SID6 = 111;
- static final String LOCAL_LEAF_LB6 = "2000::c0a8:101";
- static final MacAddress LOCAL_MAC = MacAddress.valueOf("00:00:00:00:01:01");
-
- // Configure a pair
- static final DeviceId LOCAL_LEAF1 = DeviceId.deviceId("of:0000000000000201");
- static final int LOCAL_LEAF1_SID4 = 201;
- static final String LOCAL_LEAF1_LB4 = "192.168.0.201";
- static final int LOCAL_LEAF1_SID6 = 211;
- static final String LOCAL_LEAF1_LB6 = "2000::c0a8:201";
- static final MacAddress LOCAL_MAC1 = MacAddress.valueOf("00:00:00:00:02:01");
-
- static final DeviceId LOCAL_LEAF2 = DeviceId.deviceId("of:0000000000000202");
- static final int LOCAL_LEAF2_SID4 = 202;
- static final String LOCAL_LEAF2_LB4 = "192.168.0.202";
- static final int LOCAL_LEAF2_SID6 = 212;
- static final String LOCAL_LEAF2_LB6 = "2000::c0a8:202";
- static final MacAddress LOCAL_MAC2 = MacAddress.valueOf("00:00:00:00:02:02");
-
- // Pair port
- static final PortNumber P3 = PortNumber.portNumber(3);
-
- // Ports configuration section
- static final ConnectPoint CP11 = new ConnectPoint(REMOTE_LEAF, P1);
- private static final PortNumber P2 = PortNumber.portNumber(2);
- static final ConnectPoint CP12 = new ConnectPoint(REMOTE_LEAF, P2);
- private static final IpAddress IP4_1 = IpAddress.valueOf("10.0.0.254");
- private static final IpPrefix PREFIX4_1 = IpPrefix.valueOf("10.0.0.254/24");
- private static final IpAddress IP6_1 = IpAddress.valueOf("2000::ff");
- private static final IpPrefix PREFIX6_1 = IpPrefix.valueOf("2000::ff/120");
- private static final InterfaceIpAddress INTF_IP4_1 = new InterfaceIpAddress(
- IP4_1, PREFIX4_1);
- private static final InterfaceIpAddress INTF_IP6_1 = new InterfaceIpAddress(
- IP6_1, PREFIX6_1);
- private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
- static final Interface INTF1 = new Interface(
- "INTF1", CP12, Lists.newArrayList(INTF_IP4_1, INTF_IP6_1), MacAddress.NONE,
- null, INTF_VLAN_UNTAGGED, null, null);
- static final ConnectPoint CP13 = new ConnectPoint(REMOTE_LEAF, P3);
- private static final IpAddress IP4_2 = IpAddress.valueOf("10.0.3.254");
- private static final IpPrefix PREFIX4_2 = IpPrefix.valueOf("10.0.3.254/24");
- private static final IpAddress IP6_2 = IpAddress.valueOf("2000::3ff");
- private static final IpPrefix PREFIX6_2 = IpPrefix.valueOf("2000::3ff/120");
- private static final InterfaceIpAddress INTF_IP4_2 = new InterfaceIpAddress(
- IP4_2, PREFIX4_2);
- private static final InterfaceIpAddress INTF_IP6_2 = new InterfaceIpAddress(
- IP6_2, PREFIX6_2);
- static final Interface INTF2 = new Interface(
- "INTF2", CP13, Lists.newArrayList(INTF_IP4_2, INTF_IP6_2), MacAddress.NONE,
- null, INTF_VLAN_UNTAGGED, null, null);
-
- static final ConnectPoint CP1011 = new ConnectPoint(LOCAL_LEAF, P1);
- private static final IpAddress IP4_11 = IpAddress.valueOf("10.0.1.254");
- private static final IpPrefix PREFIX4_11 = IpPrefix.valueOf("10.0.1.254/24");
- private static final InterfaceIpAddress INTF_IP4_11 = new InterfaceIpAddress(
- IP4_11, PREFIX4_11);
- private static final IpAddress IP6_11 = IpAddress.valueOf("2000::1ff");
- private static final IpPrefix PREFIX6_11 = IpPrefix.valueOf("2000::1ff/120");
- private static final InterfaceIpAddress INTF_IP6_11 = new InterfaceIpAddress(
- IP6_11, PREFIX6_11);
- static final Interface INTF111 = new Interface(
- "INTF111", CP1011, Lists.newArrayList(INTF_IP4_11, INTF_IP6_11), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
-
- static final ConnectPoint CP2011 = new ConnectPoint(LOCAL_LEAF1, P1);
- private static final IpAddress IP4_21 = IpAddress.valueOf("10.0.2.254");
- private static final IpPrefix PREFIX4_21 = IpPrefix.valueOf("10.0.2.254/24");
- private static final InterfaceIpAddress INTF_IP4_21 = new InterfaceIpAddress(
- IP4_21, PREFIX4_21);
- private static final IpAddress IP6_21 = IpAddress.valueOf("2000::2ff");
- private static final IpPrefix PREFIX6_21 = IpPrefix.valueOf("2000::2ff/120");
- private static final InterfaceIpAddress INTF_IP6_21 = new InterfaceIpAddress(
- IP6_21, PREFIX6_21);
- static final Interface INTF211 = new Interface(
- "INTF211", CP2011, Lists.newArrayList(INTF_IP4_21, INTF_IP6_21), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
-
- static final ConnectPoint CP2021 = new ConnectPoint(LOCAL_LEAF2, P1);
- private static final IpAddress IP4_22 = IpAddress.valueOf("10.0.2.254");
- private static final IpPrefix PREFIX4_22 = IpPrefix.valueOf("10.0.2.254/24");
- private static final InterfaceIpAddress INTF_IP4_22 = new InterfaceIpAddress(
- IP4_22, PREFIX4_22);
- private static final IpAddress IP6_22 = IpAddress.valueOf("2000::2ff");
- private static final IpPrefix PREFIX6_22 = IpPrefix.valueOf("2000::2ff/120");
- private static final InterfaceIpAddress INTF_IP6_22 = new InterfaceIpAddress(
- IP6_22, PREFIX6_22);
- static final Interface INTF212 = new Interface(
- "INTF212", CP2021, Lists.newArrayList(INTF_IP4_22, INTF_IP6_22), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
- private static final PortNumber P4 = PortNumber.portNumber(4);
- static final ConnectPoint CP2024 = new ConnectPoint(LOCAL_LEAF2, P4);
- private static final PortNumber P5 = PortNumber.portNumber(5);
- static final ConnectPoint CP2025 = new ConnectPoint(LOCAL_LEAF2, P5);
- private static final IpAddress IP4_23 = IpAddress.valueOf("10.0.4.254");
- private static final IpPrefix PREFIX4_23 = IpPrefix.valueOf("10.0.4.254/24");
- private static final InterfaceIpAddress INTF_IP4_23 = new InterfaceIpAddress(
- IP4_23, PREFIX4_23);
- private static final IpAddress IP6_23 = IpAddress.valueOf("2000::4ff");
- private static final IpPrefix PREFIX6_23 = IpPrefix.valueOf("2000::4ff/120");
- private static final InterfaceIpAddress INTF_IP6_23 = new InterfaceIpAddress(
- IP6_23, PREFIX6_23);
- static final Interface INTF213 = new Interface(
- "INTF212", CP2024, Lists.newArrayList(INTF_IP4_23, INTF_IP6_23), MacAddress.NONE, null,
- INTF_VLAN_UNTAGGED, null, null);
-
- // Packet-ins section
- private static final MacAddress SRC_MAC = MacAddress.valueOf("00:00:00:00:00:01");
-
- private static final ICMPEcho ICMP_ECHO = new ICMPEcho()
- .setIdentifier((short) 0)
- .setSequenceNum((short) 0);
-
- private static final ICMP ICMP_REQUEST = (ICMP) new ICMP()
- .setIcmpType(TYPE_ECHO_REQUEST)
- .setPayload(ICMP_ECHO);
-
- private static final Ip4Address SRC_IPV4 = Ip4Address.valueOf("10.0.1.1");
- static final Ip4Address DST_IPV4 = Ip4Address.valueOf("10.0.0.254");
-
- private static final IPv4 IPV4_REQUEST = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4.toInt())
- .setSourceAddress(SRC_IPV4.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV4 = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV4_REQUEST);
-
- private static final ICMP6 ICMP6_REQUEST = new ICMP6()
- .setIcmpType(ECHO_REQUEST);
-
- private static final Ip6Address SRC_IPV6 = Ip6Address.valueOf("2000::101");
- static final Ip6Address DST_IPV6 = Ip6Address.valueOf("2000::ff");
-
- private static final IPv6 IPV6_REQUEST = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6.toOctets())
- .setSourceAddress(SRC_IPV6.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6 = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV6_REQUEST);
-
- static final Ip4Address SRC_IPV41 = Ip4Address.valueOf("10.0.2.1");
-
- private static final IPv4 IPV41_REQUEST = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4.toInt())
- .setSourceAddress(SRC_IPV41.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV41 = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV41_REQUEST);
-
- static final Ip6Address SRC_IPV61 = Ip6Address.valueOf("2000::201");
-
- private static final IPv6 IPV61_REQUEST = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6.toOctets())
- .setSourceAddress(SRC_IPV61.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV61 = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV61_REQUEST);
-
- private static final MacAddress SRC_MAC_MY = MacAddress.valueOf("00:01:00:00:00:01");
- static final Ip4Address SRC_IPV4_MY = Ip4Address.valueOf("10.0.0.1");
-
- private static final IPv4 IPV4_REQUEST_MY = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4.toInt())
- .setSourceAddress(SRC_IPV4_MY.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV4_MY = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC_MY)
- .setPayload(IPV4_REQUEST_MY);
-
- static final Ip6Address SRC_IPV6_MY = Ip6Address.valueOf("2000::1");
-
- private static final IPv6 IPV6_REQUEST_MY = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6.toOctets())
- .setSourceAddress(SRC_IPV6_MY.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6_MY = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC_MY)
- .setPayload(IPV6_REQUEST_MY);
-
- static final Ip4Address DST_IPV4_LOCAL = Ip4Address.valueOf("10.0.3.254");
-
- private static final IPv4 IPV4_REQUEST_LOCAL = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4_LOCAL.toInt())
- .setSourceAddress(SRC_IPV4_MY.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV4_LOCAL = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC_MY)
- .setPayload(IPV4_REQUEST_LOCAL);
-
- static final Ip6Address DST_IPV6_LOCAL = Ip6Address.valueOf("2000::3ff");
-
- private static final IPv6 IPV6_REQUEST_LOCAL = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6_LOCAL.toOctets())
- .setSourceAddress(SRC_IPV6_MY.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6_LOCAL = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC_MY)
- .setPayload(IPV6_REQUEST_LOCAL);
-
- static final Ip4Address DST_IPV4_SAME = Ip4Address.valueOf("10.0.4.254");
-
- private static final IPv4 IPV4_REQUEST_SAME = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4_SAME.toInt())
- .setSourceAddress(SRC_IPV41.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV4_SAME = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(LOCAL_MAC2)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV4_REQUEST_SAME);
-
- static final Ip6Address DST_IPV6_SAME = Ip6Address.valueOf("2000::4ff");
-
- private static final IPv6 IPV6_REQUEST_SAME = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6_SAME.toOctets())
- .setSourceAddress(SRC_IPV61.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6_SAME = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(LOCAL_MAC2)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV6_REQUEST_SAME);
-
- static final Ip6Address DST_IPV6_LL = Ip6Address.valueOf(
- IPv6.getLinkLocalAddress(MacAddress.NONE.toBytes()));
- static final Ip6Address SRC_IPV6_LL = Ip6Address.valueOf(
- IPv6.getLinkLocalAddress(SRC_MAC_MY.toBytes()));
-
- private static final IPv6 IPV6_REQUEST_LL = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6_LL.toOctets())
- .setSourceAddress(SRC_IPV6_LL.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6_LL = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(MacAddress.NONE)
- .setSourceMACAddress(SRC_MAC_MY)
- .setPayload(IPV6_REQUEST_LL);
-
- static final Ip4Address DST_IPV4_LOOPBACK = Ip4Address.valueOf(REMOTE_LEAF_LB4);
-
- private static final IPv4 IPV4_REQUEST_LOOPBACK = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4_LOOPBACK.toInt())
- .setSourceAddress(SRC_IPV4_MY.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV4_LOOPBACK = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC_MY)
- .setPayload(IPV4_REQUEST_LOOPBACK);
-
- static final Ip6Address DST_IPV6_LOOPBACK = Ip6Address.valueOf(REMOTE_LEAF_LB6);
-
- private static final IPv6 IPV6_REQUEST_LOOPBACK = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6_LOOPBACK.toOctets())
- .setSourceAddress(SRC_IPV6_MY.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6_LOOPBACK = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(REMOTE_MAC)
- .setSourceMACAddress(SRC_MAC_MY)
- .setPayload(IPV6_REQUEST_LOOPBACK);
-
- static final Ip4Address DST_IPV4_LOOPBACK_PAIR = Ip4Address.valueOf(LOCAL_LEAF1_LB4);
-
- private static final IPv4 IPV4_REQUEST_LOOPBACK_PAIR = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4_LOOPBACK_PAIR.toInt())
- .setSourceAddress(SRC_IPV41.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV4_LOOPBACK_PAIR = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(LOCAL_MAC1)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV4_REQUEST_LOOPBACK_PAIR);
-
- static final Ip6Address DST_IPV6_LOOPBACK_PAIR = Ip6Address.valueOf(LOCAL_LEAF2_LB6);
-
- private static final IPv6 IPV6_REQUEST_LOOPBACK_PAIR = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6_LOOPBACK_PAIR.toOctets())
- .setSourceAddress(SRC_IPV61.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6_LOOPBACK_PAIR = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(LOCAL_MAC2)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV6_REQUEST_LOOPBACK_PAIR);
-
- static final Ip4Address DST_IPV4_GATEWAY_PAIR = Ip4Address.valueOf("10.0.2.254");
-
- private static final IPv4 IPV4_REQUEST_GATEWAY_PAIR = (IPv4) new IPv4()
- .setDestinationAddress(DST_IPV4_GATEWAY_PAIR.toInt())
- .setSourceAddress(SRC_IPV41.toInt())
- .setTtl((byte) 64)
- .setProtocol(PROTOCOL_ICMP)
- .setPayload(ICMP_REQUEST);
-
- static final Ethernet ETH_REQ_IPV4_GATEWAY_PAIR = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV4)
- .setDestinationMACAddress(LOCAL_MAC1)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV4_REQUEST_GATEWAY_PAIR);
-
- static final Ip6Address DST_IPV6_GATEWAY_PAIR = Ip6Address.valueOf("2000::2ff");
-
- private static final IPv6 IPV6_REQUEST_GATEWAY_PAIR = (IPv6) new IPv6()
- .setDestinationAddress(DST_IPV6_GATEWAY_PAIR.toOctets())
- .setSourceAddress(SRC_IPV61.toOctets())
- .setHopLimit((byte) 255)
- .setNextHeader(IPv6.PROTOCOL_ICMP6)
- .setPayload(ICMP6_REQUEST);
-
- static final Ethernet ETH_REQ_IPV6_GATEWAY_PAIR = (Ethernet) new Ethernet()
- .setEtherType(Ethernet.TYPE_IPV6)
- .setDestinationMACAddress(LOCAL_MAC2)
- .setSourceMACAddress(SRC_MAC)
- .setPayload(IPV6_REQUEST_GATEWAY_PAIR);
-
- // Resolved route
- private static final ResolvedRoute IPV4_ROUTE = new ResolvedRoute(
- new Route(STATIC, SRC_IPV4.toIpPrefix(), SRC_IPV4), MacAddress.NONE);
- private static final ResolvedRoute IPV6_ROUTE = new ResolvedRoute(
- new Route(STATIC, SRC_IPV6.toIpPrefix(), SRC_IPV6), MacAddress.NONE);
- static final Map<IpPrefix, Set<ResolvedRoute>> ROUTE_STORE = ImmutableMap.of(SRC_IPV4.toIpPrefix(),
- Sets.newHashSet(IPV4_ROUTE),
- SRC_IPV6.toIpPrefix(),
- Sets.newHashSet(IPV6_ROUTE));
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/BlockedPortsConfigTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/BlockedPortsConfigTest.java
deleted file mode 100644
index e457896..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/BlockedPortsConfigTest.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.DefaultApplicationId;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-/**
- * Unit tests for {@link BlockedPortsConfig}.
- */
-public class BlockedPortsConfigTest {
-
- private static final ApplicationId APP_ID = new DefaultApplicationId(1, "foo");
- private static final String KEY = "blocked";
- private static final ObjectMapper MAPPER = new ObjectMapper();
-
- private static final String DEV1 = "of:0000000000000001";
- private static final String DEV2 = "of:0000000000000002";
- private static final String DEV3 = "of:0000000000000003";
- private static final String DEV4 = "of:0000000000000004";
- private static final String RANGE_14 = "1-4";
- private static final String RANGE_79 = "7-9";
- private static final String P1 = "1";
- private static final String P5 = "5";
- private static final String P9 = "9";
-
- private BlockedPortsConfig cfg;
- private BlockedPortsConfig.Range range;
-
- private void print(String s) {
- System.out.println(s);
- }
-
- private void print(Object o) {
- print(o.toString());
- }
-
- @Before
- public void setUp() throws IOException {
- InputStream blockedPortsJson = BlockedPortsConfigTest.class
- .getResourceAsStream("/blocked-ports.json");
- JsonNode node = MAPPER.readTree(blockedPortsJson);
- cfg = new BlockedPortsConfig();
- cfg.init(APP_ID, KEY, node, MAPPER, null);
- }
-
- @Test
- public void basic() {
- cfg = new BlockedPortsConfig();
- print(cfg);
-
- assertEquals("non-empty devices list", 0, cfg.deviceIds().size());
- assertEquals("non-empty port-ranges list", 0, cfg.portRanges("non-exist").size());
- }
-
-
- @Test
- public void overIteratePort() {
- Iterator<Long> iterator = cfg.portIterator(DEV3);
- while (iterator.hasNext()) {
- print(iterator.next());
- }
-
- try {
- print(iterator.next());
- fail("NoSuchElement exception NOT thrown");
- } catch (NoSuchElementException e) {
- print("<good> " + e);
- }
- }
-
- @Test
- public void overIterateRange() {
- range = new BlockedPortsConfig.Range("4-6");
-
- Iterator<Long> iterator = range.iterator();
- while (iterator.hasNext()) {
- print(iterator.next());
- }
-
- try {
- print(iterator.next());
- fail("NoSuchElement exception NOT thrown");
- } catch (NoSuchElementException e) {
- print("<good> " + e);
- }
- }
-
-
- @Test
- public void simple() {
- List<String> devIds = cfg.deviceIds();
- print(devIds);
- assertEquals("wrong dev id count", 3, devIds.size());
- assertEquals("missing dev 1", true, devIds.contains(DEV1));
- assertEquals("dev 2??", false, devIds.contains(DEV2));
- assertEquals("missing dev 3", true, devIds.contains(DEV3));
-
- List<String> d1ranges = cfg.portRanges(DEV1);
- print(d1ranges);
- assertEquals("wrong d1 range count", 2, d1ranges.size());
- assertEquals("missing 1-4", true, d1ranges.contains(RANGE_14));
- assertEquals("missing 7-9", true, d1ranges.contains(RANGE_79));
-
- List<String> d2ranges = cfg.portRanges(DEV2);
- print(d2ranges);
- assertEquals("wrong d2 range count", 0, d2ranges.size());
-
- List<String> d3ranges = cfg.portRanges(DEV3);
- print(d3ranges);
- assertEquals("wrong d3 range count", 1, d3ranges.size());
- assertEquals("range 1-4?", false, d3ranges.contains(RANGE_14));
- assertEquals("missing 7-9", true, d3ranges.contains(RANGE_79));
- }
-
-
- private void verifyPorts(List<Long> ports, long... exp) {
- assertEquals("Wrong port count", exp.length, ports.size());
- for (long e : exp) {
- assertEquals("missing port", true, ports.contains(e));
- }
- }
-
- private void verifyPortIterator(String devid, long... exp) {
- List<Long> ports = new ArrayList<>();
- Iterator<Long> iter = cfg.portIterator(devid);
- iter.forEachRemaining(ports::add);
- print(ports);
- verifyPorts(ports, exp);
- }
-
- @Test
- public void rangeIterators() {
- verifyPortIterator(DEV1, 1, 2, 3, 4, 7, 8, 9);
- verifyPortIterator(DEV2);
- verifyPortIterator(DEV3, 7, 8, 9);
- }
-
- @Test
- public void singlePorts() {
- List<String> devIds = cfg.deviceIds();
- print(devIds);
- assertEquals("wrong dev id count", 3, devIds.size());
- assertEquals("missing dev 4", true, devIds.contains(DEV4));
-
- List<String> d1ranges = cfg.portRanges(DEV4);
- print(d1ranges);
- assertEquals("wrong d4 range count", 3, d1ranges.size());
- assertEquals("missing 1", true, d1ranges.contains(P1));
- assertEquals("missing 5", true, d1ranges.contains(P5));
- assertEquals("missing 9", true, d1ranges.contains(P9));
-
- verifyPortIterator(DEV4, 1, 5, 9);
- }
-
-
- // test Range inner class
-
- @Test
- public void rangeBadFormat() {
- try {
- range = new BlockedPortsConfig.Range("not-a-range-format");
- fail("no exception thrown");
- } catch (IllegalArgumentException iar) {
- print(iar);
- assertEquals("wrong msg", "Bad Range Format not-a-range-format", iar.getMessage());
- }
- }
-
- @Test
- public void rangeBadHi() {
- try {
- range = new BlockedPortsConfig.Range("2-nine");
- fail("no exception thrown");
- } catch (IllegalArgumentException iar) {
- print(iar);
- assertEquals("wrong msg", "Bad Range Format 2-nine", iar.getMessage());
- }
- }
-
- @Test
- public void rangeHiLessThanLo() {
- try {
- range = new BlockedPortsConfig.Range("9-5");
- fail("no exception thrown");
- } catch (IllegalArgumentException iar) {
- print(iar);
- assertEquals("wrong msg", "Bad Range Format 9-5", iar.getMessage());
- }
- }
-
- @Test
- public void rangeNegative() {
- try {
- range = new BlockedPortsConfig.Range("-2-4");
- fail("no exception thrown");
- } catch (IllegalArgumentException iar) {
- print(iar);
- assertEquals("wrong msg", "Bad Range Format -2-4", iar.getMessage());
- }
- }
-
- @Test
- public void rangeGood() {
- range = new BlockedPortsConfig.Range("100-104");
- List<Long> values = new ArrayList<>();
- range.iterator().forEachRemaining(values::add);
- print(values);
- verifyPorts(values, 100, 101, 102, 103, 104);
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java
deleted file mode 100644
index 1674f6c..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigRegistry;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.net.neighbour.NeighbourResolutionService;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-
-import java.io.InputStream;
-import java.util.List;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.*;
-
-public class DeviceConfigurationTest {
- private static final DeviceId DEV1 = DeviceId.deviceId("of:1");
- private static final String CONFIG_KEY = "segmentrouting";
- private static final PortNumber PORT1 = PortNumber.portNumber(1);
- private static final PortNumber PORT2 = PortNumber.portNumber(2);
- private static final ConnectPoint CP1 = new ConnectPoint(DEV1, PORT1);
- private static final ConnectPoint CP2 = new ConnectPoint(DEV1, PORT2);
- private static final MacAddress MAC1 = MacAddress.valueOf("00:11:22:33:44:55");
- private static final VlanId VLAN1 = VlanId.vlanId((short) 10);
- private static final VlanId VLAN2 = VlanId.vlanId((short) 20);
- private static final IpPrefix PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
- private static final IpPrefix PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
- private static final IpPrefix ROUTE1 = IpPrefix.valueOf("20.0.1.254/24");
- private static final InterfaceIpAddress INTF1_IP = new InterfaceIpAddress(PREFIX1.address(), PREFIX1);
- private static final InterfaceIpAddress INTF2_IP = new InterfaceIpAddress(PREFIX2.address(), PREFIX2);
- private static final List<InterfaceIpAddress> IP_LIST1 = Lists.newArrayList(INTF1_IP);
- private static final List<InterfaceIpAddress> IP_LIST2 = Lists.newArrayList(INTF2_IP);
- private static final Interface INTF1 = new Interface("mock-intf1", CP1, IP_LIST1, MAC1,
- null, VLAN1, null, null);
- private static final Interface INTF2 = new Interface("mock-intf2", CP2, IP_LIST2, MAC1,
- null, VLAN2, null, null);
- private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF1, INTF2);
-
- private DeviceConfiguration devConfig;
-
- private NetworkConfigRegistry networkConfigService;
-
- @Before
- public void setUp() throws Exception {
- InterfaceService interfaceService;
- networkConfigService = null;
- NeighbourResolutionService neighbourResolutionService;
- SegmentRoutingManager srManager;
-
- // Mock device netcfg
- InputStream jsonStream = SegmentRoutingDeviceConfigTest.class.getResourceAsStream("/device.json");
- ObjectMapper mapper = new ObjectMapper();
- JsonNode jsonNode = mapper.readTree(jsonStream);
- SegmentRoutingDeviceConfig srDevConfig = new SegmentRoutingDeviceConfig();
- srDevConfig.init(DEV1, CONFIG_KEY, jsonNode, mapper, config -> { });
- BasicDeviceConfig basicDeviceConfig = new BasicDeviceConfig();
- basicDeviceConfig.init(DEV1, DEV1.toString(), JsonNodeFactory.instance.objectNode(), mapper, config -> { });
- BasicDeviceConfig purgeOnDisconnectConfig = basicDeviceConfig.purgeOnDisconnection(true);
-
-
- // Mock interface netcfg
- jsonStream = InterfaceConfig.class.getResourceAsStream("/interface1.json");
- jsonNode = mapper.readTree(jsonStream);
- InterfaceConfig interfaceConfig1 = new InterfaceConfig();
- interfaceConfig1.init(CP1, CONFIG_KEY, jsonNode, mapper, config -> { });
- jsonStream = InterfaceConfig.class.getResourceAsStream("/interface2.json");
- jsonNode = mapper.readTree(jsonStream);
- InterfaceConfig interfaceConfig2 = new InterfaceConfig();
- interfaceConfig2.init(CP1, CONFIG_KEY, jsonNode, mapper, config -> { });
-
- networkConfigService = createMock(NetworkConfigRegistry.class);
- expect(networkConfigService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class))
- .andReturn(Sets.newHashSet(DEV1)).anyTimes();
- expect(networkConfigService.getConfig(DEV1, SegmentRoutingDeviceConfig.class))
- .andReturn(srDevConfig).anyTimes();
- expect(networkConfigService.addConfig(DEV1, BasicDeviceConfig.class))
- .andReturn(basicDeviceConfig).anyTimes();
- expect(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class))
- .andReturn(basicDeviceConfig).anyTimes();
- expect(networkConfigService.applyConfig(DEV1, BasicDeviceConfig.class, purgeOnDisconnectConfig.node()))
- .andReturn(purgeOnDisconnectConfig).anyTimes();
- expect(networkConfigService.getSubjects(ConnectPoint.class, InterfaceConfig.class))
- .andReturn(Sets.newHashSet(CP1, CP2)).anyTimes();
- expect(networkConfigService.getConfig(CP1, InterfaceConfig.class)).andReturn(interfaceConfig1).anyTimes();
- expect(networkConfigService.getConfig(CP2, InterfaceConfig.class)).andReturn(interfaceConfig2).anyTimes();
- expect(networkConfigService.applyConfig(eq(CP1), eq(InterfaceConfig.class), anyObject()))
- .andReturn(interfaceConfig1).anyTimes();
- expect(networkConfigService.applyConfig(eq(CP2), eq(InterfaceConfig.class), anyObject()))
- .andReturn(interfaceConfig2).anyTimes();
- expect(networkConfigService.getConfig(null, SegmentRoutingAppConfig.class)).andReturn(null).anyTimes();
- replay(networkConfigService);
-
- interfaceService = createMock(InterfaceService.class);
- expect(interfaceService.getInterfaces()).andReturn(INTERFACES).anyTimes();
- expect(interfaceService.getInterfacesByPort(CP1)).andReturn(Sets.newHashSet(INTF1)).anyTimes();
- expect(interfaceService.getInterfacesByPort(CP2)).andReturn(Sets.newHashSet(INTF2)).anyTimes();
- replay(interfaceService);
-
- neighbourResolutionService = createMock(NeighbourResolutionService.class);
- neighbourResolutionService.registerNeighbourHandler(anyObject(ConnectPoint.class), anyObject(), anyObject());
- expectLastCall().anyTimes();
- replay(neighbourResolutionService);
-
- srManager = new SegmentRoutingManager();
- srManager.interfaceService = interfaceService;
- srManager.cfgService = networkConfigService;
- srManager.neighbourResolutionService = neighbourResolutionService;
-
- devConfig = new DeviceConfiguration(srManager);
- devConfig.addSubnet(CP2, ROUTE1);
- }
-
- @Test
- public void getConfiguredSubnets() {
- Set<IpPrefix> expect = Sets.newHashSet(PREFIX1, PREFIX2);
- assertEquals(expect, devConfig.getConfiguredSubnets(DEV1));
- }
-
- @Test
- public void getSubnets() {
- Set<IpPrefix> expect = Sets.newHashSet(PREFIX1, PREFIX2, ROUTE1);
- assertEquals(expect, devConfig.getSubnets(DEV1));
- }
-
- @Test
- public void getPortSubnets() {
- assertEquals(Sets.newHashSet(PREFIX1), devConfig.getPortSubnets(DEV1, PORT1));
- assertEquals(Sets.newHashSet(PREFIX2), devConfig.getPortSubnets(DEV1, PORT2));
- }
-
- @Test
- public void inSameSubnet() {
- assertTrue(devConfig.inSameSubnet(DEV1, PREFIX1.address()));
- assertTrue(devConfig.inSameSubnet(DEV1, PREFIX2.address()));
- assertFalse(devConfig.inSameSubnet(DEV1, ROUTE1.address()));
- }
-
- @Test
- public void getPurgeOnDisconnect() {
- assertNotNull(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class));
- assertTrue(networkConfigService.getConfig(DEV1, BasicDeviceConfig.class).purgeOnDisconnection());
- }
-}
\ No newline at end of file
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
deleted file mode 100644
index 2a10f56..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfigTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-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;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.ConfigApplyDelegate;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
-
-import java.io.InputStream;
-import java.util.Set;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.*;
-
-/**
- * Tests for class {@link SegmentRoutingAppConfig}.
- */
-public class SegmentRoutingAppConfigTest {
- private SegmentRoutingAppConfig config;
- private SegmentRoutingAppConfig invalidConfig;
- private SegmentRoutingAppConfig mplsEcmpConfig;
-
- private static final MacAddress ROUTER_MAC_1 = MacAddress.valueOf("00:00:00:00:00:01");
- private static final MacAddress ROUTER_MAC_2 = MacAddress.valueOf("00:00:00:00:00:02");
- private static final MacAddress ROUTER_MAC_3 = MacAddress.valueOf("00:00:00:00:00:03");
- private static final ConnectPoint PORT_1 = ConnectPoint.deviceConnectPoint("of:1/1");
- private static final ConnectPoint PORT_2 = ConnectPoint.deviceConnectPoint("of:1/2");
- private static final ConnectPoint PORT_3 = ConnectPoint.deviceConnectPoint("of:1/3");
- private static final DeviceId VROUTER_ID_1 = DeviceId.deviceId("of:1");
- private static final DeviceId VROUTER_ID_2 = DeviceId.deviceId("of:2");
- 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.
- *
- * @throws Exception
- */
- @Before
- public void setUp() throws Exception {
- InputStream jsonStream = SegmentRoutingAppConfigTest.class
- .getResourceAsStream("/app.json");
- InputStream invalidJsonStream = SegmentRoutingAppConfigTest.class
- .getResourceAsStream("/app-invalid.json");
- InputStream mplsEcmpJsonStream = SegmentRoutingAppConfigTest.class
- .getResourceAsStream("/app-ecmp.json");
-
- String key = SegmentRoutingManager.APP_NAME;
- ApplicationId subject = new TestApplicationId(key);
- ObjectMapper mapper = new ObjectMapper();
- JsonNode jsonNode = mapper.readTree(jsonStream);
- JsonNode invalidJsonNode = mapper.readTree(invalidJsonStream);
- JsonNode mplsEcmpJsonNode = mapper.readTree(mplsEcmpJsonStream);
- ConfigApplyDelegate delegate = new MockDelegate();
-
- config = new SegmentRoutingAppConfig();
- config.init(subject, key, jsonNode, mapper, delegate);
- invalidConfig = new SegmentRoutingAppConfig();
- invalidConfig.init(subject, key, invalidJsonNode, mapper, delegate);
- mplsEcmpConfig = new SegmentRoutingAppConfig();
- mplsEcmpConfig.init(subject, key, mplsEcmpJsonNode, mapper, delegate);
- }
-
- /**
- * Tests config validity.
- *
- * @throws Exception
- */
- @Test
- public void testIsValid() throws Exception {
- assertTrue(config.isValid());
- assertFalse(invalidConfig.isValid());
- assertTrue(mplsEcmpConfig.isValid());
- }
-
- /**
- * Test MPLS-ECMP default getter. By-default
- * MPLS-ECMPS is false.
- */
- @Test
- public void testDefaultMplsEcmp() {
- boolean mplsEcmp = config.mplsEcmp();
- assertThat(mplsEcmp, is(false));
- }
-
- /**
- * Test MPLS-ECMP getter.
- */
- @Test
- public void testMplsEcmp() {
- boolean mplsEcmp = mplsEcmpConfig.mplsEcmp();
- assertThat(mplsEcmp, is(true));
- }
-
- /**
- * Test MPLS-ECMP setter.
- */
- @Test
- public void testSetMplsEcmp() {
- /*
- * In the config the value is not set.
- */
- boolean mplsEcmp = config.mplsEcmp();
- assertThat(mplsEcmp, is(false));
- config.setMplsEcmp(true);
- mplsEcmp = config.mplsEcmp();
- assertThat(mplsEcmp, is(true));
- /*
- * In the mplsEcmpConfig the value is true,
- */
- mplsEcmp = mplsEcmpConfig.mplsEcmp();
- assertThat(mplsEcmp, is(true));
- config.setMplsEcmp(false);
- mplsEcmp = config.mplsEcmp();
- assertThat(mplsEcmp, is(false));
- }
-
- /**
- * Tests vRouterMacs getter.
- *
- * @throws Exception
- */
- @Test
- public void testVRouterMacs() throws Exception {
- Set<MacAddress> vRouterMacs = config.vRouterMacs();
- assertNotNull("vRouterMacs should not be null", vRouterMacs);
- assertThat(vRouterMacs.size(), is(2));
- assertTrue(vRouterMacs.contains(ROUTER_MAC_1));
- assertTrue(vRouterMacs.contains(ROUTER_MAC_2));
- }
-
- /**
- * Tests vRouterMacs setter.
- *
- * @throws Exception
- */
- @Test
- public void testSetVRouterMacs() throws Exception {
- ImmutableSet.Builder<MacAddress> builder = ImmutableSet.builder();
- builder.add(ROUTER_MAC_3);
- config.setVRouterMacs(builder.build());
-
- Set<MacAddress> vRouterMacs = config.vRouterMacs();
- assertThat(vRouterMacs.size(), is(1));
- assertTrue(vRouterMacs.contains(ROUTER_MAC_3));
- }
-
- /**
- * Tests suppressSubnet getter.
- *
- * @throws Exception
- */
- @Test
- public void testSuppressSubnet() throws Exception {
- Set<ConnectPoint> suppressSubnet = config.suppressSubnet();
- assertNotNull("suppressSubnet should not be null", suppressSubnet);
- assertThat(suppressSubnet.size(), is(2));
- assertTrue(suppressSubnet.contains(PORT_1));
- assertTrue(suppressSubnet.contains(PORT_2));
- }
-
- /**
- * Tests suppressSubnet setter.
- *
- * @throws Exception
- */
- @Test
- public void testSetSuppressSubnet() throws Exception {
- ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
- builder.add(PORT_3);
- config.setSuppressSubnet(builder.build());
-
- Set<ConnectPoint> suppressSubnet = config.suppressSubnet();
- assertNotNull("suppressSubnet should not be null", suppressSubnet);
- assertThat(suppressSubnet.size(), is(1));
- assertTrue(suppressSubnet.contains(PORT_3));
- }
-
- /**
- * Tests suppressHostByPort getter.
- *
- * @throws Exception
- */
- @Test
- public void testSuppressHostByPort() throws Exception {
- Set<ConnectPoint> suppressHostByPort = config.suppressHostByPort();
- assertNotNull("suppressHostByPort should not be null", suppressHostByPort);
- assertThat(suppressHostByPort.size(), is(2));
- assertTrue(suppressHostByPort.contains(PORT_1));
- assertTrue(suppressHostByPort.contains(PORT_2));
- }
-
- /**
- * Tests suppressHostByPort setter.
- *
- * @throws Exception
- */
- @Test
- public void testSetSuppressHostByPort() throws Exception {
- ImmutableSet.Builder<ConnectPoint> builder = ImmutableSet.builder();
- builder.add(PORT_3);
- config.setSuppressHostByPort(builder.build());
-
- Set<ConnectPoint> suppressHostByPort = config.suppressHostByPort();
- assertNotNull("suppressHostByPort should not be null", suppressHostByPort);
- assertThat(suppressHostByPort.size(), is(1));
- assertTrue(suppressHostByPort.contains(PORT_3));
- }
-
- /**
- * Tests suppressHostByProvider getter.
- *
- * @throws Exception
- */
- @Test
- public void testSuppressHostByProvider() throws Exception {
- Set<String> supprsuppressHostByProvider = config.suppressHostByProvider();
- assertNotNull("suppressHostByProvider should not be null", supprsuppressHostByProvider);
- assertThat(supprsuppressHostByProvider.size(), is(2));
- assertTrue(supprsuppressHostByProvider.contains(PROVIDER_1));
- assertTrue(supprsuppressHostByProvider.contains(PROVIDER_2));
- }
-
- /**
- * Tests suppressHostByProvider setter.
- *
- * @throws Exception
- */
- @Test
- public void testSetHostLearning() throws Exception {
- ImmutableSet.Builder<String> builder = ImmutableSet.builder();
- builder.add(PROVIDER_3);
- config.setSuppressHostByProvider(builder.build());
-
- Set<String> supprsuppressHostByProvider = config.suppressHostByProvider();
- assertNotNull("suppressHostByProvider should not be null", supprsuppressHostByProvider);
- assertThat(supprsuppressHostByProvider.size(), is(1));
- 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/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java
deleted file mode 100644
index ddf90bb..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/config/SegmentRoutingDeviceConfigTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.ConfigApplyDelegate;
-
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests for class {@link SegmentRoutingDeviceConfig}.
- */
-public class SegmentRoutingDeviceConfigTest {
- private SegmentRoutingDeviceConfig config;
- private SegmentRoutingDeviceConfig ipv6Config;
- private SegmentRoutingDeviceConfig pairConfig;
- private SegmentRoutingDeviceConfig invalidConfig;
- private Map<Integer, Set<Integer>> adjacencySids1;
- private Map<Integer, Set<Integer>> adjacencySids2;
- private static final DeviceId PAIR_DEVICE_ID = DeviceId.deviceId("of:123456789ABCDEF0");
- private static final PortNumber PAIR_LOCAL_PORT = PortNumber.portNumber(10);
-
- @Before
- public void setUp() throws Exception {
- InputStream jsonStream = SegmentRoutingDeviceConfigTest.class
- .getResourceAsStream("/device.json");
- InputStream ipv6JsonStream = SegmentRoutingDeviceConfigTest.class
- .getResourceAsStream("/device-ipv6.json");
- InputStream pairJsonStream = SegmentRoutingDeviceConfigTest.class
- .getResourceAsStream("/device-pair.json");
- InputStream invalidJsonStream = SegmentRoutingDeviceConfigTest.class
- .getResourceAsStream("/device-invalid.json");
-
- adjacencySids1 = new HashMap<>();
- Set<Integer> ports1 = new HashSet<>();
- ports1.add(2);
- ports1.add(3);
- adjacencySids1.put(100, ports1);
- Set<Integer> ports2 = new HashSet<>();
- ports2.add(4);
- ports2.add(5);
- adjacencySids1.put(200, ports2);
-
- adjacencySids2 = new HashMap<>();
- Set<Integer> ports3 = new HashSet<>();
- ports3.add(6);
- adjacencySids2.put(300, ports3);
-
- DeviceId subject = DeviceId.deviceId("of:0000000000000001");
- String key = "segmentrouting";
- ObjectMapper mapper = new ObjectMapper();
- JsonNode jsonNode = mapper.readTree(jsonStream);
- JsonNode ipv6JsonNode = mapper.readTree(ipv6JsonStream);
- JsonNode pairJsonNode = mapper.readTree(pairJsonStream);
- JsonNode invalidJsonNode = mapper.readTree(invalidJsonStream);
- ConfigApplyDelegate delegate = new MockDelegate();
-
- config = new SegmentRoutingDeviceConfig();
- config.init(subject, key, jsonNode, mapper, delegate);
-
- ipv6Config = new SegmentRoutingDeviceConfig();
- ipv6Config.init(subject, key, ipv6JsonNode, mapper, delegate);
-
- pairConfig = new SegmentRoutingDeviceConfig();
- pairConfig.init(subject, key, pairJsonNode, mapper, delegate);
-
- invalidConfig = new SegmentRoutingDeviceConfig();
- invalidConfig.init(subject, key, invalidJsonNode, mapper, delegate);
- }
-
- @Test
- public void testIsValid() {
- assertTrue(config.isValid());
- assertTrue(ipv6Config.isValid());
- assertTrue(pairConfig.isValid());
- assertFalse(invalidConfig.isValid());
- }
-
- @Test
- public void testName() throws Exception {
- assertTrue(config.name().isPresent());
- assertThat(config.name().get(), is("Leaf-R1"));
- }
-
- @Test
- public void testSetName() throws Exception {
- config.setName("Spine-R1");
- assertTrue(config.name().isPresent());
- assertThat(config.name().get(), is("Spine-R1"));
- }
-
- @Test
- public void testRouterIp() throws Exception {
- assertThat(config.routerIpv4(), is(IpAddress.valueOf("10.0.1.254")));
- assertThat(ipv6Config.routerIpv4(), is(IpAddress.valueOf("10.0.1.254")));
- assertThat(ipv6Config.routerIpv6(), is(IpAddress.valueOf("2000::c0a8:0101")));
- }
-
- @Test
- public void testSetRouterIp() throws Exception {
- config.setRouterIpv4("10.0.2.254");
- assertThat(config.routerIpv4(), is(IpAddress.valueOf("10.0.2.254")));
- ipv6Config.setRouterIpv4("10.0.2.254");
- assertThat(ipv6Config.routerIpv4(), is(IpAddress.valueOf("10.0.2.254")));
- ipv6Config.setRouterIpv6("2000::c0a9:0101");
- assertThat(ipv6Config.routerIpv6(), is(IpAddress.valueOf("2000::c0a9:0101")));
- }
-
- @Test
- public void testRouterMac() throws Exception {
- assertThat(config.routerMac(), is(MacAddress.valueOf("00:00:00:00:01:80")));
- }
-
- @Test
- public void testSetRouterMac() throws Exception {
- config.setRouterMac("00:00:00:00:02:80");
- assertThat(config.routerMac(), is(MacAddress.valueOf("00:00:00:00:02:80")));
- }
-
- @Test
- public void testNodeSid() throws Exception {
- assertThat(config.nodeSidIPv4(), is(101));
- assertThat(ipv6Config.nodeSidIPv4(), is(101));
- assertThat(ipv6Config.nodeSidIPv6(), is(111));
- }
-
- @Test
- public void testSetNodeSid() throws Exception {
- config.setNodeSidIPv4(200);
- assertThat(config.nodeSidIPv4(), is(200));
- ipv6Config.setNodeSidIPv4(200);
- assertThat(ipv6Config.nodeSidIPv4(), is(200));
- ipv6Config.setNodeSidIPv6(201);
- assertThat(ipv6Config.nodeSidIPv6(), is(201));
- }
-
- @Test
- public void testIsEdgeRouter() throws Exception {
- assertThat(config.isEdgeRouter(), is(true));
- }
-
- @Test
- public void testSetIsEdgeRouter() throws Exception {
- config.setIsEdgeRouter(false);
- assertThat(config.isEdgeRouter(), is(false));
- }
-
- @Test
- public void testAdjacencySids() throws Exception {
- assertThat(config.adjacencySids(), is(adjacencySids1));
- }
-
- @Test
- public void testSetAdjacencySids() throws Exception {
- config.setAdjacencySids(adjacencySids2);
- assertThat(config.adjacencySids(), is(adjacencySids2));
- }
-
- @Test
- public void testPairDeviceId() throws Exception {
- assertNull(config.pairDeviceId());
- assertNull(ipv6Config.pairDeviceId());
- assertThat(pairConfig.pairDeviceId(), is(PAIR_DEVICE_ID));
- }
-
- @Test
- public void testSetPairDeviceId() throws Exception {
- config.setPairDeviceId(PAIR_DEVICE_ID);
- assertThat(config.pairDeviceId(), is(PAIR_DEVICE_ID));
- }
-
- @Test
- public void testPairLocalPort() throws Exception {
- assertNull(config.pairLocalPort());
- assertNull(ipv6Config.pairLocalPort());
- assertThat(pairConfig.pairLocalPort(), is(PAIR_LOCAL_PORT));
- }
-
- @Test
- public void testSetPairLocalPort() throws Exception {
- config.setPairLocalPort(PAIR_LOCAL_PORT);
- assertThat(config.pairLocalPort(), is(PAIR_LOCAL_PORT));
- }
-
- private class MockDelegate implements ConfigApplyDelegate {
- @Override
- public void onApply(Config configFile) {
- }
- }
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/grouphandler/DestinationSetTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/grouphandler/DestinationSetTest.java
deleted file mode 100644
index b41fe07..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/grouphandler/DestinationSetTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.grouphandler;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.net.DeviceId;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class DestinationSetTest {
- DestinationSet ds1, ds2, ds3, ds4, ds5, ds6;
- DeviceId d201, d202;
- int el201, el202;
-
- @Before
- public void setUp() {
- d201 = DeviceId.deviceId("of:0000000000000201");
- d202 = DeviceId.deviceId("of:0000000000000202");
- el201 = 201;
- el202 = 202;
- ds1 = DestinationSet.createTypePushNone(d201);
- ds2 = DestinationSet.createTypePushBos(el201, d201);
- ds3 = DestinationSet.createTypePushBos(el201, d201, el202, d202);
- ds4 = DestinationSet.createTypePushBos(DestinationSet.NO_EDGE_LABEL, d201,
- DestinationSet.NO_EDGE_LABEL, d202);
- ds5 = DestinationSet.createTypePopNotBos(d201);
- ds6 = DestinationSet.createTypeSwapBos(el201, d201);
- }
-
- @Test
- public void testIsValid() {
- assertTrue(!ds1.notBos());
- assertTrue(!ds1.swap());
- assertTrue(ds1.getEdgeLabel(d201) == DestinationSet.NO_EDGE_LABEL);
- assertTrue(ds1.getDestinationSwitches().size() == 1);
-
- assertTrue(!ds2.notBos());
- assertTrue(!ds2.swap());
- assertTrue(ds2.getEdgeLabel(d201) == el201);
- assertTrue(ds2.getDestinationSwitches().size() == 1);
-
- assertTrue(!ds3.notBos());
- assertTrue(!ds3.swap());
- assertTrue(ds3.getEdgeLabel(d201) == el201);
- assertTrue(ds3.getEdgeLabel(d202) == el202);
- assertTrue(ds3.getDestinationSwitches().size() == 2);
-
- assertTrue(!ds4.notBos());
- assertTrue(!ds4.swap());
- assertTrue(ds4.getEdgeLabel(d201) == DestinationSet.NO_EDGE_LABEL);
- assertTrue(ds4.getEdgeLabel(d202) == DestinationSet.NO_EDGE_LABEL);
- assertTrue(ds4.getDestinationSwitches().size() == 2);
-
- assertFalse(ds1.equals(ds2));
- assertFalse(ds1.equals(ds4));
- assertFalse(ds3.equals(ds4));
- assertFalse(ds2.equals(ds3));
- assertFalse(ds1.equals(ds3));
-
- assertFalse(ds1.equals(ds5));
- assertFalse(ds2.equals(ds6));
- }
-
-
- @Test
- public void testOneDestinationWithoutLabel() {
- DestinationSet testds = DestinationSet.createTypePushNone(d201);
- assertTrue(testds.equals(ds1)); // match
-
- testds = DestinationSet.createTypePopNotBos(d201);
- assertFalse(testds.equals(ds1)); // wrong notBos
- assertTrue(testds.equals(ds5)); // correct notBos
-
- testds = DestinationSet.createTypePushNone(d202);
- assertFalse(testds.equals(ds1)); //wrong device
-
- testds = DestinationSet.createTypePushBos(el201, d201);
- assertFalse(testds.equals(ds1)); // wrong label
-
- testds = DestinationSet.createTypePushBos(-1, d201, -1, d202);
- assertFalse(testds.equals(ds1)); // 2-devs should not match
-
- testds = DestinationSet.createTypeSwapBos(el201, d201);
- assertFalse(testds.equals(ds1)); // wrong type and label
- assertTrue(testds.equals(ds6)); // correct swap
-
- testds = DestinationSet.createTypeSwapNotBos(el201, d201);
- assertFalse(testds.equals(ds6)); // wrong notbos
- }
-
-
-
- @Test
- public void testOneDestinationWithLabel() {
- DestinationSet testds = DestinationSet.createTypePushBos(203, d202);
- assertFalse(testds.equals(ds2)); //wrong label
-
- testds = DestinationSet.createTypePushBos(201, d202);
- assertFalse(testds.equals(ds2)); //wrong device
-
- testds = DestinationSet.createTypePushBos(201, DeviceId.deviceId("of:0000000000000201"));
- assertTrue(testds.equals(ds2)); // match
-
- testds = DestinationSet.createTypePushNone(d201);
- assertFalse(testds.equals(ds2)); // wrong label
-
- testds = DestinationSet.createTypePushBos(el201, d201, el202, d202);
- assertFalse(testds.equals(ds1)); // 2-devs should not match
- }
-
- @Test
- public void testDestPairWithLabel() {
- DestinationSet testds = DestinationSet.createTypePushBos(el201, d201, el202, d202);
- assertTrue(testds.equals(ds3)); // match same switches, same order
- assertTrue(testds.hashCode() == ds3.hashCode());
-
- testds = DestinationSet.createTypePushBos(el202, d202, el201, d201);
- assertTrue(testds.equals(ds3)); // match same switches, order reversed
- assertTrue(testds.hashCode() == ds3.hashCode());
-
- testds = DestinationSet.createTypePushBos(el202, d202);
- assertFalse(testds.equals(ds3)); // one less switch should not match
- assertFalse(testds.hashCode() == ds3.hashCode());
-
- testds = DestinationSet.createTypePushBos(el201, d201);
- assertFalse(testds.equals(ds3)); // one less switch should not match
- assertFalse(testds.hashCode() == ds3.hashCode());
-
- testds = DestinationSet.createTypePushBos(el201, d201, 0, DeviceId.NONE);
- assertFalse(testds.equals(ds3)); // one less switch should not match
- assertFalse(testds.hashCode() == ds3.hashCode());
-
- testds = DestinationSet.createTypePushBos(el201, d202, el201, d201);
- assertFalse(testds.equals(ds3)); // wrong labels
- assertFalse(testds.hashCode() == ds3.hashCode());
-
- testds = DestinationSet.createTypePushBos(el202, d202, el201, d202);
- assertFalse(testds.equals(ds3)); // wrong device
- assertFalse(testds.hashCode() == ds3.hashCode());
-
- testds = DestinationSet.createTypePushBos(
- el202, DeviceId.deviceId("of:0000000000000205"),
- el201, d201);
- assertFalse(testds.equals(ds3)); // wrong device
- assertFalse(testds.hashCode() == ds3.hashCode());
- }
-
- @Test
- public void testDestPairWithoutLabel() {
- DestinationSet testds = DestinationSet.createTypePushBos(-1, d201, -1, d202);
- assertTrue(testds.equals(ds4)); // match same switches, same order
- assertTrue(testds.hashCode() == ds4.hashCode());
-
- testds = DestinationSet.createTypePushBos(-1, d202, -1, d201);
- assertTrue(testds.equals(ds4)); // match same switches, order reversed
- assertTrue(testds.hashCode() == ds4.hashCode());
-
- testds = DestinationSet.createTypePushBos(-1, d202);
- assertFalse(testds.equals(ds4)); // one less switch should not match
- assertFalse(testds.hashCode() == ds4.hashCode());
-
- testds = DestinationSet.createTypePushBos(-1, d201);
- assertFalse(testds.equals(ds4)); // one less switch should not match
- assertFalse(testds.hashCode() == ds4.hashCode());
-
- testds = DestinationSet.createTypePushBos(-1, d201, 0, DeviceId.NONE);
- assertFalse(testds.equals(ds4)); // one less switch should not match
- assertFalse(testds.hashCode() == ds4.hashCode());
-
- testds = DestinationSet.createTypePushBos(el201, d201, -1, d202);
- assertFalse(testds.equals(ds4)); // wrong labels
- assertFalse(testds.hashCode() == ds4.hashCode());
-
- testds = DestinationSet.createTypePushBos(-1, d202, -1, d202);
- assertFalse(testds.equals(ds4)); // wrong device
- assertFalse(testds.hashCode() == ds4.hashCode());
-
- testds = DestinationSet.createTypePushBos(
- -1, DeviceId.deviceId("of:0000000000000205"),
- -1, d201);
- assertFalse(testds.equals(ds4)); // wrong device
- assertFalse(testds.hashCode() == ds4.hashCode());
- }
-
-}
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/pwaas/PwaasUtilTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/pwaas/PwaasUtilTest.java
deleted file mode 100644
index 1d9f07e..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/pwaas/PwaasUtilTest.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.pwaas;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.onlab.junit.TestUtils;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceService;
-import org.onosproject.segmentrouting.MockDevice;
-
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-public class PwaasUtilTest {
- private static final DeviceId DID1 = DeviceId.deviceId("of:1");
- private static final DeviceId DID2 = DeviceId.deviceId("of:2");
- private static final DeviceId DID99 = DeviceId.deviceId("of:99");
- private static final PortNumber PN1 = PortNumber.portNumber(1);
- private static final PortNumber PN2 = PortNumber.portNumber(2);
- private static final PortNumber PN99 = PortNumber.portNumber(99);
- private static final ConnectPoint CP11 = new ConnectPoint(DID1, PN1);
- private static final ConnectPoint CP12 = new ConnectPoint(DID1, PN2);
- private static final ConnectPoint CP21 = new ConnectPoint(DID2, PN1);
- private static final ConnectPoint CP22 = new ConnectPoint(DID2, PN2);
- private static final VlanId V1 = VlanId.vlanId((short) 1);
- private static final VlanId V2 = VlanId.vlanId((short) 2);
- private static final Device D1 = new MockDevice(DID1, null);
- private static final Device D2 = new MockDevice(DID2, null);
- private static final Port P11 = new DefaultPort(D1, PN1, true);
- private static final Port P12 = new DefaultPort(D1, PN2, true);
- private static final Port P21 = new DefaultPort(D2, PN1, true);
- private static final Port P22 = new DefaultPort(D2, PN2, true);
- private static final Interface I11 = new Interface("I11", CP11, Lists.newArrayList(), MacAddress.NONE,
- VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
- private static final Interface I12 = new Interface("I12", CP12, Lists.newArrayList(), MacAddress.NONE,
- VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
- private static final Interface I21 = new Interface("I21", CP21, Lists.newArrayList(), MacAddress.NONE,
- VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
- private static final Interface I22 = new Interface("I22", CP22, Lists.newArrayList(), MacAddress.NONE,
- VlanId.NONE, VlanId.NONE, Sets.newHashSet(VlanId.NONE), VlanId.NONE);
-
- private ConnectPoint cp1;
- private ConnectPoint cp2;
- private VlanId ingressInner;
- private VlanId ingressOuter;
- private VlanId egressInner;
- private VlanId egressOuter;
- private static final Long TUNNEL_ID = (long) 1234;
-
- @Before
- public void setUp() {
- DeviceService deviceService = createNiceMock(DeviceService.class);
- InterfaceService intfService = createNiceMock(InterfaceService.class);
- TestUtils.setField(PwaasUtil.class, "deviceService", deviceService);
- TestUtils.setField(PwaasUtil.class, "intfService", intfService);
-
- expect(deviceService.getDevice(DID1)).andReturn(D1).anyTimes();
- expect(deviceService.getDevice(DID2)).andReturn(D2).anyTimes();
- expect(deviceService.getPort(CP11)).andReturn(P11).anyTimes();
- expect(deviceService.getPort(CP12)).andReturn(P12).anyTimes();
- expect(deviceService.getPort(CP21)).andReturn(P21).anyTimes();
- expect(deviceService.getPort(CP22)).andReturn(P22).anyTimes();
- expect(intfService.getInterfacesByPort(CP11)).andReturn(Sets.newHashSet(I11)).anyTimes();
- expect(intfService.getInterfacesByPort(CP12)).andReturn(Sets.newHashSet(I12)).anyTimes();
- expect(intfService.getInterfacesByPort(CP21)).andReturn(Sets.newHashSet(I21)).anyTimes();
- expect(intfService.getInterfacesByPort(CP22)).andReturn(Sets.newHashSet(I22)).anyTimes();
- replay(deviceService);
- replay(intfService);
- }
-
- @Rule
- public final ExpectedException exception = ExpectedException.none();
-
- @Test
- public void verifyPolicy() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = V2;
- egressInner = V1;
- egressOuter = V2;
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
-
- ingressInner = VlanId.NONE;
- ingressOuter = VlanId.NONE;
- egressInner = VlanId.NONE;
- egressOuter = VlanId.NONE;
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyOnSameDevice() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID1, PN2);
- ingressInner = VlanId.NONE;
- ingressOuter = VlanId.NONE;
- egressInner = VlanId.NONE;
- egressOuter = VlanId.NONE;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_SAME_DEV, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyEmptyInnerCp1() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = VlanId.NONE;
- ingressOuter = V1;
- egressInner = VlanId.NONE;
- egressOuter = VlanId.NONE;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_EMPTY_INNER_WHEN_OUTER_PRESENT, TUNNEL_ID, "cp1"));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyEmptyInnerCp2() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = VlanId.NONE;
- ingressOuter = VlanId.NONE;
- egressInner = VlanId.NONE;
- egressOuter = V1;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_EMPTY_INNER_WHEN_OUTER_PRESENT, TUNNEL_ID, "cp2"));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyVlanWildcard() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = VlanId.ANY;
- ingressOuter = VlanId.NONE;
- egressInner = VlanId.NONE;
- egressOuter = VlanId.NONE;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_WILDCARD_VLAN, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
-
- @Test
- public void verifyPolicyDeviceServiceNotAvailable() {
- TestUtils.setField(PwaasUtil.class, "deviceService", null);
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = V2;
- egressInner = V1;
- egressOuter = V2;
- exception.expect(IllegalStateException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_SERVICE_UNAVAIL, "DeviceService"));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyDoubleToUntagged() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = V2;
- egressInner = VlanId.NONE;
- egressOuter = VlanId.NONE;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_DOUBLE_TO_UNTAGGED, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyDoubleToSingle() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = V2;
- egressInner = V1;
- egressOuter = VlanId.NONE;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_DOUBLE_TO_SINGLE, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicySingleToUntagged() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = VlanId.NONE;
- egressInner = VlanId.NONE;
- egressOuter = VlanId.NONE;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_SINGLE_TO_UNTAGGED, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyVlanTranslation() {
- cp1 = new ConnectPoint(DID1, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = VlanId.NONE;
- egressInner = V2;
- egressOuter = VlanId.NONE;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_VLAN_TRANSLATION, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyDeviceNotFound() {
- cp1 = new ConnectPoint(DID99, PN1);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = V2;
- egressInner = V1;
- egressOuter = V2;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_DEV_NOT_FOUND, DID99, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-
- @Test
- public void verifyPolicyPortNotFound() {
- cp1 = new ConnectPoint(DID1, PN99);
- cp2 = new ConnectPoint(DID2, PN2);
- ingressInner = V1;
- ingressOuter = V2;
- egressInner = V1;
- egressOuter = V2;
- exception.expect(IllegalArgumentException.class);
- exception.expectMessage(String.format(PwaasUtil.ERR_PORT_NOT_FOUND, PN99, DID1, TUNNEL_ID));
- PwaasUtil.verifyPolicy(cp1, cp2, ingressInner, ingressOuter, egressInner, egressOuter, TUNNEL_ID);
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodecTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodecTest.java
deleted file mode 100644
index bac9ff4..0000000
--- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/xconnect/api/XconnectCodecTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.xconnect.api;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.VlanId;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import org.onosproject.codec.impl.MockCodecContext;
-import org.onosproject.net.DeviceId;
-
-import java.io.InputStream;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
-public class XconnectCodecTest {
- private static final DeviceId DEVICE_ID = DeviceId.deviceId("of:1");
- private static final VlanId VLAN_VID = VlanId.vlanId((short) 10);
- private static final XconnectKey KEY = new XconnectKey(DEVICE_ID, VLAN_VID);
- private static final XconnectEndpoint EP1 = XconnectEndpoint.fromString("1");
- private static final XconnectEndpoint EP2 = XconnectEndpoint.fromString("2");
- private static final XconnectEndpoint EP3 = XconnectEndpoint.fromString("LB:5");
-
- private CodecContext context;
- private JsonCodec<XconnectDesc> codec;
-
- @Before
- public void setUp() throws Exception {
- context = new MockCodecContext();
- codec = new XconnectCodec();
- }
-
- @Test
- public void testEncodePort() throws Exception {
- Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP2);
- XconnectDesc desc1 = new XconnectDesc(KEY, endpoints1);
-
- ObjectMapper mapper = new ObjectMapper();
- InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect1.json");
- JsonNode expected = mapper.readTree(jsonStream1);
-
- JsonNode actual = codec.encode(desc1, context);
-
- assertEquals(expected.get(XconnectCodec.DEVICE_ID), actual.get(XconnectCodec.DEVICE_ID));
- assertEquals(expected.get(XconnectCodec.VLAN_ID).asInt(), actual.get(XconnectCodec.VLAN_ID).asInt());
- assertEquals(expected.get(XconnectCodec.ENDPOINTS), actual.get(XconnectCodec.ENDPOINTS));
- }
-
- @Test
- public void testDecodePort() throws Exception {
- Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP2);
- XconnectDesc expected = new XconnectDesc(KEY, endpoints1);
-
- ObjectMapper mapper = new ObjectMapper();
- InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect1.json");
- ObjectNode objectNode = mapper.readTree(jsonStream1).deepCopy();
-
- XconnectDesc actual = codec.decode(objectNode, context);
-
- assertEquals(expected, actual);
- }
-
- @Test
- public void testEncodeLb() throws Exception {
- Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP3);
- XconnectDesc desc1 = new XconnectDesc(KEY, endpoints1);
-
- ObjectMapper mapper = new ObjectMapper();
- InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect2.json");
- JsonNode expected = mapper.readTree(jsonStream1);
-
- JsonNode actual = codec.encode(desc1, context);
-
- assertEquals(expected.get(XconnectCodec.DEVICE_ID), actual.get(XconnectCodec.DEVICE_ID));
- assertEquals(expected.get(XconnectCodec.VLAN_ID).asInt(), actual.get(XconnectCodec.VLAN_ID).asInt());
- assertEquals(expected.get(XconnectCodec.ENDPOINTS), actual.get(XconnectCodec.ENDPOINTS));
- }
-
- @Test
- public void testDecodeLb() throws Exception {
- Set<XconnectEndpoint> endpoints1 = Sets.newHashSet(EP1, EP3);
- XconnectDesc expected = new XconnectDesc(KEY, endpoints1);
-
- ObjectMapper mapper = new ObjectMapper();
- InputStream jsonStream1 = XconnectCodecTest.class.getResourceAsStream("/xconnect2.json");
- ObjectNode objectNode = mapper.readTree(jsonStream1).deepCopy();
-
- XconnectDesc actual = codec.decode(objectNode, context);
-
- assertEquals(expected, actual);
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/resources/app-ecmp.json b/apps/segmentrouting/app/src/test/resources/app-ecmp.json
deleted file mode 100644
index e94b1c5..0000000
--- a/apps/segmentrouting/app/src/test/resources/app-ecmp.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "vRouterMacs" : [
- "00:00:00:00:00:01",
- "00:00:00:00:00:02"
- ],
- "suppressSubnet" : [
- "of:1/1",
- "of:1/2"
- ],
- "suppressHostByPort" : [
- "of:1/1",
- "of:1/2"
- ],
- "suppressHostByProvider" : [
- "org.onosproject.provider.host",
- "org.onosproject.netcfghost"
- ],
- "MPLS-ECMP" : true
-}
diff --git a/apps/segmentrouting/app/src/test/resources/app-invalid.json b/apps/segmentrouting/app/src/test/resources/app-invalid.json
deleted file mode 100644
index 01508f8..0000000
--- a/apps/segmentrouting/app/src/test/resources/app-invalid.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "vRouterMacs" : [
- "00:00:00:00:00:01",
- "00:00:00:00:00:02"
- ],
- "suppressSubnet" : [
- "of:1/1",
- "of:1/2"
- ],
- "suppressHostByPort" : [
- "of:1/1",
- "wrongPort"
- ],
- "suppressHostByProvider" : []
-}
diff --git a/apps/segmentrouting/app/src/test/resources/app.json b/apps/segmentrouting/app/src/test/resources/app.json
deleted file mode 100644
index 2e59b0d..0000000
--- a/apps/segmentrouting/app/src/test/resources/app.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "vRouterMacs" : [
- "00:00:00:00:00:01",
- "00:00:00:00:00:02"
- ],
- "suppressSubnet" : [
- "of:1/1",
- "of:1/2"
- ],
- "suppressHostByPort" : [
- "of:1/1",
- "of:1/2"
- ],
- "suppressHostByProvider" : [
- "org.onosproject.provider.host",
- "org.onosproject.netcfghost"
- ],
- "blackholeIps": [
- "10.0.0.0/8"
- ]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/blocked-ports-alt.json b/apps/segmentrouting/app/src/test/resources/blocked-ports-alt.json
deleted file mode 100644
index 3d8749e..0000000
--- a/apps/segmentrouting/app/src/test/resources/blocked-ports-alt.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "of:0000000000000001": ["1-9"],
- "of:0000000000000003": ["7"],
- "of:0000000000000004": ["1"]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/blocked-ports.json b/apps/segmentrouting/app/src/test/resources/blocked-ports.json
deleted file mode 100644
index 2543f3d..0000000
--- a/apps/segmentrouting/app/src/test/resources/blocked-ports.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "of:0000000000000001": ["1-4", "7-9"],
- "of:0000000000000003": ["7-9"],
- "of:0000000000000004": ["1", "5", "9"]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device-invalid.json b/apps/segmentrouting/app/src/test/resources/device-invalid.json
deleted file mode 100644
index dfcbdb8..0000000
--- a/apps/segmentrouting/app/src/test/resources/device-invalid.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name" : "Leaf-R1",
- "ipv4NodeSid" : 101,
- "ipv4Loopback" : "10.0.1.254",
- "routerMac" : "00:00:00:00:01:80",
- "isEdgeRouter" : true,
- "adjacencySids" : [
- { "adjSid" : 100, "ports" : [2, 3] },
- { "adjSid" : 200, "ports" : [4, 5] }
- ],
- "pairDeviceId" : "of:123456789ABCDEF0"
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device-ipv6.json b/apps/segmentrouting/app/src/test/resources/device-ipv6.json
deleted file mode 100644
index 9832f8c..0000000
--- a/apps/segmentrouting/app/src/test/resources/device-ipv6.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name" : "Leaf-R1",
- "ipv4NodeSid" : 101,
- "ipv4Loopback" : "10.0.1.254",
- "ipv6NodeSid" : 111,
- "ipv6Loopback" : "2000::c0a8:0101",
- "routerMac" : "00:00:00:00:01:80",
- "isEdgeRouter" : true,
- "adjacencySids" : [
- { "adjSid" : 100, "ports" : [2, 3] },
- { "adjSid" : 200, "ports" : [4, 5] }
- ]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device-pair.json b/apps/segmentrouting/app/src/test/resources/device-pair.json
deleted file mode 100644
index c699ff5..0000000
--- a/apps/segmentrouting/app/src/test/resources/device-pair.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name" : "Leaf-R1",
- "ipv4NodeSid" : 101,
- "ipv4Loopback" : "10.0.1.254",
- "routerMac" : "00:00:00:00:01:80",
- "isEdgeRouter" : true,
- "adjacencySids" : [
- { "adjSid" : 100, "ports" : [2, 3] },
- { "adjSid" : 200, "ports" : [4, 5] }
- ],
- "pairDeviceId" : "of:123456789ABCDEF0",
- "pairLocalPort" : "10"
-}
diff --git a/apps/segmentrouting/app/src/test/resources/device.json b/apps/segmentrouting/app/src/test/resources/device.json
deleted file mode 100644
index 83aec6e..0000000
--- a/apps/segmentrouting/app/src/test/resources/device.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name" : "Leaf-R1",
- "ipv4NodeSid" : 101,
- "ipv4Loopback" : "10.0.1.254",
- "routerMac" : "00:00:00:00:01:80",
- "isEdgeRouter" : true,
- "adjacencySids" : [
- { "adjSid" : 100, "ports" : [2, 3] },
- { "adjSid" : 200, "ports" : [4, 5] }
- ]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/interface1.json b/apps/segmentrouting/app/src/test/resources/interface1.json
deleted file mode 100644
index 0f7123f..0000000
--- a/apps/segmentrouting/app/src/test/resources/interface1.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "ips" : [ "10.0.1.254/24" ],
- "vlan-untagged": 10
- }
-]
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/resources/interface2.json b/apps/segmentrouting/app/src/test/resources/interface2.json
deleted file mode 100644
index 114fbf5..0000000
--- a/apps/segmentrouting/app/src/test/resources/interface2.json
+++ /dev/null
@@ -1,6 +0,0 @@
-[
- {
- "ips" : [ "10.0.2.254/24" ],
- "vlan-untagged": 20
- }
-]
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-conflicting-vlan.json b/apps/segmentrouting/app/src/test/resources/pwaas-conflicting-vlan.json
deleted file mode 100644
index fac162d..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-conflicting-vlan.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "1": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000002/2",
- "cP1InnerTag": "10",
- "cP1OuterTag": "20",
- "cP2InnerTag": "11",
- "cP2OuterTag": "21",
- "mode": "RAW",
- "sdTag": "",
- "pwLabel": "255"
- },
- "20": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000002/2",
- "cP1InnerTag": "100",
- "cP1OuterTag": "",
- "cP2InnerTag": "21",
- "cP2OuterTag": "",
- "mode": "RAW",
- "sdTag": "",
- "pwLabel": "1255"
- }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-mode.json b/apps/segmentrouting/app/src/test/resources/pwaas-invalid-mode.json
deleted file mode 100644
index af0a9d1..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-mode.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "1": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000011/1",
- "cP1InnerTag": "10",
- "cP1OuterTag": "20",
- "cP2InnerTag": "11",
- "cP2OuterTag": "",
- "mode": "UNDEFINED_MODED",
- "sdTag": "40",
- "pwLabel": "255"
- }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-pwlabel.json b/apps/segmentrouting/app/src/test/resources/pwaas-invalid-pwlabel.json
deleted file mode 100644
index 66697f5..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-pwlabel.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "1": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000011/1",
- "cP1InnerTag": "10",
- "cP1OuterTag": "20",
- "cP2InnerTag": "11",
- "cP2OuterTag": "",
- "mode": "1",
- "sdTag": "40",
- "pwLabel": "255.555551"
- }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-vlan.json b/apps/segmentrouting/app/src/test/resources/pwaas-invalid-vlan.json
deleted file mode 100644
index b556e06..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas-invalid-vlan.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "1": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000002/2",
- "cP1InnerTag": "10",
- "cP1OuterTag": "20",
- "cP2InnerTag": "11",
- "cP2OuterTag": "21",
- "mode": "RAW",
- "sdTag": "",
- "pwLabel": "255"
- },
- "20": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000002/2",
- "cP1InnerTag": "100",
- "cP1OuterTag": "200.55",
- "cP2InnerTag": "1100",
- "cP2OuterTag": "210",
- "mode": "RAW",
- "sdTag": "",
- "pwLabel": "1255"
- }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/pwaas.json b/apps/segmentrouting/app/src/test/resources/pwaas.json
deleted file mode 100644
index 2a58b4e..0000000
--- a/apps/segmentrouting/app/src/test/resources/pwaas.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "1": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000002/1",
- "cP1InnerTag": "10",
- "cP1OuterTag": "20",
- "cP2InnerTag": "10",
- "cP2OuterTag": "21",
- "mode": "RAW",
- "sdTag": "",
- "pwLabel": "255"
- },
- "20": {
- "cP1": "of:0000000000000001/1",
- "cP2": "of:0000000000000002/1",
- "cP1InnerTag": "100",
- "cP1OuterTag": "200",
- "cP2InnerTag": "100",
- "cP2OuterTag": "210",
- "mode": "RAW",
- "sdTag": "",
- "pwLabel": "1255"
- }
-}
diff --git a/apps/segmentrouting/app/src/test/resources/xconnect1.json b/apps/segmentrouting/app/src/test/resources/xconnect1.json
deleted file mode 100644
index d8990d4..0000000
--- a/apps/segmentrouting/app/src/test/resources/xconnect1.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "deviceId": "of:1",
- "vlanId": 10,
- "endpoints": ["1", "2"]
-}
diff --git a/apps/segmentrouting/app/src/test/resources/xconnect2.json b/apps/segmentrouting/app/src/test/resources/xconnect2.json
deleted file mode 100644
index 61919da..0000000
--- a/apps/segmentrouting/app/src/test/resources/xconnect2.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "deviceId": "of:1",
- "vlanId": 10,
- "endpoints": ["1", "LB:5"]
-}
diff --git a/apps/segmentrouting/web/BUILD b/apps/segmentrouting/web/BUILD
deleted file mode 100644
index 67ee7d9..0000000
--- a/apps/segmentrouting/web/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + JACKSON + [
- "@javax_ws_rs_api//jar",
- "//utils/rest:onlab-rest",
- "//apps/segmentrouting/app:onos-apps-segmentrouting-app",
-]
-
-osgi_jar_with_tests(
- api_description = "REST API for Segment Routing Application",
- api_package = "org.onosproject.segmentrouting.web",
- api_title = "Segment Routing Rest Server",
- api_version = "1.0",
- web_context = "/onos/segmentrouting",
- deps = COMPILE_DEPS,
-)
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java
deleted file mode 100644
index 8202eed..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * Query multicast trees.
- */
-@Path("mcast")
-public class McastWebResource extends AbstractWebResource {
-
- private ObjectNode encodeMcastTrees(String gAddr, String source) {
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Set<IpAddress> mcastGroups = ImmutableSet.copyOf(srService.getMcastLeaders(null)
- .keySet());
-
- if (!isNullOrEmpty(gAddr)) {
- mcastGroups = mcastGroups.stream()
- .filter(mcastIp -> mcastIp.equals(IpAddress.valueOf(gAddr)))
- .collect(Collectors.toSet());
- }
-
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode root = mapper.createObjectNode();
-
- // Print the trees for each group or build json objects
- mcastGroups.forEach(group -> {
- // We want to use source cp only for a specific group
- ConnectPoint sourcecp = null;
- if (!isNullOrEmpty(source) &&
- !isNullOrEmpty(gAddr)) {
- sourcecp = ConnectPoint.deviceConnectPoint(source);
- }
- Multimap<ConnectPoint, List<ConnectPoint>> mcastTree = srService.getMcastTrees(group, sourcecp);
- // Build a json object for each group
- root.putPOJO(group.toString(), json(mcastTree));
-
- });
- return root;
- }
-
- private ObjectNode json(Multimap<ConnectPoint, List<ConnectPoint>> mcastTree) {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode jsonSinks = mapper.createObjectNode();
- mcastTree.asMap().forEach((sink, paths) -> {
- ArrayNode jsonPaths = mapper.createArrayNode();
- paths.forEach(path -> {
- ArrayNode jsonPath = mapper.createArrayNode();
- path.forEach(connectPoint -> jsonPath.add(connectPoint.toString()));
- jsonPaths.addPOJO(jsonPath);
- });
- jsonSinks.putPOJO(sink.toString(), jsonPaths);
- });
- return jsonSinks;
- }
-
- /**
- * Get all multicast trees.
- * Returns an object of the multicast trees.
- *
- * @return status of OK
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getMcastTrees() {
- ObjectNode root = encodeMcastTrees(null, null);
- return ok(root).build();
- }
-
- /**
- * Get the multicast trees of a group.
- *
- * @param group group IP address
- * @return 200 OK with a multicast routes
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("{group}")
- public Response getRoute(@PathParam("group") String group) {
- ObjectNode root = encodeMcastTrees(group, null);
- return ok(root).build();
- }
-
- /**
- * Get the multicast tree of a group.
- *
- * @param group group IP address
- * @param sourcecp source connect point
- * @return 200 OK with a multicast routes
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("{group}/{sourcecp}")
- public Response getRoute(@PathParam("group") String group,
- @PathParam("sourcecp") String sourcecp) {
- ObjectNode root = encodeMcastTrees(group, sourcecp);
- return ok(root).build();
- }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
deleted file mode 100644
index 0dedc7c..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.TunnelPolicy;
-
-/**
- * Codec of Policy class.
- */
-public final class PolicyCodec extends JsonCodec<Policy> {
-
- // JSON field names
- private static final String POLICY_ID = "policy_id";
- private static final String PRIORITY = "priority";
- private static final String TYPE = "policy_type";
- private static final String TUNNEL_ID = "tunnel_id";
- private static final String DST_IP = "dst_ip";
- private static final String SRC_IP = "src_ip";
- private static final String PROTO_TYPE = "proto_type";
- private static final String SRC_PORT = "src_tp_port";
- private static final String DST_PORT = "dst_tp_port";
-
- @Override
- public ObjectNode encode(Policy policy, CodecContext context) {
- final ObjectNode result = context.mapper().createObjectNode()
- .put(POLICY_ID, policy.id());
-
- result.put(PRIORITY, policy.priority());
- result.put(TYPE, policy.type().toString());
-
- if (policy.dstIp() != null) {
- result.put(DST_IP, policy.dstIp());
- }
- if (policy.srcIp() != null) {
- result.put(SRC_IP, policy.srcIp());
- }
- if (policy.ipProto() != null) {
- result.put(PROTO_TYPE, policy.ipProto());
- }
-
- int srcPort = policy.srcPort() & 0xffff;
- if (policy.srcPort() != 0) {
- result.put(SRC_PORT, srcPort);
- }
- int dstPort = policy.dstPort() & 0xffff;
- if (policy.dstPort() != 0) {
- result.put(DST_PORT, dstPort);
- }
- if (policy.type() == Policy.Type.TUNNEL_FLOW) {
- result.put(TUNNEL_ID, ((TunnelPolicy) policy).tunnelId());
- }
-
- return result;
- }
-
- @Override
- public Policy decode(ObjectNode json, CodecContext context) {
-
- String pid = json.path(POLICY_ID).asText();
- String type = json.path(TYPE).asText();
- int priority = json.path(PRIORITY).asInt();
- String dstIp = json.path(DST_IP).asText();
- String srcIp = json.path(SRC_IP).asText();
- String tunnelId = json.path(TUNNEL_ID).asText();
- String protoType = json.path(PROTO_TYPE).asText();
- short srcPort = json.path(SRC_PORT).shortValue();
- short dstPort = json.path(DST_PORT).shortValue();
-
- if (json.path(POLICY_ID).isMissingNode() || pid == null) {
- // TODO: handle errors
- return null;
- }
-
- TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(pid);
- if (!json.path(TYPE).isMissingNode() && type != null &&
- Policy.Type.valueOf(type).equals(Policy.Type.TUNNEL_FLOW)) {
-
- if (json.path(TUNNEL_ID).isMissingNode() || tunnelId == null) {
- return null;
- }
-
- tpb.setTunnelId(tunnelId);
- tpb.setType(Policy.Type.valueOf(type));
-
- if (!json.path(PRIORITY).isMissingNode()) {
- tpb.setPriority(priority);
- }
- if (dstIp != null) {
- tpb.setDstIp(dstIp);
- }
- if (srcIp != null) {
- tpb.setSrcIp(srcIp);
- }
- if (protoType != null) {
- tpb.setIpProto(protoType);
- }
- if (dstPort != 0) {
- tpb.setDstPort(dstPort);
- }
- if (srcPort != 0) {
- tpb.setSrcPort(srcPort);
- }
- }
-
- return tpb.build();
- }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
deleted file mode 100644
index 08663e4..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove segment routing plicies.
- */
-// @Path("policy")
-public class PolicyWebResource extends AbstractWebResource {
-
- private static final PolicyCodec POLICY_CODEC = new PolicyCodec();
-
- /**
- * Get all segment routing policies.
- * Returns an array of segment routing policies.
- *
- * @return status of OK
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getPolicy() {
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- List<Policy> policies = srService.getPolicies();
- ObjectNode result = new ObjectMapper().createObjectNode();
- result.set("policy", new PolicyCodec().encode(policies, this));
-
- return ok(result.toString()).build();
- }
-
- /**
- * Create a new segment routing policy.
- *
- * @param input JSON stream for policy to create
- * @return status of the request - OK if the policy is created,
- * @throws IOException if JSON processing fails
- */
- @POST
- @Consumes(MediaType.APPLICATION_JSON)
- public Response createPolicy(InputStream input) throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode policyJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Policy policyInfo = POLICY_CODEC.decode(policyJson, this);
-
- if (policyInfo.type() == Policy.Type.TUNNEL_FLOW) {
- srService.createPolicy(policyInfo);
- return Response.ok().build();
- } else {
- return Response.serverError().build();
- }
- }
-
- /**
- * Delete a segment routing policy.
- *
- * @param input JSON stream for policy to delete
- * @return 204 NO CONTENT if the policy is removed
- * @throws IOException if JSON is invalid
- */
- @DELETE
- @Consumes(MediaType.APPLICATION_JSON)
- public Response removePolicy(InputStream input) throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode policyJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Policy policyInfo = POLICY_CODEC.decode(policyJson, this);
- // TODO: Check the result
- srService.removePolicy(policyInfo);
-
- return Response.noContent().build();
- }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
deleted file mode 100644
index b2d5d2f..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Mode;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
-
-/**
- * Codec of PseudowireCodec class.
- */
-public final class PseudowireCodec extends JsonCodec<DefaultL2TunnelDescription> {
-
- // JSON field names
- private static final String PW_ID = "pwId";
- private static final String CP1 = "cP1";
- private static final String CP2 = "cP2";
- private static final String CP1_INNER_TAG = "cP1InnerTag";
- private static final String CP1_OUTER_TAG = "cP1OuterTag";
- private static final String CP2_INNER_TAG = "cP2InnerTag";
- private static final String CP2_OUTER_TAG = "cP2OuterTag";
- private static final String MODE = "mode";
- private static final String SERVICE_DELIM_TAG = "serviceTag";
- private static final String PW_LABEL = "pwLabel";
-
- // JSON field names for error in return
- private static final String FAILED_PWS = "failedPws";
- private static final String FAILED_PW = "pw";
- private static final String REASON = "reason";
-
- private static Logger log = LoggerFactory
- .getLogger(PseudowireCodec.class);
-
- @Override
- public ObjectNode encode(DefaultL2TunnelDescription pseudowire, CodecContext context) {
- final ObjectNode result = context.mapper().createObjectNode()
- .put(PW_ID, pseudowire.l2Tunnel().tunnelId());
-
- result.put(CP1, pseudowire.l2TunnelPolicy().cP1().toString());
- result.put(CP2, pseudowire.l2TunnelPolicy().cP2().toString());
-
- result.put(CP1_INNER_TAG, pseudowire.l2TunnelPolicy().cP1InnerTag().toString());
- result.put(CP1_OUTER_TAG, pseudowire.l2TunnelPolicy().cP1OuterTag().toString());
- result.put(CP2_INNER_TAG, pseudowire.l2TunnelPolicy().cP2InnerTag().toString());
- result.put(CP2_OUTER_TAG, pseudowire.l2TunnelPolicy().cP2OuterTag().toString());
- result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
-
- result.put(MODE, pseudowire.l2Tunnel().pwMode() == L2Mode.RAW ? "RAW" : "TAGGED");
- result.put(PW_LABEL, pseudowire.l2Tunnel().pwLabel().toString());
-
- return result;
- }
-
- /**
- * Encoded in an Object Node the pseudowire and the specificError it failed.
- *
- * @param failedPW The failed pseudowire
- * @param specificError The specificError it failed
- * @param context Our context
- * @return A node containing the information we provided
- */
- public ObjectNode encodeError(DefaultL2TunnelDescription failedPW, String specificError,
- CodecContext context) {
- ObjectNode result = context.mapper().createObjectNode();
-
- ObjectNode pw = encode(failedPW, context);
- result.set(FAILED_PW, pw);
- result.put(REASON, specificError);
-
- return result;
- }
-
- /**
- * Encoded in an Object Node the undecoed pseudowire and the specificError it failed.
- *
- * @param failedPW The failed pseudowire in json format
- * @param specificError The specificError it failed
- * @param context Our context
- * @return A node containing the information we provided
- */
- public ObjectNode encodeError(JsonNode failedPW, String specificError,
- CodecContext context) {
- ObjectNode result = context.mapper().createObjectNode();
-
- result.set(FAILED_PW, failedPW);
- result.put(REASON, specificError);
-
- return result;
- }
-
- /**
- * Returns a JSON containing the failed pseudowires and the reason that they failed.
- *
- * @param failedPws Pairs of pws and reasons.
- * @param undecodedPws Pairs of pws that we could not decode with reason being illegal arguments.
- * @param context The context
- * @return ObjectNode representing the json to return
- */
- public ObjectNode encodeFailedPseudowires(
- List<Pair<DefaultL2TunnelDescription, String>> failedPws,
- List<Pair<JsonNode, String>> undecodedPws,
- CodecContext context) {
-
- ArrayNode failedNodes = context.mapper().createArrayNode();
- failedPws.stream()
- .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
- undecodedPws.stream()
- .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
- final ObjectNode toReturn = context.mapper().createObjectNode();
- toReturn.set(FAILED_PWS, failedNodes);
- return toReturn;
- }
-
- /**
- *
- * @param json The json containing the pseudowires.
- * @param context The context
- * @return A pair of lists.
- * First list contains pseudowires that we were not able to decode
- * along with the reason we could not decode them.
- * Second list contains successfully decoded pseudowires which we are
- * going to instantiate.
- */
- public Pair<List<Pair<JsonNode, String>>, List<L2TunnelDescription>> decodePws(ArrayNode json,
- CodecContext context) {
-
- List<L2TunnelDescription> decodedPws = new ArrayList<>();
- List<Pair<JsonNode, String>> notDecodedPws = new ArrayList<>();
- for (JsonNode node : json) {
- DefaultL2TunnelDescription l2Description;
- try {
- l2Description = decode((ObjectNode) node, context);
- decodedPws.add(l2Description);
- } catch (IllegalArgumentException e) {
- // the reason why we could not decode this pseudowire is encoded in the
- // exception, we need to store it now
- notDecodedPws.add(Pair.of(node, e.getMessage()));
- }
- }
-
- return Pair.of(notDecodedPws, decodedPws);
- }
-
- /**
- * Decodes a json containg a single field with the pseudowire id.
- *
- * @param json Json to decode.
- * @return The pseudowire id.
- */
- public static Integer decodeId(ObjectNode json) {
-
- Integer id;
- try {
- id = parsePwId(json.path(PW_ID).asText());
- } catch (IllegalArgumentException e) {
- log.error("Pseudowire id is not an integer!");
- return null;
- }
-
- return id;
- }
-
- @Override
- public DefaultL2TunnelDescription decode(ObjectNode json, CodecContext context) {
-
- Integer id = parsePwId(json.path(PW_ID).asText());
-
- ConnectPoint cP1, cP2;
- cP1 = ConnectPoint.deviceConnectPoint(json.path(CP1).asText());
- cP2 = ConnectPoint.deviceConnectPoint(json.path(CP2).asText());
-
- VlanId cP1InnerVlan, cP1OuterVlan, cP2InnerVlan, cP2OuterVlan, sdTag;
- cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText());
- cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText());
- cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText());
- cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText());
- sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText());
-
- L2Mode mode = parseMode(json.path(MODE).asText());
- MplsLabel pwLabel = parsePWLabel(json.path(PW_LABEL).asText());
-
- DefaultL2Tunnel l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel);
- DefaultL2TunnelPolicy l2Policy = new DefaultL2TunnelPolicy(id, cP1, cP1InnerVlan, cP1OuterVlan,
- cP2, cP2InnerVlan, cP2OuterVlan);
- return new DefaultL2TunnelDescription(l2Tunnel, l2Policy);
-
- }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
deleted file mode 100644
index 4867c90..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.util.ItemNotFoundException;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
-import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
-import org.onosproject.segmentrouting.pwaas.L2Tunnel;
-import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.onlab.util.Tools.nullIsIllegal;
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove pseudowires.
- */
-@Path("pseudowire")
-public class PseudowireWebResource extends AbstractWebResource {
-
- private static final PseudowireCodec PSEUDOWIRE_CODEC = new PseudowireCodec();
- public static final String PWS = "pseudowires";
- private static final String PWS_KEY_ERROR = "Pseudowires key must be present.";
-
- private static Logger log = LoggerFactory
- .getLogger(PseudowireWebResource.class);
-
- /**
- * Get all pseudowires.
- * Returns an array of pseudowires.
- *
- * @return status of OK
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getPseudowire() {
- SegmentRoutingService srService = get(SegmentRoutingService.class);
-
- log.debug("Fetching pseudowires form rest api!");
-
- List<L2TunnelPolicy> policies = srService.getL2Policies();
- List<L2Tunnel> tunnels = srService.getL2Tunnels();
- List<DefaultL2TunnelDescription> pseudowires = tunnels.stream()
- .map(l2Tunnel -> {
- L2TunnelPolicy policy = null;
- for (L2TunnelPolicy l2Policy : policies) {
- if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
- policy = l2Policy;
- break;
- }
- }
-
- // return a copy
- return new DefaultL2TunnelDescription(l2Tunnel, policy);
- })
- .collect(Collectors.toList());
-
- ObjectNode result = new ObjectMapper().createObjectNode();
- result.set("pseudowires", new PseudowireCodec().encode(pseudowires, this));
-
- return ok(result.toString()).build();
- }
-
- /**
- * Create a new pseudowire.
- *
- * @param input JSON stream for pseudowire to create
- * @return Response with appropriate status
- * @throws IOException Throws IO exception.
- * @onos.rsModel PseudowireCreate
- */
- @POST
- @Consumes(MediaType.APPLICATION_JSON)
- public Response createPseudowire(InputStream input) throws IOException {
-
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- List<Pair<DefaultL2TunnelDescription, String>> failed = new ArrayList<>();
- List<Pair<JsonNode, String>> undecoded = new ArrayList<>();
-
- DefaultL2TunnelDescription pseudowire;
- try {
- pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
-
- // pseudowire decoded, try to instantiate it, if we fail add it to failed list
- long tunId = pseudowire.l2Tunnel().tunnelId();
- log.debug("Creating pseudowire {} from rest api!", tunId);
-
- L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
- if (res != L2TunnelHandler.Result.SUCCESS) {
- log.error("Could not create pseudowire {} : {}", pseudowire.l2Tunnel().tunnelId(),
- res.getSpecificError());
- failed.add(Pair.of(pseudowire, res.getSpecificError()));
- }
- } catch (IllegalArgumentException e) {
- log.debug("Pseudowire could not be decoded : {}", e.getMessage());
- undecoded.add(Pair.of(pseudowireJson, e.getMessage()));
- }
-
- if ((failed.size() == 0) && (undecoded.size() == 0)) {
- // pseudowire instantiated correctly
- return Response.ok().build();
- } else {
- // failed to decode or instantiate pseudowire, return the reason
- PseudowireCodec pwCodec = new PseudowireCodec();
- ObjectNode result = pwCodec.encodeFailedPseudowires(failed, undecoded, this);
- return Response.serverError().entity(result).build();
- }
- }
-
- /**
- * Create a bulk of pseudowires.
- *
- * @param input JSON stream for pseudowires to create
- * @return Response with appropriate status
- * @throws IOException Throws IO exception.
- * @onos.rsModel PseudowireCreateBulk
- */
- @POST
- @Path("/bulk")
- @Consumes(MediaType.APPLICATION_JSON)
- public Response createPseudowiresBulk(InputStream input) throws IOException {
-
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Pair<List<Pair<JsonNode, String>>, List<L2TunnelDescription>> pseudowires;
-
- try {
- ArrayNode pseudowiresArray = nullIsIllegal((ArrayNode) pseudowireJson.get(PWS), PWS_KEY_ERROR);
- // get two lists, first one contains pseudowires that we were unable to decode
- // that have faulty arguments, second one contains pseudowires that we decoded
- // succesfully
- pseudowires = PSEUDOWIRE_CODEC.decodePws(pseudowiresArray, this);
- } catch (ItemNotFoundException e) {
- return Response.serverError().status(Response.Status.BAD_REQUEST).build();
- }
-
- log.debug("Creating pseudowires {} from rest api!", pseudowires);
- List<Pair<DefaultL2TunnelDescription, String>> failed = new ArrayList<>();
- for (L2TunnelDescription pw : pseudowires.getRight()) {
- L2TunnelHandler.Result res = srService.addPseudowire(pw);
- if (res != L2TunnelHandler.Result.SUCCESS) {
- log.error("Could not create pseudowire {} : {}", pw.l2Tunnel().tunnelId(), res.getSpecificError());
- failed.add(Pair.of((DefaultL2TunnelDescription) pw, res.getSpecificError()));
- }
- }
- List<Pair<JsonNode, String>> undecodedPws = pseudowires.getLeft();
-
- if ((failed.size() == 0) && (undecodedPws.size() == 0)) {
- // all pseudowires were decoded and instantiated succesfully
- return Response.ok().build();
- } else {
- PseudowireCodec pwCodec = new PseudowireCodec();
- // some failed, need to report them to user
- ObjectNode result = pwCodec.encodeFailedPseudowires(failed, undecodedPws, this);
- return Response.serverError().entity(result).build();
- }
- }
-
- /**
- * Delete a pseudowire.
- *
- * @param input JSON stream for pseudowire to delete
- * @return Response with appropriate status
- * @throws IOException Throws IO exception.
- * @onos.rsModel PseudowireDelete
- */
- @DELETE
- @Consumes(MediaType.APPLICATION_JSON)
- public Response removePseudowire(InputStream input) throws IOException {
-
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
-
- Integer pseudowireId = PSEUDOWIRE_CODEC.decodeId(pseudowireJson);
- if (pseudowireId == null) {
- return Response.serverError().status(Response.Status.BAD_REQUEST).build();
- }
-
- log.debug("Deleting pseudowire {} from rest api!", pseudowireId);
-
- L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
- switch (res) {
- case WRONG_PARAMETERS:
- case INTERNAL_ERROR:
- log.error("Pseudowire {} could not be removed : {}",
- pseudowireId, res.getSpecificError());
- return Response.noContent().build();
- case SUCCESS:
- log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
- return Response.noContent().build();
- default:
- return Response.noContent().build();
- }
- }
-
- /**
- * Delete a bulk of pseudowires.
- *
- * @param input JSON stream for pseudowires to delete
- * @return Response with appropriate status
- * @throws IOException Throws IO exception.
- * @onos.rsModel PseudowireDeleteBulk
- */
- @DELETE
- @Path("/bulk")
- @Consumes(MediaType.APPLICATION_JSON)
- public Response removePseudowiresBulk(InputStream input) throws IOException {
-
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
-
- List<Integer> ids = new ArrayList<>();
-
- // try to parse all ids, if key is not present, or if an id is not an int
- // throw an exception and stop process
- try {
- for (JsonNode node : pseudowireJson.withArray(PWS)) {
- Integer idToDelete = PseudowireCodec.decodeId((ObjectNode) node);
- if (idToDelete == null) {
- log.error("Error when parsing pseudowire for deletion in REST API.");
- throw new IllegalArgumentException("Id of pseudowire should be an integer!");
- }
- ids.add(idToDelete);
- }
- } catch (IllegalArgumentException e) {
- log.error("Pseudowire ID should be an integer.");
- return Response.serverError().status(Response.Status.BAD_REQUEST).build();
- } catch (UnsupportedOperationException e) {
- log.error("Pseudowires for deletion should be an array of pseudowire ids.");
- return Response.serverError().status(Response.Status.BAD_REQUEST).build();
- }
-
- for (Integer pseudowireId : ids) {
- L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId);
- switch (res) {
- case WRONG_PARAMETERS:
- case INTERNAL_ERROR:
- log.error("Pseudowire {} could not be removed, internal error : {}",
- pseudowireId, res.getSpecificError());
- break;
- case SUCCESS:
- log.debug("Pseudowire {} was removed succesfully!", pseudowireId);
- break;
- default:
- }
- }
-
- return Response.noContent().build();
- }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
deleted file mode 100644
index 6704030..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.segmentrouting.web;
-
-import org.onlab.rest.AbstractWebApplication;
-
-import java.util.Set;
-
-/**
- * Segment Routing REST API.
- */
-public class SegmentRoutingWebApplication extends AbstractWebApplication {
- @Override
- public Set<Class<?>> getClasses() {
- return getClasses(
- PseudowireWebResource.class,
- McastWebResource.class,
- XconnectWebResource.class
- );
- }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java
deleted file mode 100644
index b2d74b1..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import org.onosproject.codec.CodecContext;
-import org.onosproject.codec.JsonCodec;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.segmentrouting.DefaultTunnel;
-import org.onosproject.segmentrouting.Tunnel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Codec of Tunnel class.
- */
-public final class TunnelCodec extends JsonCodec<Tunnel> {
-
- // JSON field names
- private static final String TUNNEL_ID = "tunnel_id";
- private static final String GROUP_ID = "group_id";
- private static final String LABEL_PATH = "label_path";
-
- @Override
- public ObjectNode encode(Tunnel tunnel, CodecContext context) {
- final ObjectNode result = context.mapper().createObjectNode()
- .put(TUNNEL_ID, tunnel.id());
-
- result.put(GROUP_ID, tunnel.groupId());
-
- final ArrayNode jsonLabelIds = result.putArray(LABEL_PATH);
-
- tunnel.labelIds().forEach(label -> jsonLabelIds.add(label.intValue()));
-
- return result;
- }
-
- @Override
- public DefaultTunnel decode(ObjectNode json, CodecContext context) {
-
- String tid = json.path(TUNNEL_ID).asText();
- List<Integer> labels = new ArrayList<>();
-
- if (!json.path(LABEL_PATH).isMissingNode()) {
- ArrayNode labelArray = (ArrayNode) json.path(LABEL_PATH);
- for (JsonNode o : labelArray) {
- labels.add(o.asInt());
- }
- }
-
- return new DefaultTunnel(tid, labels);
- }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
deleted file mode 100644
index 010f6c9..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.Tunnel;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove segment routing tunnels.
- */
-// @Path("tunnel")
-public class TunnelWebResource extends AbstractWebResource {
-
- private static final TunnelCodec TUNNEL_CODEC = new TunnelCodec();
-
- /**
- * Get all segment routing tunnels.
- * Returns an array of segment routing tunnels.
- *
- * @return status of OK
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getTunnel() {
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- List<Tunnel> tunnels = srService.getTunnels();
- ObjectNode result = new ObjectMapper().createObjectNode();
- result.set("tunnel", new TunnelCodec().encode(tunnels, this));
-
- return ok(result.toString()).build();
- }
-
- /**
- * Create a new segment routing tunnel.
- *
- * @param input JSON stream for tunnel to create
- * @return status of the request - OK if the tunnel is created,
- * @throws IOException if the JSON is invalid
- */
- @POST
- @Consumes(MediaType.APPLICATION_JSON)
- public Response createTunnel(InputStream input) throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode tunnelJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this);
- srService.createTunnel(tunnelInfo);
-
- return Response.ok().build();
- }
-
- /**
- * Delete a segment routing tunnel.
- *
- * @param input JSON stream for tunnel to delete
- * @return 204 NO CONTENT, if the tunnel is removed
- * @throws IOException if JSON is invalid
- */
- @DELETE
- @Consumes(MediaType.APPLICATION_JSON)
- public Response removeTunnel(InputStream input) throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode tunnelJson = readTreeFromStream(mapper, input);
- SegmentRoutingService srService = get(SegmentRoutingService.class);
- Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this);
- srService.removeTunnel(tunnelInfo);
-
- return Response.noContent().build();
- }
-
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/XconnectWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/XconnectWebResource.java
deleted file mode 100644
index 51c9cc9..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/XconnectWebResource.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.segmentrouting.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.xconnect.api.XconnectDesc;
-import org.onosproject.segmentrouting.xconnect.api.XconnectService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Set;
-
-import static org.onlab.util.Tools.readTreeFromStream;
-
-/**
- * Query, create and remove Xconnects.
- */
-@Path("xconnect")
-public class XconnectWebResource extends AbstractWebResource {
- private static final String XCONNECTS = "xconnects";
- private static Logger log = LoggerFactory.getLogger(XconnectWebResource.class);
-
- /**
- * Gets all Xconnects.
- *
- * @return an array of xconnects
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getXconnects() {
- XconnectService xconnectService = get(XconnectService.class);
- Set<XconnectDesc> xconnects = xconnectService.getXconnects();
-
- ObjectNode result = encodeArray(XconnectDesc.class, XCONNECTS, xconnects);
- return ok(result).build();
- }
-
- /**
- * Create a new Xconnect.
- *
- * @param input JSON stream for xconnect to create
- * @return 200 OK
- * @throws IOException Throws IO exception
- * @onos.rsModel XconnectCreate
- */
- @POST
- @Consumes(MediaType.APPLICATION_JSON)
- public Response addOrUpdateXconnect(InputStream input) throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode json = readTreeFromStream(mapper, input);
- XconnectDesc desc = codec(XconnectDesc.class).decode(json, this);
-
- if (desc.endpoints().size() != 2) {
- throw new IllegalArgumentException("Ports should have only two items.");
- }
-
- XconnectService xconnectService = get(XconnectService.class);
- xconnectService.addOrUpdateXconnect(desc.key().deviceId(), desc.key().vlanId(), desc.endpoints());
-
- return Response.ok().build();
- }
-
-
- /**
- * Delete an existing Xconnect.
- *
- * @param input JSON stream for xconnect to remove
- * @return 204 NO CONTENT
- * @throws IOException Throws IO exception
- * @onos.rsModel XconnectDelete
- */
- @DELETE
- @Consumes(MediaType.APPLICATION_JSON)
- public Response removeXconnect(InputStream input) throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode json = readTreeFromStream(mapper, input);
- XconnectDesc desc = codec(XconnectDesc.class).decode(json, this);
-
- XconnectService xconnectService = get(XconnectService.class);
- xconnectService.removeXonnect(desc.key().deviceId(), desc.key().vlanId());
-
- return Response.noContent().build();
- }
-}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java
deleted file mode 100644
index ff9555e..0000000
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Segment routing application components.
- */
-package org.onosproject.segmentrouting.web;
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreate.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreate.json
deleted file mode 100644
index 315d01d..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreate.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "type": "object",
- "title": "pseudowire-creation",
- "required": [
- "pwId",
- "cP1",
- "cP2",
- "cP1InnerTag",
- "cP1OuterTag",
- "cP2InnerTag",
- "cP2OuterTag",
- "mode",
- "sdTag",
- "pwLabel"
- ],
- "properties": {
- "pwId": {
- "type": "string",
- "example": "42",
- "description": "Id of pseudowire to create."
- },
- "cP1": {
- "type": "string",
- "example": "of:0000000000000227/25",
- "description": "Pseudowire connection point 1."
- },
- "cP2": {
- "type": "string",
- "example": "of:0000000000000226/25",
- "description": "Pseudowire connection point 2."
- },
- "cP1InnerTag": {
- "type": "string",
- "example": "101",
- "description": "Inner vlan for pseudowire connection point 1."
- },
- "cP1OuterTag": {
- "type": "string",
- "example": "",
- "description": "Outer vlan for pseudowire connection point 1."
- },
- "cP2InnerTag": {
- "type": "string",
- "example": "101",
- "description": "Inner vlan for pseudowire connection point 2."
- },
- "cP2OuterTag": {
- "type": "string",
- "example": "",
- "description": "Outer vlan for pseudowire connection point 2."
- },
- "mode": {
- "type": "string",
- "example": "RAW",
- "description": "Working mode of pseudowire."
- },
- "sDTag": {
- "type": "string",
- "example": "",
- "description": "Service delimiting tag of the pseudowire"
- },
- "pwLabel": {
- "type": "256",
- "example": "1577",
- "description": "Pseudowire label."
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreateBulk.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreateBulk.json
deleted file mode 100644
index 752e6eb..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreateBulk.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "type": "object",
- "title": "pseudowire-creation-bulk",
- "required": [
- "pseudowires"
- ],
- "properties": {
- "pseudowires": {
- "type": "array",
- "items": {
- "properties": {
- "pwId": {
- "type": "string",
- "example": "42",
- "description": "Id of pseudowire to create."
- },
- "cP1": {
- "type": "string",
- "example": "of:0000000000000227/25",
- "description": "Pseudowire connection point 1."
- },
- "cP2": {
- "type": "string",
- "example": "of:0000000000000226/25",
- "description": "Pseudowire connection point 2."
- },
- "cP1InnerTag": {
- "type": "string",
- "example": "101",
- "description": "Inner vlan for pseudowire connection point 1."
- },
- "cP1OuterTag": {
- "type": "string",
- "example": "",
- "description": "Outer vlan for pseudowire connection point 1."
- },
- "cP2InnerTag": {
- "type": "string",
- "example": "101",
- "description": "Inner vlan for pseudowire connection point 2."
- },
- "cP2OuterTag": {
- "type": "string",
- "example": "",
- "description": "Outer vlan for pseudowire connection point 2."
- },
- "mode": {
- "type": "string",
- "example": "RAW",
- "description": "Working mode of pseudowire."
- },
- "sDTag": {
- "type": "string",
- "example": "",
- "description": "Service delimiting tag of the pseudowire"
- },
- "pwLabel": {
- "type": "256",
- "example": "1577",
- "description": "Pseudowire label."
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDelete.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDelete.json
deleted file mode 100644
index 4dd5c04..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDelete.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "type": "object",
- "title": "pseudowire-deletion",
- "required": [
- "pwId"
- ],
- "properties": {
- "pwId": {
- "type": "string",
- "example": "42",
- "description": "Id of pseudowire to delete."
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDeleteBulk.json b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDeleteBulk.json
deleted file mode 100644
index 2edc7e6..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDeleteBulk.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "type": "object",
- "title": "pseudowire-deletion-bulk",
- "required": [
- "pseudowires"
- ],
- "properties": {
- "pseudowires": {
- "type": "array",
- "items": {
- "type": "object",
- "title": "pseudowire-1",
- "required": [
- "pwId"
- ],
- "properties": {
- "pwId": {
- "type": "string",
- "example": "42",
- "description": "Id of pseudowire to Delete."
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/XconnectCreate.json b/apps/segmentrouting/web/src/main/resources/definitions/XconnectCreate.json
deleted file mode 100644
index 87a776c..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/XconnectCreate.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "type": "object",
- "title": "xconnect-creation",
- "required": [
- "deviceId",
- "vlanId",
- "endpoints"
- ],
- "properties": {
- "deviceId": {
- "type": "string",
- "example": "of:0000000000000201",
- "description": "Device ID"
- },
- "vlanId": {
- "type": "string",
- "example": "94",
- "description": "VLAN ID"
- },
- "endpoints": {
- "type": "array",
- "items": {
- "type": "int8",
- "description": "Port number"
- },
- "example": [1, 2]
- }
- }
-}
diff --git a/apps/segmentrouting/web/src/main/resources/definitions/XconnectDelete.json b/apps/segmentrouting/web/src/main/resources/definitions/XconnectDelete.json
deleted file mode 100644
index fcd5f66..0000000
--- a/apps/segmentrouting/web/src/main/resources/definitions/XconnectDelete.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "type": "object",
- "title": "xconnect-deletion",
- "required": [
- "deviceId",
- "vlanId"
- ],
- "properties": {
- "deviceId": {
- "type": "string",
- "example": "of:0000000000000201",
- "description": "Device ID"
- },
- "vlanId": {
- "type": "string",
- "example": "94",
- "description": "VLAN ID"
- }
- }
-}
\ No newline at end of file
diff --git a/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml b/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 1362728..0000000
--- a/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright 2015-present Open Networking Foundation
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- id="ONOS" version="2.5">
- <display-name>Segment Routing Server REST API v1.0</display-name>
-
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>Secured</web-resource-name>
- <url-pattern>/*</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>admin</role-name>
- <role-name>viewer</role-name>
- </auth-constraint>
- </security-constraint>
-
- <security-role>
- <role-name>admin</role-name>
- <role-name>viewer</role-name>
- </security-role>
-
- <login-config>
- <auth-method>BASIC</auth-method>
- <realm-name>karaf</realm-name>
- </login-config>
-
- <servlet>
- <servlet-name>JAX-RS Service</servlet-name>
- <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
- <init-param>
- <param-name>javax.ws.rs.Application</param-name>
- <param-value>org.onosproject.segmentrouting.web.SegmentRoutingWebApplication</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>JAX-RS Service</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-</web-app>
diff --git a/apps/t3/BUILD b/apps/t3/BUILD
deleted file mode 100644
index 0e444bf..0000000
--- a/apps/t3/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-BUNDLES = [
- "//apps/t3/web:onos-apps-t3-web",
- "//apps/t3/app:onos-apps-t3-app",
-]
-
-onos_app(
- app_name = "org.onosproject.t3",
- category = "Utilities",
- description = "Provides static analysis of flows and groups " +
- "to determine the possible paths a packet may take.",
- included_bundles = BUNDLES,
- required_apps = [
- "org.onosproject.segmentrouting",
- "org.onosproject.route-service",
- "org.onosproject.mcast",
- ],
- title = "Trellis Troubleshooting Toolkit",
- url = "https://wiki.opencord.org/pages/viewpage.action?pageId=4456974",
-)
diff --git a/apps/t3/app/BUILD b/apps/t3/app/BUILD
deleted file mode 100644
index 81173f6..0000000
--- a/apps/t3/app/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + KRYO + JACKSON + CLI + [
- "//core/store/serializers:onos-core-serializers",
- "//core/store/primitives:onos-core-primitives",
- "//drivers/default:onos-drivers-default",
- "//apps/segmentrouting/app:onos-apps-segmentrouting-app",
- "//apps/route-service/api:onos-apps-route-service-api",
- "//apps/mcast/api:onos-apps-mcast-api",
-]
-
-TEST_DEPS = TEST_ADAPTERS + [
- "//utils/misc:onlab-misc",
- "//apps/route-service/api:onos-apps-route-service-api-tests",
-]
-
-osgi_jar_with_tests(
- karaf_command_packages = ["org.onosproject.t3.cli"],
- test_deps = TEST_DEPS,
- deps = COMPILE_DEPS,
-)
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/AbstractNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/AbstractNib.java
deleted file mode 100644
index 652c974..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/AbstractNib.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-/**
- * Base abstraction of Network Information Base (NIB).
- */
-public abstract class AbstractNib {
-
- protected NibProfile nibProfile;
-
- /**
- * Sets a profile describing this NIB.
- *
- * @param nibProfile NIB profile
- */
- public void setProfile(NibProfile nibProfile) {
- this.nibProfile = nibProfile;
- }
-
- /**
- * Returns the current profile of this NIB.
- *
- * @return NIB profile
- */
- public NibProfile getProfile() {
- return nibProfile;
- }
-
- /**
- * Checks this NIB is valid.
- *
- * @return true (valid) only if this NIB is already filled with any source. false means invalid
- */
- public boolean isValid() {
- if (nibProfile != null) {
- return nibProfile.isValid();
- } else {
- return false;
- }
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/DeviceNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/DeviceNib.java
deleted file mode 100644
index aca8418..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/DeviceNib.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Represents Network Information Base (NIB) for devices
- * and supports alternative functions to
- * {@link org.onosproject.net.device.DeviceService} for offline data.
- */
-public class DeviceNib extends AbstractNib {
-
- private Map<Device, Set<Port>> devicePortMap;
-
- // use the singleton helper to create the instance
- protected DeviceNib() {
- }
-
- /**
- * Sets a map of device : ports of the device.
- *
- * @param devicePortMap device-ports map
- */
- public void setDevicePortMap(Map<Device, Set<Port>> devicePortMap) {
- this.devicePortMap = devicePortMap;
- }
-
- /**
- * Returns the device-ports map.
- *
- * @return device-ports map
- */
- public Map<Device, Set<Port>> getDevicePortMap() {
- return ImmutableMap.copyOf(devicePortMap);
- }
-
- /**
- * Returns the device with the specified identifier.
- *
- * @param deviceId device identifier
- * @return device or null if one with the given identifier is not known
- */
- public Device getDevice(DeviceId deviceId) {
- return devicePortMap.keySet().stream()
- .filter(device -> device.id().equals(deviceId))
- .findFirst().orElse(null);
- }
-
- /**
- * Returns the port with the specified connect point.
- *
- * @param cp connect point
- * @return device port
- */
- public Port getPort(ConnectPoint cp) {
- return devicePortMap.get(getDevice(cp.deviceId())).stream()
- .filter(port -> port.number().equals(cp.port()))
- .findFirst().orElse(null);
- }
-
- /**
- * Returns the list of ports associated with the device.
- *
- * @param deviceId device identifier
- * @return list of ports
- */
- public List<Port> getPorts(DeviceId deviceId) {
- return ImmutableList.copyOf(devicePortMap.get(getDevice(deviceId)));
- }
-
- /**
- * Indicates whether or not the device is presently online and available.
- * Availability, unlike reachability, denotes whether ANY node in the
- * cluster can discover that this device is in an operational state,
- * this does not necessarily mean that there exists a node that can
- * control this device.
- *
- * @param deviceId device identifier
- * @return true if the device is available
- */
- public boolean isAvailable(DeviceId deviceId) {
- Device device = getDevice(deviceId);
- // TODO: may need an extra REST API to get availableDevices from DeviceService, not from device annotations
- return device.annotations().value("available").equals("true") ? true : false;
- }
-
- /**
- * Returns the singleton instance of devices NIB.
- *
- * @return instance of devices NIB
- */
- public static DeviceNib getInstance() {
- return DeviceNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final DeviceNib INSTANCE = new DeviceNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/DriverNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/DriverNib.java
deleted file mode 100644
index edee901..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/DriverNib.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-
-/**
- * Represents Network Information Base (NIB) for drivers
- * and supports alternative functions to
- * {@link org.onosproject.net.driver.DriverService} for offline data.
- */
-public class DriverNib extends AbstractNib {
-
- private Map<DeviceId, String> deviceDriverMap;
-
- // use the singleton helper to create the instance
- protected DriverNib() {
- }
-
- /**
- * Sets a map of device id : driver name.
- *
- * @param deviceDriverMap device-driver map
- */
- public void setDeviceDriverMap(Map<DeviceId, String> deviceDriverMap) {
- this.deviceDriverMap = deviceDriverMap;
- }
-
- /**
- * Returns the device-driver map.
- *
- * @return device-driver map
- */
- public Map<DeviceId, String> getDeviceDriverMap() {
- return ImmutableMap.copyOf(deviceDriverMap);
- }
-
- /**
- * Returns a driver name of the given device.
- *
- * @param deviceId the device id
- * @return the driver name
- */
- public String getDriverName(DeviceId deviceId) {
- return deviceDriverMap.get(deviceId);
- }
-
- /**
- * Returns the singleton instance of drivers NIB.
- *
- * @return instance of drivers NIB
- */
- public static DriverNib getInstance() {
- return DriverNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final DriverNib INSTANCE = new DriverNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/EdgePortNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/EdgePortNib.java
deleted file mode 100644
index 060f9c4..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/EdgePortNib.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Represents Network Information Base (NIB) for edge ports
- * and supports alternative functions to
- * {@link org.onosproject.net.edge.EdgePortService} for offline data.
- */
-public class EdgePortNib extends AbstractNib {
-
- private Map<DeviceId, Set<ConnectPoint>> edgePorts;
-
- // use the singleton helper to create the instance
- protected EdgePortNib() {
- }
-
- /**
- * Sets a map of device id : edge ports of the device.
- *
- * @param edgePorts device-edge ports map
- */
- public void setEdgePorts(Map<DeviceId, Set<ConnectPoint>> edgePorts) {
- this.edgePorts = edgePorts;
- }
-
- /**
- * Returns the device-edge ports map.
- * @return device-edge ports map
- */
- public Map<DeviceId, Set<ConnectPoint>> getEdgePorts() {
- return ImmutableMap.copyOf(edgePorts);
- }
-
- /**
- * Indicates whether or not the specified connection point is an edge point.
- *
- * @param point connection point
- * @return true if edge point
- */
- public boolean isEdgePoint(ConnectPoint point) {
- Set<ConnectPoint> connectPoints = edgePorts.get(point.deviceId());
- return connectPoints != null && connectPoints.contains(point);
- }
-
- /**
- * Returns the singleton instance of edge ports NIB.
- *
- * @return instance of edge ports NIB
- */
- public static EdgePortNib getInstance() {
- return EdgePortNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final EdgePortNib INSTANCE = new EdgePortNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/FlowNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/FlowNib.java
deleted file mode 100644
index b9f2226..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/FlowNib.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.flow.FlowEntry;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for flows
- * and supports alternative functions to
- * {@link org.onosproject.net.flow.FlowRuleService} for offline data.
- */
-public class FlowNib extends AbstractNib {
-
- // TODO with method optimization, store into subdivided structures at the first load
- private Set<FlowEntry> flows;
-
- // use the singleton helper to create the instance
- protected FlowNib() {
- }
-
- /**
- * Sets a set of flows.
- *
- * @param flows flow set
- */
- public void setFlows(Set<FlowEntry> flows) {
- this.flows = flows;
- }
-
- /**
- * Returns the set of flows.
- *
- * @return flow set
- */
- public Set<FlowEntry> getFlows() {
- return ImmutableSet.copyOf(flows);
- }
-
- /**
- * Returns a list of rules filtered by device id and flow state.
- *
- * @param deviceId the device id to lookup
- * @param flowState the flow state to lookup
- * @return collection of flow entries
- */
- public Iterable<FlowEntry> getFlowEntriesByState(DeviceId deviceId, FlowEntry.FlowEntryState flowState) {
- Set<FlowEntry> flowsFiltered = flows.stream()
- .filter(flow -> flow.state() == flowState
- && flow.deviceId().equals(deviceId))
- .collect(Collectors.toSet());
- return flowsFiltered != null ? ImmutableSet.copyOf(flowsFiltered) : ImmutableSet.of();
- }
-
- /**
- * Returns the singleton instance of flows NIB.
- *
- * @return instance of flows NIB
- */
- public static FlowNib getInstance() {
- return SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final FlowNib INSTANCE = new FlowNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupNib.java
deleted file mode 100644
index b1fb563..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupNib.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.group.Group;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for groups
- * and supports alternative functions to
- * {@link org.onosproject.net.group.GroupService} for offline data.
- */
-public class GroupNib extends AbstractNib {
-
- // TODO with method optimization, store into subdivided structures at the first load
- private Set<Group> groups;
-
- // use the singleton helper to create the instance
- protected GroupNib() {
- }
-
- /**
- * Sets a set of groups.
- *
- * @param groups group set
- */
- public void setGroups(Set<Group> groups) {
- this.groups = groups;
- }
-
- /**
- * Returns the set of groups.
- *
- * @return group set
- */
- public Set<Group> getGroups() {
- return ImmutableSet.copyOf(groups);
- }
-
- /**
- * Returns all groups associated with the given device.
- *
- * @param deviceId device ID to get groups for
- * @return iterable of device's groups
- */
- public Iterable<Group> getGroups(DeviceId deviceId) {
- Set<Group> groupsFiltered = groups.stream()
- .filter(g -> g.deviceId().equals(deviceId))
- .collect(Collectors.toSet());
- return groupsFiltered != null ? ImmutableSet.copyOf(groupsFiltered) : ImmutableSet.of();
- }
-
- /**
- * Returns the singleton instance of groups NIB.
- *
- * @return instance of groups NIB
- */
- public static GroupNib getInstance() {
- return GroupNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final GroupNib INSTANCE = new GroupNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupsInDevice.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupsInDevice.java
deleted file mode 100644
index 74203af..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/GroupsInDevice.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.group.Group;
-
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Class to represent the groups in a device for a given output and packet.
- */
-//FIXME consider name change.
-public class GroupsInDevice {
-
- private ConnectPoint output;
- private List<Group> groups;
- private TrafficSelector selector;
-
- /**
- * Saves the given groups for the output connect point and the selector.
- *
- * @param output the output connect point
- * @param groups the groups
- * @param selector the selector representing the final packet
- */
- public GroupsInDevice(ConnectPoint output, List<Group> groups, TrafficSelector selector) {
-
- this.output = output;
- this.groups = groups;
- this.selector = selector;
- }
-
- /**
- * Returns the output connect point.
- *
- * @return the connect point
- */
- public ConnectPoint getOutput() {
- return output;
- }
-
- /**
- * Returns the groups.
- *
- * @return groups.
- */
- public List<Group> getGroups() {
- return groups;
- }
-
- /**
- * Returns the final packet after traversing the network.
- *
- * @return the selector with packet info
- */
- public TrafficSelector getFinalPacket() {
- return selector;
- }
-
- /**
- * Updates the final packet.
- *
- * @param updatedPacket the updated final packet
- */
- public void setFinalPacket(TrafficSelector updatedPacket) {
- selector = updatedPacket;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- GroupsInDevice that = (GroupsInDevice) o;
-
- return Objects.equals(output, that.output) &&
- Objects.equals(groups, that.groups) &&
- Objects.equals(selector, that.selector);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(output, groups, selector);
- }
-
- @Override
- public String toString() {
- return "GroupsInDevice{" +
-
- "output=" + output +
- ", groups=" + groups +
- ", selector=" + selector +
- '}';
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/HostNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/HostNib.java
deleted file mode 100644
index 2ba68d1..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/HostNib.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for hosts
- * and supports alternative functions to
- * {@link org.onosproject.net.host.HostService} for offline data.
- */
-public class HostNib extends AbstractNib {
-
- // TODO with method optimization, store into subdivided structures at the first load
- private Set<Host> hosts;
-
- // use the singleton helper to create the instance
- protected HostNib() {
- }
-
- /**
- * Sets a set of hosts.
- *
- * @param hosts host set
- */
- public void setHosts(Set<Host> hosts) {
- this.hosts = hosts;
- }
-
- /**
- * Returns the set of hosts.
- *
- * @return host set
- */
- public Set<Host> getHosts() {
- return ImmutableSet.copyOf(hosts);
- }
-
- /**
- * Returns the host with the specified identifier.
- *
- * @param hostId host identifier
- * @return host or null if one with the given identifier is not known
- */
- public Host getHost(HostId hostId) {
- return hosts.stream()
- .filter(host -> host.id().equals(hostId))
- .findFirst().orElse(null);
- }
-
- /**
- * Returns the set of hosts whose most recent location is the specified
- * connection point.
- *
- * @param connectPoint connection point
- * @return set of hosts connected to the connection point
- */
- public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
- // TODO extend this method to support matching on auxLocations as well
- Set<Host> connectedHosts = hosts.stream()
- .filter(host -> host.locations().contains(connectPoint))
- .collect(Collectors.toSet());
- return connectedHosts != null ? ImmutableSet.copyOf(connectedHosts) : ImmutableSet.of();
- }
-
- /**
- * Returns the set of hosts that have the specified IP address.
- *
- * @param ip ip address
- * @return set of hosts with the given IP
- */
- public Set<Host> getHostsByIp(IpAddress ip) {
- Set<Host> hostsByIp = hosts.stream()
- .filter(host -> host.ipAddresses().contains(ip))
- .collect(Collectors.toSet());
- return hostsByIp != null ? ImmutableSet.copyOf(hostsByIp) : ImmutableSet.of();
- }
-
- /**
- * Returns the set of hosts that have the specified MAC address.
- *
- * @param mac mac address
- * @return set of hosts with the given mac
- */
- public Set<Host> getHostsByMac(MacAddress mac) {
- Set<Host> hostsByMac = hosts.stream()
- .filter(host -> host.mac().equals(mac))
- .collect(Collectors.toSet());
- return hostsByMac != null ? ImmutableSet.copyOf(hostsByMac) : ImmutableSet.of();
- }
-
- /**
- * Returns the singleton instance of hosts NIB.
- *
- * @return instance of hosts NIB
- */
- public static HostNib getInstance() {
- return HostNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final HostNib INSTANCE = new HostNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/LinkNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/LinkNib.java
deleted file mode 100644
index 622a187..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/LinkNib.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Link;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for links
- * and supports alternative functions to
- * {@link org.onosproject.net.link.LinkService} for offline data.
- */
-public class LinkNib extends AbstractNib {
-
- // TODO with method optimization, store into subdivided structures at the first load
- private Set<Link> links;
-
- // use the singleton helper to create the instance
- protected LinkNib() {
- }
-
- /**
- * Sets a set of links.
- *
- * @param links link set
- */
- public void setLinks(Set<Link> links) {
- this.links = links;
- }
-
- /**
- * Returns the set of links.
- *
- * @return link set
- */
- public Set<Link> getLinks() {
- return ImmutableSet.copyOf(links);
- }
-
- /**
- * Returns set of all infrastructure links leading from the specified
- * connection point.
- *
- * @param connectPoint connection point
- * @return set of device egress links
- */
- public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
- Set<Link> egressLinks = links.stream()
- .filter(link -> connectPoint.equals(link.src()))
- .collect(Collectors.toSet());
- return egressLinks != null ? ImmutableSet.copyOf(egressLinks) : ImmutableSet.of();
- }
-
- /**
- * Returns the singleton instance of links NIB.
- *
- * @return instance of links NIB
- */
- public static LinkNib getInstance() {
- return LinkNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final LinkNib INSTANCE = new LinkNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/MastershipNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/MastershipNib.java
deleted file mode 100644
index 733c590..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/MastershipNib.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.DeviceId;
-
-import java.util.Map;
-
-/**
- * Represents Network Information Base (NIB) for mastership
- * and supports alternative functions to
- * {@link org.onosproject.mastership.MastershipService} for offline data.
- */
-public class MastershipNib extends AbstractNib {
-
- private Map<DeviceId, NodeId> deviceMasterMap;
-
- // use the singleton helper to create the instance
- protected MastershipNib() {
- }
-
- /**
- * Sets a map of device id : master node id.
- *
- * @param deviceMasterMap device-master map
- */
- public void setDeviceMasterMap(Map<DeviceId, NodeId> deviceMasterMap) {
- this.deviceMasterMap = deviceMasterMap;
- }
-
- /**
- * Returns the device-master map.
- *
- * @return device-master map
- */
- public Map<DeviceId, NodeId> getDeviceMasterMap() {
- return ImmutableMap.copyOf(deviceMasterMap);
- }
-
- /**
- * Returns the current master for a given device.
- *
- * @param deviceId the identifier of the device
- * @return the ID of the master controller for the device
- */
- public NodeId getMasterFor(DeviceId deviceId) {
- return deviceMasterMap.get(deviceId);
- }
-
- /**
- * Returns the singleton instance of mastership NIB.
- *
- * @return instance of mastership NIB
- */
- public static MastershipNib getInstance() {
- return MastershipNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final MastershipNib INSTANCE = new MastershipNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/MulticastRouteNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/MulticastRouteNib.java
deleted file mode 100644
index 0bcdc1f..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/MulticastRouteNib.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Represents Network Information Base (NIB) for multicast routes
- * and supports alternative functions to
- * {@link org.onosproject.mcast.api.MulticastRouteService} for offline data.
- */
-public class MulticastRouteNib extends AbstractNib {
-
- private Map<McastRoute, McastRouteData> mcastRoutes;
-
- // use the singleton helper to create the instance
- protected MulticastRouteNib() {
- }
-
- public void setMcastRoutes(Map<McastRoute, McastRouteData> mcastRoutes) {
- this.mcastRoutes = mcastRoutes;
- }
-
- public Map<McastRoute, McastRouteData> getMcastRoutes() {
- return ImmutableMap.copyOf(mcastRoutes);
- }
-
- /**
- * Gets all Multicast routes in the system.
- *
- * @return set of Multicast routes
- */
- public Set<McastRoute> getRoutes() {
- return ImmutableSet.copyOf(mcastRoutes.keySet());
- }
-
- /**
- * Return the Multicast data for this route.
- *
- * @param route route
- * @return the mcast route data
- */
- public McastRouteData routeData(McastRoute route) {
- return mcastRoutes.get(route);
- }
-
- /**
- * Returns the singleton instance of multicast routes NIB.
- *
- * @return instance of multicast routes NIB
- */
- public static MulticastRouteNib getInstance() {
- return MulticastRouteNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final MulticastRouteNib INSTANCE = new MulticastRouteNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/NetworkConfigNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/NetworkConfigNib.java
deleted file mode 100644
index f3de961..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/NetworkConfigNib.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableMap;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.slf4j.Logger;
-
-import java.util.Map;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Represents Network Information Base (NIB) for network configurations
- * and supports alternative functions to
- * {@link org.onosproject.net.config.NetworkConfigService} for offline data.
- */
-public class NetworkConfigNib extends AbstractNib {
-
- private static final Logger log = getLogger(NetworkConfigNib.class);
-
- // Map of str ConnectPoint : InterfaceConfig
- private Map<String, Config> portConfigMap;
- // Map of str DeviceId : SegmentRoutingDeviceConfig
- private Map<String, Config> deviceConfigMap;
-
- // use the singleton helper to create the instance
- protected NetworkConfigNib() {
- }
-
- /**
- * Sets a map of port : configuration to the port.
- *
- * @param portConfigMap port-config map
- */
- public void setPortConfigMap(Map<String, Config> portConfigMap) {
- this.portConfigMap = portConfigMap;
- }
-
- /**
- * Sets a map of device : configuration to the device.
- *
- * @param deviceConfigMap device-config map
- */
- public void setDeviceConfigMap(Map<String, Config> deviceConfigMap) {
- this.deviceConfigMap = deviceConfigMap;
- }
-
- /**
- * Returns the port-config map.
- *
- * @return port-config map
- */
- public Map<Object, Object> getPortConfigMap() {
- return ImmutableMap.copyOf(portConfigMap);
- }
-
- /**
- * Returns the device-config map.
- *
- * @return device-config map
- */
- public Map<Object, Object> getDeviceConfigMap() {
- return ImmutableMap.copyOf(deviceConfigMap);
- }
-
- /**
- * Returns the configuration for the specified subject and configuration
- * class if one is available; null otherwise.
- *
- * @param subject configuration subject
- * @param configClass configuration class
- * @param <S> type of subject
- * @param <C> type of configuration
- * @return configuration or null if one is not available
- */
- public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
- if (configClass.equals(InterfaceConfig.class)) {
- return (C) portConfigMap.get(subject.toString());
- } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
- return (C) deviceConfigMap.get(subject.toString());
- } else {
- log.warn("Given configuration {} is not supported", configClass.toString());
- return null;
- }
- }
-
- /**
- * Returns the singleton instance of multicast routes NIB.
- *
- * @return instance of multicast routes NIB
- */
- public static NetworkConfigNib getInstance() {
- return NetworkConfigNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final NetworkConfigNib INSTANCE = new NetworkConfigNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/NibProfile.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/NibProfile.java
deleted file mode 100644
index 146d98a..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/NibProfile.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import java.text.SimpleDateFormat;
-
-/**
- * Basic descriptions about a single Network information Base (NIB) instance.
- */
-public class NibProfile {
- // default false means the contents of this NIB are empty at the instantiation
- private boolean valid = false;
- private String date;
- private SourceType sourceType;
-
- public enum SourceType {
- /**
- * Provided by dump files.
- */
- FILE,
- /**
- * Provided by a running system.
- */
- SNAPSHOT
- }
-
- public NibProfile(long date, SourceType sourceType) {
- this.valid = true;
- this.date = new SimpleDateFormat("dd-MM-yyyy hh:mm").format(date);
- this.sourceType = sourceType;
- }
-
- /**
- * Returns the validity state of this NIB.
- *
- * @return true once this profile is initialized
- */
- public boolean isValid() {
- return valid;
- }
-
- /**
- * Returns the time this NIB has been filled.
- *
- * @return string representation for the time
- */
- public String date() {
- return date;
- }
-
- /**
- * Returns the type of the source used to fill this NIB.
- *
- * @return source type
- */
- public SourceType sourceType() {
- return sourceType;
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/RouteNib.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/RouteNib.java
deleted file mode 100644
index 01e6e61..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/RouteNib.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.routeservice.ResolvedRoute;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents Network Information Base (NIB) for routes
- * and supports alternative functions to
- * {@link org.onosproject.routeservice.RouteService} for offline data.
- */
-public class RouteNib extends AbstractNib {
-
- // TODO with method optimization, store into subdivided structures at the first load
- // unresolved Route is treated as ResolvedRoute with nextHopMac null
- Set<ResolvedRoute> routes;
-
- // use the singleton helper to create the instance
- protected RouteNib() {
- }
-
- /**
- * Sets a set of routes.
- *
- * @param routes route set
- */
- public void setRoutes(Set<ResolvedRoute> routes) {
- this.routes = routes;
- }
-
- /**
- * Returns the set of routes.
- *
- * @return route set
- */
- public Set<ResolvedRoute> getRoutes() {
- return routes;
- }
-
- /**
- * Performs a longest prefix lookup on the given IP address.
- *
- * @param ip IP address to look up
- * @return most specific matching route, if one exists
- */
- public Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip) {
- return routes.stream()
- .filter(r -> r.prefix().contains(ip))
- .max(Comparator.comparing(r -> r.prefix().prefixLength()));
- }
-
- /**
- * Returns all resolved routes stored for the given prefix, including the
- * best selected route.
- *
- * @param prefix IP prefix to look up routes for
- * @return all stored resolved routes for this prefix
- */
- public Collection<ResolvedRoute> getAllResolvedRoutes(IpPrefix prefix) {
- return routes.stream()
- .filter(r -> r.prefix().contains(prefix)
- && r.nextHopMac() != null
- && r.nextHopVlan() != null)
- .collect(Collectors.toCollection(ArrayList::new));
- }
-
- /**
- * Returns the singleton instance of multicast routes NIB.
- *
- * @return instance of multicast routes NIB
- */
- public static RouteNib getInstance() {
- return RouteNib.SingletonHelper.INSTANCE;
- }
-
- private static class SingletonHelper {
- private static final RouteNib INSTANCE = new RouteNib();
- }
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
deleted file mode 100644
index 22db007..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import com.google.common.collect.ImmutableList;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.TrafficSelector;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-/**
- * Encapsulates the result of tracing a packet (traffic selector) through
- * the current topology.
- */
-public class StaticPacketTrace {
-
- private final TrafficSelector inPacket;
- private final ConnectPoint in;
- List<List<ConnectPoint>> completePaths;
- private Map<DeviceId, List<GroupsInDevice>> outputsForDevice;
- private Map<DeviceId, List<FlowEntry>> flowsForDevice;
- private StringBuilder resultMessage;
- private Pair<Host, Host> hosts;
- private List<Boolean> success = new ArrayList<>();
-
- /**
- * Builds the trace with a given packet and a connect point.
- *
- * @param packet the packet to trace
- * @param in the initial connect point
- */
- public StaticPacketTrace(TrafficSelector packet, ConnectPoint in) {
- this.inPacket = packet;
- this.in = in;
- completePaths = new ArrayList<>();
- outputsForDevice = new HashMap<>();
- flowsForDevice = new HashMap<>();
- resultMessage = new StringBuilder();
- hosts = null;
- }
-
- /**
- * Builds the trace with a given packet and a connect point.
- *
- * @param packet the packet to trace
- * @param in the initial connect point
- * @param hosts pair of source and destination hosts
- */
- public StaticPacketTrace(TrafficSelector packet, ConnectPoint in, Pair<Host, Host> hosts) {
- this.inPacket = packet;
- this.in = in;
- completePaths = new ArrayList<>();
- outputsForDevice = new HashMap<>();
- flowsForDevice = new HashMap<>();
- resultMessage = new StringBuilder();
- this.hosts = hosts;
- }
-
- /**
- * Return the initial packet.
- *
- * @return the initial packet in the form of a selector.
- */
- public TrafficSelector getInitialPacket() {
- return inPacket;
- }
-
- /**
- * Returns the first connect point the packet came in through.
- *
- * @return the connect point
- */
- public ConnectPoint getInitialConnectPoint() {
- return in;
- }
-
- /**
- * Add a result message for the Trace.
- *
- * @param resultMessage the message
- */
- public void addResultMessage(String resultMessage) {
- if (this.resultMessage.length() != 0) {
- this.resultMessage.append("\n");
- }
- this.resultMessage.append(resultMessage);
- }
-
- /**
- * Return the result message.
- *
- * @return the message
- */
- public String resultMessage() {
- return resultMessage.toString();
- }
-
- /**
- * Adds the groups for a given device.
- *
- * @param deviceId the device
- * @param outputPath the groups in device objects
- */
- public void addGroupOutputPath(DeviceId deviceId, GroupsInDevice outputPath) {
- if (!outputsForDevice.containsKey(deviceId)) {
- outputsForDevice.put(deviceId, new ArrayList<>());
- }
- outputsForDevice.get(deviceId).add(outputPath);
- }
-
- /**
- * Returns all the possible group-based outputs for a given device.
- *
- * @param deviceId the device
- * @return the list of Groups for this device.
- */
- public List<GroupsInDevice> getGroupOuputs(DeviceId deviceId) {
- return outputsForDevice.get(deviceId) == null ? null : ImmutableList.copyOf(outputsForDevice.get(deviceId));
- }
-
- /**
- * Adds a complete possible path.
- *
- * @param completePath the path
- */
- public void addCompletePath(List<ConnectPoint> completePath) {
- completePaths.add(completePath);
- }
-
- /**
- * Return all the possible path the packet can take through the network.
- *
- * @return a list of paths
- */
- public List<List<ConnectPoint>> getCompletePaths() {
- return completePaths;
- }
-
- /**
- * Add the flows traversed by the packet in a given device.
- *
- * @param deviceId the device considered
- * @param flows the flows
- */
- public void addFlowsForDevice(DeviceId deviceId, List<FlowEntry> flows) {
- flowsForDevice.put(deviceId, flows);
- }
-
- /**
- * Returns the flows matched by this trace's packet for a given device.
- *
- * @param deviceId the device
- * @return the flows matched
- */
- public List<FlowEntry> getFlowsForDevice(DeviceId deviceId) {
- return flowsForDevice.getOrDefault(deviceId, ImmutableList.of());
- }
-
- /**
- * Return, if present, the two hosts at the endpoints of this trace.
- *
- * @return pair of source and destination hosts
- */
- public Optional<Pair<Host, Host>> getEndpointHosts() {
- return Optional.ofNullable(hosts);
- }
-
- /**
- * Sets the two hosts at the endpoints of this trace.
- *
- * @param endpointHosts pair of source and destination hosts
- */
- public void addEndpointHosts(Pair<Host, Host> endpointHosts) {
- hosts = endpointHosts;
- }
-
- /**
- * Return if all the possible paths of this trace are successful.
- *
- * @return true if all paths are successful
- */
- public boolean isSuccess() {
- return !success.contains(false);
- }
-
- /**
- * Sets if a path from this trace is successful.
- *
- * @param success true if a path of trace is successful.
- */
- public void setSuccess(boolean success) {
- this.success.add(success);
- }
-
-
- @Override
- public String toString() {
- return "StaticPacketTrace{" +
- "inPacket=" + inPacket +
- ", in=" + in +
- ", completePaths=" + completePaths +
- ", outputsForDevice=" + outputsForDevice +
- ", flowsForDevice=" + flowsForDevice +
- ", resultMessage=" + resultMessage +
- '}';
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/TroubleshootService.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/TroubleshootService.java
deleted file mode 100644
index 3ab6052..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/TroubleshootService.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.api;
-
-import org.onlab.packet.EthType;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.HostId;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.t3.impl.Generator;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * API for troubleshooting services, providing static analysis of installed
- * flows and groups.
- */
-public interface TroubleshootService {
-
- /**
- * Requests a static trace be performed between all hosts in the network, given a type of traffic.
- *
- * @param type the etherType of the traffic we want to trace.
- * @return trace result
- */
- List<StaticPacketTrace> pingAll(EthType.EtherType type);
-
- /**
- * Requests a static trace be performed between all hosts in the network, given a type of traffic.
- *
- * @param type the etherType of the traffic we want to trace.
- * @return trace result
- */
- Generator<Set<StaticPacketTrace>> pingAllGenerator(EthType.EtherType type);
-
- /**
- * Requests a static trace be performed for all mcast Routes in the network.
- *
- * @param vlanId the vlanId configured for multicast.
- * @return set of trace result yielded one by one.
- */
- Generator<Set<StaticPacketTrace>> traceMcast(VlanId vlanId);
-
- /**
- * Requests a static trace be performed between the two hosts in the network, given a type of traffic.
- *
- * @param sourceHost source host
- * @param destinationHost destination host
- * @param type the etherType of the traffic we want to trace.
- * @return trace result
- */
- Set<StaticPacketTrace> trace(HostId sourceHost, HostId destinationHost, EthType.EtherType type);
-
- /**
- * Requests a static trace be performed for the given traffic selector
- * starting at the given connect point.
- *
- * @param packet description of packet
- * @param in point at which packet starts
- * @return trace result
- */
- StaticPacketTrace trace(TrafficSelector packet, ConnectPoint in);
-
- /**
- * Requests list of static trace to be performed for all mcast routes in the network.
- *
- * @param vlanId the vlan id configured for multicast
- * @return list of trace result
- */
- List<Set<StaticPacketTrace>> getMulitcastTrace(VlanId vlanId);
-
- /**
- * Checks the validity of NIBs applied to the manager.
- *
- * @return true only if all NIBs are in the valid state.
- */
- boolean checkNibValidity();
-
- /**
- * Returns a summary describing all the NIBs applied to the manager.
- *
- * @return string for the summary
- */
- String printNibSummary();
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/api/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/api/package-info.java
deleted file mode 100644
index 152d568..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/api/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics API.
- */
-package org.onosproject.t3.api;
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/NibLoader.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/NibLoader.java
deleted file mode 100644
index 40690ca..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/NibLoader.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import java.io.IOException;
-
-/**
- * Common APIs for T3 CLI commands to load snapshots of the network states
- * from {@link org.onosproject.t3.api.NibProfile.SourceType} and fill the NIB.
- */
-public interface NibLoader {
-
- /**
- * Extracts flow-related information and fills the flow NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadFlowNib() throws IOException;
-
- /**
- * Extracts group-related information and fills the group NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadGroupNib() throws IOException;
-
- /**
- * Extracts host-related information and fills the host NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadHostNib() throws IOException;
-
- /**
- * Extracts link-related information and fills the link NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadLinkNib() throws IOException;
-
- /**
- * Extracts device-related information and fills the device NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadDeviceNib() throws IOException;
-
- /**
- * Extracts driver-related information and fills the driver NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadDriverNib() throws IOException;
-
- /**
- * Extracts mastership-related information and fills the mastership NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadMastershipNib() throws IOException;
-
- /**
- * Extracts edge port-related information and fills the edge port NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadEdgePortNib() throws IOException;
-
- /**
- * Extracts route-related information and fills the route NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadRouteNib() throws IOException;
-
- /**
- * Extracts network config-related information and fills the network configuration NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadNetworkConfigNib() throws IOException;
-
- /**
- * Extracts multicast route-related information and fills the multicast route NIB.
- *
- * @throws IOException exception during possible file I/O
- */
- void loadMulticastRouteNib() throws IOException;
-
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/T3CliUtils.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/T3CliUtils.java
deleted file mode 100644
index ddbdb38..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/T3CliUtils.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import org.apache.commons.lang.StringUtils;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.t3.api.GroupsInDevice;
-import org.onosproject.t3.api.StaticPacketTrace;
-
-import java.util.List;
-
-/**
- * Class containing utility methods for T3 cli.
- */
-final class T3CliUtils {
-
- private T3CliUtils() {
- //banning construction
- }
-
- private static final String FLOW_SHORT_FORMAT = " %s, bytes=%s, packets=%s, "
- + "table=%s, priority=%s, selector=%s, treatment=%s";
-
- private static final String GROUP_FORMAT =
- " id=0x%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s, referenceCount=%s";
- private static final String GROUP_BUCKET_FORMAT =
- " id=0x%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
-
- public static final String NIB_AUTOFILLED =
- "*** NIB is invalid. Snapshots for the NIB have been auto-filled: ***";
- public static final String NIB_TERMINATE =
- "*** NIB is still invalid. You can manually load it via CLI commands for T3 load and try again ***";
-
- /**
- * Builds a string output for the given trace for a specific level of verbosity.
- *
- * @param trace the trace
- * @param verbosity1 middle verbosity level
- * @param verbosity2 high verbosity level
- * @return a string representing the trace.
- */
- static String printTrace(StaticPacketTrace trace, boolean verbosity1, boolean verbosity2) {
- StringBuilder tracePrint = new StringBuilder();
- //Print based on verbosity
- if (verbosity1) {
- tracePrint = printTrace(trace, false, tracePrint);
- } else if (verbosity2) {
- tracePrint = printTrace(trace, true, tracePrint);
- } else {
- tracePrint.append("Paths");
- tracePrint.append("\n");
- List<List<ConnectPoint>> paths = trace.getCompletePaths();
- for (List<ConnectPoint> path : paths) {
- tracePrint.append(path);
- tracePrint.append("\n");
- }
- }
- tracePrint.append("Result: \n" + trace.resultMessage());
- return tracePrint.toString();
- }
-
- //prints the trace
- private static StringBuilder printTrace(StaticPacketTrace trace, boolean verbose, StringBuilder tracePrint) {
- List<List<ConnectPoint>> paths = trace.getCompletePaths();
- for (List<ConnectPoint> path : paths) {
- tracePrint.append("Path " + path);
- tracePrint.append("\n");
- ConnectPoint previous = null;
- if (path.size() == 1) {
- ConnectPoint connectPoint = path.get(0);
- tracePrint.append("Device " + connectPoint.deviceId());
- tracePrint.append("\n");
- tracePrint.append("Input from " + connectPoint);
- tracePrint.append("\n");
- tracePrint = printFlows(trace, verbose, connectPoint, tracePrint);
- tracePrint = printGroups(trace, verbose, connectPoint, tracePrint);
- tracePrint.append("\n");
- } else {
- for (ConnectPoint connectPoint : path) {
- if (previous == null || !previous.deviceId().equals(connectPoint.deviceId())) {
- tracePrint.append("Device " + connectPoint.deviceId());
- tracePrint.append("\n");
- tracePrint.append(" Input from " + connectPoint);
- tracePrint.append("\n");
- tracePrint = printFlows(trace, verbose, connectPoint, tracePrint);
- } else {
- tracePrint = printGroups(trace, verbose, connectPoint, tracePrint);
- tracePrint.append(" Output through " + connectPoint);
- tracePrint.append("\n");
- }
- previous = connectPoint;
- }
- }
- tracePrint.append(StringUtils.leftPad("\n", 100, '-'));
- }
- return tracePrint;
- }
-
-
- //Prints the flows for a given trace and a specified level of verbosity
- private static StringBuilder printFlows(StaticPacketTrace trace, boolean verbose, ConnectPoint connectPoint,
- StringBuilder tracePrint) {
- tracePrint.append(" Flows ");
- tracePrint.append(trace.getFlowsForDevice(connectPoint.deviceId()).size());
- tracePrint.append(" \n");
- trace.getFlowsForDevice(connectPoint.deviceId()).forEach(f -> {
- if (verbose) {
- tracePrint.append(" " + String.format(FLOW_SHORT_FORMAT, f.state(), f.bytes(), f.packets(),
- f.table(), f.priority(), f.selector().criteria(),
- printTreatment(f.treatment())));
- tracePrint.append("\n");
- } else {
- tracePrint.append(String.format(" flowId=%s, table=%s, selector=%s", f.id(), f.table(),
- f.selector().criteria()));
- tracePrint.append("\n");
- }
- });
- return tracePrint;
- }
-
- //Prints the groups for a given trace and a specified level of verbosity
- private static StringBuilder printGroups(StaticPacketTrace trace, boolean verbose, ConnectPoint connectPoint,
- StringBuilder tracePrint) {
- List<GroupsInDevice> groupsInDevice = trace.getGroupOuputs(connectPoint.deviceId());
- if (groupsInDevice != null) {
- tracePrint.append(" Groups");
- tracePrint.append("\n");
- groupsInDevice.forEach(output -> {
- if (output.getOutput().equals(connectPoint)) {
- output.getGroups().forEach(group -> {
- if (verbose) {
- tracePrint.append(" " + String.format(GROUP_FORMAT, Integer.toHexString(group.id().id()),
- group.state(), group.type(), group.bytes(), group.packets(),
- group.appId().name(), group.referenceCount()));
- tracePrint.append("\n");
- int i = 0;
- for (GroupBucket bucket : group.buckets().buckets()) {
- tracePrint.append(" " + String.format(GROUP_BUCKET_FORMAT,
- Integer.toHexString(group.id().id()),
- ++i, bucket.bytes(), bucket.packets(),
- bucket.treatment().allInstructions()));
- tracePrint.append("\n");
- }
- } else {
- tracePrint.append(" groupId=" + group.id());
- tracePrint.append("\n");
- }
- });
- tracePrint.append(" Outgoing Packet " + output.getFinalPacket());
- tracePrint.append("\n");
- }
- });
- }
- return tracePrint;
- }
-
- private static String printTreatment(TrafficTreatment treatment) {
- final String delimiter = ", ";
- StringBuilder builder = new StringBuilder("[");
- if (!treatment.immediate().isEmpty()) {
- builder.append("immediate=" + treatment.immediate() + delimiter);
- }
- if (!treatment.deferred().isEmpty()) {
- builder.append("deferred=" + treatment.deferred() + delimiter);
- }
- if (treatment.clearedDeferred()) {
- builder.append("clearDeferred" + delimiter);
- }
- if (treatment.tableTransition() != null) {
- builder.append("transition=" + treatment.tableTransition() + delimiter);
- }
- if (treatment.metered() != null) {
- builder.append("meter=" + treatment.metered() + delimiter);
- }
- if (treatment.writeMetadata() != null) {
- builder.append("metadata=" + treatment.writeMetadata() + delimiter);
- }
- // Chop off last delimiter
- builder.replace(builder.length() - delimiter.length(), builder.length(), "");
- builder.append("]");
- return builder.toString();
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadFileCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadFileCommand.java
deleted file mode 100644
index 58b99d6..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadFileCommand.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.Lists;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.group.Group;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.Route;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.NetworkConfigNib;
-import org.onosproject.t3.api.NibProfile;
-import org.onosproject.t3.api.RouteNib;
-import org.slf4j.Logger;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * T3 CLI command to load the NIB with dump files that represent snapshots of the network states.
- */
-@Service
-@Command(scope = "onos", name = "t3-load-file",
- description = "Load the NIB with onos-diagnostics dump files")
-public class TroubleshootLoadFileCommand
- extends AbstractShellCommand implements NibLoader {
-
- private static final Logger log = getLogger(TroubleshootLoadFileCommand.class);
-
- @Argument(index = 0, name = "rootDir", description = "Specify the location of the directory " +
- "where the dump files of a given instance have been extracted (e.g. /tmp/onos-diags/127.0.0.1)",
- required = true, multiValued = false)
- @Completion(PlaceholderCompleter.class)
- String rootDir;
-
- @Override
- protected void doExecute() {
-
- if (!rootDir.endsWith("/")) {
- rootDir = rootDir + "/";
- }
- print("Load target files in: %s", rootDir);
-
- try {
- // names of files to read are defined in the onos-diagnostics script
- loadFlowNib();
- loadGroupNib();
- loadLinkNib();
- loadHostNib();
- loadDeviceNib();
- loadDriverNib();
- loadMastershipNib();
- loadEdgePortNib();
- loadRouteNib();
- loadNetworkConfigNib();
- loadMulticastRouteNib();
-
- } catch (IOException e) {
- print("Error in creating NIB: %s", e.getMessage());
- log.error("Nib creation error", e);
- return;
- }
-
- // ensured no errors in file loading. so make them available officially
- Lists.newArrayList(FlowNib.getInstance(), GroupNib.getInstance(), LinkNib.getInstance(),
- HostNib.getInstance(), DeviceNib.getInstance(), DriverNib.getInstance(),
- MastershipNib.getInstance(), EdgePortNib.getInstance(), RouteNib.getInstance(),
- NetworkConfigNib.getInstance(), MulticastRouteNib.getInstance())
- .forEach(nib -> {
- // specify creation time and source which the NIB is filled with
- nib.setProfile(new NibProfile(System.currentTimeMillis(), NibProfile.SourceType.FILE));
- NibProfile profile = nib.getProfile();
- print(String.format(
- nib.getClass().getSimpleName() + " created %s from %s",
- profile.date(), profile.sourceType()));
- });
- }
-
- @Override
- public void loadFlowNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "flows.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Set<FlowEntry> flows = new HashSet<>();
-
- List<ObjectNode> flowNodeList = new ArrayList<>();
- jsonTree.forEach(jsonNode -> {
- ArrayNode flowArrayNode = (ArrayNode) jsonNode.get("flows");
- Lists.newArrayList(flowArrayNode.iterator())
- .forEach(flowNode -> flowNodeList.add((ObjectNode) flowNode));
- });
-
- // TODO: future plan for the new APIs of the flow rule service that returns raw flows or normalized flows
- flowNodeList.forEach(flowNode -> {
- FlowEntry flow;
- try {
- flow = codec(FlowEntry.class).decode(flowNode, this);
- } catch (IllegalArgumentException e) {
- log.warn("T3 in offline mode ignores reading extension fields of this flow to avoid decoding error");
- ObjectNode extensionRemoved = removeExtension(flowNode);
- flow = codec(FlowEntry.class).decode(extensionRemoved, this);
- }
- flows.add(flow);
- });
-
- FlowNib flowNib = FlowNib.getInstance();
- flowNib.setFlows(flows);
-
- stream.close();
- }
-
- /**
- * Remove JSON nodes for extension instructions of a flow.
- * This effectively allows T3 in offline mode to ignore extension fields of flows to avoid "device not found" error.
- * See decodeExtension() in {@link org.onosproject.codec.impl.DecodeInstructionCodecHelper}.
- *
- * @param flowNode the json node representing a flow
- * @return json node with removed extensions
- */
- private ObjectNode removeExtension(ObjectNode flowNode) {
-
- // TODO: decoding extension instructions of offline (dumped) flows is not supported by T3 for now
- ArrayNode extensionRemoved = mapper().createArrayNode();
- ArrayNode instructionArrayNode = (ArrayNode) flowNode.get("treatment").get("instructions");
- instructionArrayNode.forEach(instrNode -> {
- String instrType = instrNode.get("type").asText();
- if (!instrType.equals(Instruction.Type.EXTENSION.name())) {
- extensionRemoved.add(instrNode);
- }
- });
- ((ObjectNode) flowNode.get("treatment")).replace("instructions", extensionRemoved);
-
- return flowNode;
- }
-
- @Override
- public void loadGroupNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "groups.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Set<Group> groups = new HashSet<>();
-
- // note: the parsing structure depends on GroupsListCommand
- groups.addAll(codec(Group.class).decode((ArrayNode) jsonTree, this));
-
- GroupNib groupNib = GroupNib.getInstance();
- groupNib.setGroups(groups);
-
- stream.close();
- }
-
- @Override
- public void loadLinkNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "links.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Set<Link> links = new HashSet<>();
-
- // note: the parsing structure depends on LinksListCommand
- links.addAll(codec(Link.class).decode((ArrayNode) jsonTree, this));
-
- LinkNib linkNib = LinkNib.getInstance();
- linkNib.setLinks(links);
-
- stream.close();
- }
-
- @Override
- public void loadHostNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "hosts.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Set<Host> hosts = new HashSet<>();
-
- // note: the parsing structure depends on HostsListCommand
- hosts.addAll(codec(Host.class).decode((ArrayNode) jsonTree, this));
-
- HostNib hostNib = HostNib.getInstance();
- hostNib.setHosts(hosts);
-
- stream.close();
- }
-
- @Override
- public void loadDeviceNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "ports.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Map<Device, Set<Port>> devicePortMap = new HashMap<>();
-
- // note: the parsing structure depends on DevicePortsListCommand
- jsonTree.forEach(jsonNode -> {
- Device device = codec(Device.class).decode(
- (ObjectNode) jsonNode.get("device"), this);
- Set<Port> ports = new HashSet<>(codec(Port.class).decode(
- (ArrayNode) jsonNode.get("ports"), this));
- devicePortMap.put(device, ports);
- });
-
- DeviceNib deviceNib = DeviceNib.getInstance();
- deviceNib.setDevicePortMap(devicePortMap);
-
- stream.close();
- }
-
- @Override
- public void loadDriverNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "device-drivers.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Map<DeviceId, String> deviceDriverMap = new HashMap<>();
-
- // note: the parsing structure depends on DeviceDriversCommand
- jsonTree.fields().forEachRemaining(e -> {
- deviceDriverMap.put(DeviceId.deviceId(e.getKey()), e.getValue().asText());
- });
-
- DriverNib driverNib = DriverNib.getInstance();
- driverNib.setDeviceDriverMap(deviceDriverMap);
-
- stream.close();
- }
-
- @Override
- public void loadMastershipNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "masters.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Map<DeviceId, NodeId> deviceMasterMap = new HashMap<>();
-
- // note: the parsing structure depends on MastersListCommand
- jsonTree.forEach(jsonNode -> {
- ArrayNode devicesNode = ((ArrayNode) jsonNode.get("devices"));
- devicesNode.forEach(deviceNode -> {
- // a device is connected to only one master node at a time
- deviceMasterMap.put(
- DeviceId.deviceId(deviceNode.asText()),
- NodeId.nodeId(jsonNode.get("id").asText()));
- });
- });
-
- MastershipNib mastershipNib = MastershipNib.getInstance();
- mastershipNib.setDeviceMasterMap(deviceMasterMap);
-
- stream.close();
- }
-
- @Override
- public void loadEdgePortNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "edge-ports.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Map<DeviceId, Set<ConnectPoint>> edgePorts = new HashMap<>();
-
- // note: the parsing structure depends on EdgePortsListCommand
- jsonTree.forEach(jsonNode -> {
- DeviceId deviceId = DeviceId.deviceId(jsonNode.fieldNames().next());
- PortNumber portNumber = PortNumber.portNumber(
- jsonNode.get(deviceId.toString()).asText());
- if (!edgePorts.containsKey(deviceId)) {
- edgePorts.put(deviceId, new HashSet<>());
- }
- edgePorts.get(deviceId).add(new ConnectPoint(deviceId, portNumber));
- });
-
- EdgePortNib edgePortNib = EdgePortNib.getInstance();
- edgePortNib.setEdgePorts(edgePorts);
-
- stream.close();
- }
-
- @Override
- public void loadRouteNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "routes.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Set<ResolvedRoute> routes = new HashSet<>();
-
- // note: the parsing structure depends on RoutesListCommand
- jsonTree.fields().forEachRemaining(e -> {
- ArrayNode routesNode = (ArrayNode) e.getValue();
- routesNode.forEach(routeNode -> {
- Route route = codec(Route.class).decode((ObjectNode) routeNode, this);
- // parse optional fields needed for ResolvedRoute
- MacAddress nextHopMac = (null == routeNode.get("nextHopMac")) ?
- null : MacAddress.valueOf(routeNode.get("nextHopMac").asText());
- VlanId nextHopVlan = (null == routeNode.get("nextHopVlan")) ?
- null : VlanId.vlanId(routeNode.get("nextHopVlan").asText());
- routes.add(new ResolvedRoute(route, nextHopMac, nextHopVlan));
- });
- });
-
- RouteNib routeNib = RouteNib.getInstance();
- routeNib.setRoutes(routes);
-
- stream.close();
- }
-
- @Override
- public void loadNetworkConfigNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "netcfg.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Map<String, Config> portConfigMap = new HashMap<>();
- Map<String, Config> deviceConfigMap = new HashMap<>();
-
- // note: the parsing structure depends on NetworkConfigCommand
- // TODO: improve the code quality by referring to target json
- jsonTree.fields().forEachRemaining(e -> {
- if (e.getKey().equals("ports")) {
- JsonNode portConfigsNode = e.getValue();
- portConfigsNode.fields().forEachRemaining(portConfigEntry -> {
- String key = portConfigEntry.getKey();
- InterfaceConfig config = new InterfaceConfig();
- config.init(ConnectPoint.fromString(key), "interfaces",
- portConfigEntry.getValue().get("interfaces"), mapper(), null);
- portConfigMap.put(key, config);
- });
- } else if (e.getKey().equals("devices")) {
- JsonNode deviceConfigsNode = e.getValue();
- deviceConfigsNode.fields().forEachRemaining(deviceConfigEntry -> {
- String key = deviceConfigEntry.getKey();
- SegmentRoutingDeviceConfig config = new SegmentRoutingDeviceConfig();
- config.init(DeviceId.deviceId(key), "segmentrouting",
- deviceConfigEntry.getValue().get("segmentrouting"), mapper(), null);
- deviceConfigMap.put(key, config);
- });
- } else {
- log.warn("Given configuration subject {} is not supported", e.getKey());
- }
- });
-
- NetworkConfigNib networkConfigNib = NetworkConfigNib.getInstance();
- networkConfigNib.setPortConfigMap(portConfigMap);
- networkConfigNib.setDeviceConfigMap(deviceConfigMap);
-
- stream.close();
- }
-
- @Override
- public void loadMulticastRouteNib() throws IOException {
- InputStream stream = new FileInputStream(new File(rootDir + "mcast-host-show.json"));
- JsonNode jsonTree = mapper().readTree(stream);
- Map<McastRoute, McastRouteData> mcastRoutes = new HashMap<>();
-
- // note: the parsing structure depends on McastShowHostCommand
- jsonTree.forEach(mcastRouteNode -> {
- // use McastHostRouteCodec to decode McastRoute
- McastRoute mcastRoute = codec(McastRoute.class)
- .decode((ObjectNode) mcastRouteNode, this);
- // create McastRouteData that stores sources and sinks of McastRoute
- McastRouteData mcastRouteData = McastRouteData.empty();
- if (mcastRouteNode.get("sources") != null) {
- JsonNode sourcesNode = mcastRouteNode.get("sources");
- sourcesNode.fields().forEachRemaining(sourceEntry -> {
- HostId hostId = HostId.hostId(sourceEntry.getKey());
- Set<ConnectPoint> sources = mapper().convertValue(
- sourceEntry.getValue(), new TypeReference<Set<ConnectPoint>>() { });
- mcastRouteData.addSources(hostId, sources);
- });
- }
- if (mcastRouteNode.get("sinks") != null) {
- JsonNode sinksNode = mcastRouteNode.get("sinks");
- sinksNode.fields().forEachRemaining(sinkEntry -> {
- HostId hostId = HostId.hostId(sinkEntry.getKey());
- Set<ConnectPoint> sinks = mapper().convertValue(
- sinkEntry.getValue(), new TypeReference<Set<ConnectPoint>>() { });
- mcastRouteData.addSinks(hostId, sinks);
- });
- }
- mcastRoutes.put(mcastRoute, mcastRouteData);
- });
-
- MulticastRouteNib mcastRouteNib = MulticastRouteNib.getInstance();
- mcastRouteNib.setMcastRoutes(mcastRoutes);
-
- stream.close();
- }
-
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadSnapshotCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadSnapshotCommand.java
deleted file mode 100644
index 9a6b20b..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootLoadSnapshotCommand.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright 2020-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.mcast.api.McastRoute;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.mcast.api.MulticastRouteService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.DriverService;
-import org.onosproject.net.edge.EdgePortService;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupService;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.routeservice.RouteService;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.NetworkConfigNib;
-import org.onosproject.t3.api.NibProfile;
-import org.onosproject.t3.api.RouteNib;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * T3 CLI command to load the NIB with snapshots of the network states that are fetched from ONOS stores.
- */
-@Service
-@Command(scope = "onos", name = "t3-load-snapshot",
- description = "Load the NIB with the network states stored in the ONOS instance where the T3 is running")
-public class TroubleshootLoadSnapshotCommand
- extends AbstractShellCommand implements NibLoader {
-
- @Override
- protected void doExecute() {
-
- print("Load current network states from ONOS stores");
-
- loadFlowNib();
- loadGroupNib();
- loadLinkNib();
- loadHostNib();
- loadDeviceNib();
- loadDriverNib();
- loadMastershipNib();
- loadEdgePortNib();
- loadRouteNib();
- loadNetworkConfigNib();
- loadMulticastRouteNib();
-
- Lists.newArrayList(FlowNib.getInstance(), GroupNib.getInstance(), LinkNib.getInstance(),
- HostNib.getInstance(), DeviceNib.getInstance(), DriverNib.getInstance(),
- MastershipNib.getInstance(), EdgePortNib.getInstance(), RouteNib.getInstance(),
- NetworkConfigNib.getInstance(), MulticastRouteNib.getInstance())
- .forEach(nib -> {
- // specify creation time and source which the NIB is filled with
- nib.setProfile(new NibProfile(System.currentTimeMillis(), NibProfile.SourceType.SNAPSHOT));
- NibProfile profile = nib.getProfile();
- print(String.format(
- nib.getClass().getSimpleName() + " created %s from %s",
- profile.date(), profile.sourceType()));
- });
- }
-
- @Override
- public void loadFlowNib() {
- FlowRuleService flowRuleService = get(FlowRuleService.class);
- DeviceService deviceService = get(DeviceService.class);
- Set<FlowEntry> flows = new HashSet<>();
-
- Lists.newArrayList(deviceService.getDevices().iterator())
- .forEach(device -> flows.addAll(Lists.newArrayList(
- flowRuleService.getFlowEntries(device.id()))));
-
- FlowNib flowNib = FlowNib.getInstance();
- flowNib.setFlows(flows);
- }
-
- @Override
- public void loadGroupNib() {
- GroupService groupService = get(GroupService.class);
- DeviceService deviceService = get(DeviceService.class);
- Set<Group> groups = new HashSet<>();
-
- Lists.newArrayList(deviceService.getDevices().iterator())
- .forEach(device -> groups.addAll(Lists.newArrayList(
- groupService.getGroups(device.id()))));
-
- GroupNib groupNib = GroupNib.getInstance();
- groupNib.setGroups(groups);
- }
-
- @Override
- public void loadLinkNib() {
- LinkService linkService = get(LinkService.class);
- Set<Link> links = new HashSet<>();
-
- links.addAll(Lists.newArrayList(linkService.getLinks()));
-
- LinkNib linkNib = LinkNib.getInstance();
- linkNib.setLinks(links);
- }
-
- @Override
- public void loadHostNib() {
- HostService hostService = get(HostService.class);
- Set<Host> hosts = new HashSet<>();
-
- hosts.addAll(Lists.newArrayList(hostService.getHosts()));
-
- HostNib hostNib = HostNib.getInstance();
- hostNib.setHosts(hosts);
- }
-
- @Override
- public void loadDeviceNib() {
- DeviceService deviceService = get(DeviceService.class);
- Map<Device, Set<Port>> devicePortMap = new HashMap<>();
-
- Lists.newArrayList(deviceService.getDevices().iterator())
- .forEach(device -> {
- // current DeviceNib impl. checks the availability of devices from their annotations
- DefaultAnnotations annotations = DefaultAnnotations.builder()
- .set("available", String.valueOf(deviceService.isAvailable(device.id()))).build();
- DefaultDevice annotated = new DefaultDevice(device.providerId(), device.id(), device.type(),
- device.manufacturer(), device.hwVersion(), device.swVersion(), device.serialNumber(),
- device.chassisId(), annotations);
- devicePortMap.put(annotated, Sets.newHashSet(deviceService.getPorts(device.id())));
- });
-
- DeviceNib deviceNib = DeviceNib.getInstance();
- deviceNib.setDevicePortMap(devicePortMap);
- }
-
- @Override
- public void loadDriverNib() {
- DriverService driverService = get(DriverService.class);
- Map<DeviceId, String> deviceDriverMap = driverService.getDeviceDrivers();
-
- DriverNib driverNib = DriverNib.getInstance();
- driverNib.setDeviceDriverMap(deviceDriverMap);
- }
-
- @Override
- public void loadMastershipNib() {
- MastershipService mastershipService = get(MastershipService.class);
- DeviceService deviceService = get(DeviceService.class);
- Map<DeviceId, NodeId> deviceMasterMap = new HashMap<>();
-
- Lists.newArrayList(deviceService.getDevices().iterator())
- .forEach(device -> deviceMasterMap.put(device.id(), mastershipService.getMasterFor(device.id())));
-
- MastershipNib mastershipNib = MastershipNib.getInstance();
- mastershipNib.setDeviceMasterMap(deviceMasterMap);
- }
-
- @Override
- public void loadEdgePortNib() {
- EdgePortService edgePortService = get(EdgePortService.class);
- DeviceService deviceService = get(DeviceService.class);
- Map<DeviceId, Set<ConnectPoint>> edgePorts = new HashMap<>();
-
- Lists.newArrayList(deviceService.getDevices().iterator())
- .forEach(device -> edgePorts.put(device.id(), Sets.newHashSet(edgePortService.getEdgePoints())));
-
- EdgePortNib edgePortNib = EdgePortNib.getInstance();
- edgePortNib.setEdgePorts(edgePorts);
- }
-
- @Override
- public void loadRouteNib() {
- RouteService routeService = get(RouteService.class);
- Set<ResolvedRoute> routes = new HashSet<>();
-
- Lists.newArrayList(routeService.getRouteTables())
- .forEach(routeTableId -> routes.addAll(routeService.getResolvedRoutes(routeTableId)));
-
- RouteNib routeNib = RouteNib.getInstance();
- routeNib.setRoutes(routes);
- }
-
- @Override
- public void loadNetworkConfigNib() {
- NetworkConfigService networkConfigService = get(NetworkConfigService.class);
- DeviceService deviceService = get(DeviceService.class);
-
- // Map of str ConnectPoint : InterfaceConfig
- Map<String, Config> portConfigMap = new HashMap<>();
- Lists.newArrayList(deviceService.getDevices().iterator())
- .forEach(device -> deviceService.getPorts(device.id())
- .forEach(port -> {
- ConnectPoint cp = new ConnectPoint(device.id(), port.number());
- portConfigMap.put(cp.toString(), networkConfigService.getConfig(cp, InterfaceConfig.class));
- }));
-
- // Map of str DeviceId : SegmentRoutingDeviceConfig
- Map<String, Config> deviceConfigMap = new HashMap<>();
- Lists.newArrayList(deviceService.getDevices().iterator())
- .forEach(device -> deviceConfigMap.put(device.id().toString(),
- networkConfigService.getConfig(device.id(), SegmentRoutingDeviceConfig.class)));
-
- NetworkConfigNib networkConfigNib = NetworkConfigNib.getInstance();
- networkConfigNib.setPortConfigMap(portConfigMap);
- networkConfigNib.setDeviceConfigMap(deviceConfigMap);
- }
-
- @Override
- public void loadMulticastRouteNib() {
- MulticastRouteService mcastRouteService = get(MulticastRouteService.class);
- Map<McastRoute, McastRouteData> mcastRoutes = new HashMap<>();
-
- Lists.newArrayList(mcastRouteService.getRoutes())
- .forEach(mcastRoute -> mcastRoutes.put(mcastRoute, mcastRouteService.routeData(mcastRoute)));
-
- MulticastRouteNib mcastRouteNib = MulticastRouteNib.getInstance();
- mcastRouteNib.setMcastRoutes(mcastRoutes);
- }
-
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootMcastCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootMcastCommand.java
deleted file mode 100644
index d635c23..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootMcastCommand.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.onosproject.t3.impl.Generator;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Starts a Static Packet Trace for all the multicast routes in the system and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot-mcast",
- description = "Traces all the mcast routes present in the system")
-public class TroubleshootMcastCommand extends AbstractShellCommand {
-
- @Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each mcast route")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity1 = false;
-
- @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs middle level details of every trace")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity2 = false;
-
- @Option(name = "-vvv", aliases = "--veryveryverbose", description = "Outputs complete details of every trace")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity3 = false;
-
- @Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
- @Completion(PlaceholderCompleter.class)
- String vlan = "None";
-
-
- @Override
- protected void doExecute() {
- TroubleshootService service = get(TroubleshootService.class);
- if (!service.checkNibValidity()) {
- // if the NIB is found invalid, fill it with the current network states so that this command can proceed
- print(T3CliUtils.NIB_AUTOFILLED);
- TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
- cmd.doExecute();
- if (!service.checkNibValidity()) {
- // if the NIB is still invalid even after auto-filled snapshots, stop and warn
- print(T3CliUtils.NIB_TERMINATE);
- return;
- }
- } else {
- print(service.printNibSummary());
- }
-
- print("Tracing all Multicast routes in the System");
-
- //Create the generator for the list of traces.
- VlanId vlanId = vlan == null || vlan.isEmpty() ? VlanId.NONE : VlanId.vlanId(vlan);
- Generator<Set<StaticPacketTrace>> generator = service.traceMcast(vlanId);
- int totalTraces = 0;
- List<StaticPacketTrace> failedTraces = new ArrayList<>();
- StaticPacketTrace previousTrace = null;
- while (generator.iterator().hasNext()) {
- totalTraces++;
- //Print also Route if possible or packet
- Set<StaticPacketTrace> traces = generator.iterator().next();
- if (!verbosity1 && !verbosity2 && !verbosity3) {
- for (StaticPacketTrace trace : traces) {
- previousTrace = printTrace(previousTrace, trace);
- if (!trace.isSuccess()) {
- print("Failure: %s", trace.resultMessage());
- failedTraces.add(trace);
- } else {
- print(trace.resultMessage());
- }
- }
- } else {
- traces.forEach(trace -> {
- print("Tracing packet: %s", trace.getInitialPacket());
- print("%s", T3CliUtils.printTrace(trace, verbosity2, verbosity3));
- print("%s", StringUtils.rightPad("", 125, '-'));
- });
- }
- }
-
- if (!verbosity1 && !verbosity2 && !verbosity3) {
- if (failedTraces.size() != 0) {
- print("%s", StringUtils.rightPad("", 125, '-'));
- print("Failed Traces: %s", failedTraces.size());
- }
- previousTrace = null;
- for (StaticPacketTrace trace : failedTraces) {
- previousTrace = printTrace(previousTrace, trace);
- print("Failure: %s", trace.resultMessage());
- }
- print("%s", StringUtils.rightPad("", 125, '-'));
- print("Summary");
- print("Total Traces %s, errors %s", totalTraces, failedTraces.size());
- print("%s", StringUtils.rightPad("", 125, '-'));
- }
-
- }
-
- private StaticPacketTrace printTrace(StaticPacketTrace previousTrace, StaticPacketTrace trace) {
- if (previousTrace == null || !previousTrace.equals(trace)) {
- print("%s", StringUtils.rightPad("", 125, '-'));
- previousTrace = trace;
- ConnectPoint initialConnectPoint = trace.getInitialConnectPoint();
- TrafficSelector initialPacket = trace.getInitialPacket();
- boolean isIPv4 = ((EthTypeCriterion) initialPacket.getCriterion(Criterion.Type.ETH_TYPE))
- .ethType().equals(EthType.EtherType.IPV4.ethType()
- );
- IpPrefix group = ((IPCriterion) (isIPv4 ? trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV4_DST) : trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV6_DST))).ip();
- print("Source %s, group %s", initialConnectPoint, group);
- }
- StringBuilder destinations = new StringBuilder();
- if (trace.getCompletePaths().size() > 1) {
- destinations.append("Sinks: ");
- } else {
- destinations.append("Sink: ");
- }
- trace.getCompletePaths().forEach(path -> {
- destinations.append(path.get(path.size() - 1) + " ");
- });
- print("%s", destinations.toString());
- return previousTrace;
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllCommand.java
deleted file mode 100644
index e61a533..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootPingAllCommand.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.EthTypeCompleter;
-import org.onosproject.net.Host;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.onosproject.t3.impl.Generator;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import static java.lang.Thread.sleep;
-import static org.onlab.packet.EthType.EtherType;
-
-/**
- * Starts a Static Packet Trace for a given input and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot-pingall",
- description = "Traces a ping between all hosts in the system of a given ETH type")
-public class TroubleshootPingAllCommand extends AbstractShellCommand {
-
- private static final String FMT_SHORT =
- "id=%s, mac=%s, locations=%s, vlan=%s, ip(s)=%s";
-
- @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
- @Completion(EthTypeCompleter.class)
- String ethType = "ipv4";
-
- @Option(name = "-v", aliases = "--verbose", description = "Outputs trace for each host to host combination")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity1 = false;
-
- @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs details of every trace")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity2 = false;
-
- @Option(name = "-d", aliases = "--delay", description = "delay between host to host trace display")
- @Completion(PlaceholderCompleter.class)
- private long delay = 0;
-
- @Override
- protected void doExecute() {
- TroubleshootService service = get(TroubleshootService.class);
- if (!service.checkNibValidity()) {
- // if the NIB is found invalid, fill it with the current network states so that this command can proceed
- print(T3CliUtils.NIB_AUTOFILLED);
- TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
- cmd.doExecute();
- if (!service.checkNibValidity()) {
- // if the NIB is still invalid even after auto-filled snapshots, stop and warn
- print(T3CliUtils.NIB_TERMINATE);
- return;
- }
- } else {
- print(service.printNibSummary());
- }
-
- EtherType type = EtherType.valueOf(ethType.toUpperCase());
-
- print("Tracing between all %s hosts", ethType);
-
- if (!type.equals(EtherType.IPV4) && !type.equals(EtherType.IPV6)) {
- print("Command only support IPv4 or IPv6");
- } else {
- //Create the generator for the list of traces.
- Generator<Set<StaticPacketTrace>> generator = service.pingAllGenerator(type);
- Host previousHost = null;
- int totalTraces = 0;
- List<StaticPacketTrace> failedTraces = new ArrayList<>();
- boolean ipv4 = type.equals(EtherType.IPV4);
- while (generator.iterator().hasNext()) {
- Set<StaticPacketTrace> traces = generator.iterator().next();
- totalTraces++;
- for (StaticPacketTrace trace : traces) {
- //no verbosity is mininet style output
- if (!verbosity1 && !verbosity2) {
- if (trace.getEndpointHosts().isPresent()) {
- Host src = trace.getEndpointHosts().get().getLeft();
- if (previousHost == null || !previousHost.equals(src)) {
- print("%s", StringUtils.rightPad("", 125, '-'));
- previousHost = printSrc(trace, ipv4, src);
- }
- String host = getDstString(trace, ipv4, src);
- if (!trace.isSuccess()) {
- host = host + " " + trace.resultMessage();
- failedTraces.add(trace);
- }
- print("%s", host);
- }
- } else {
- print("%s", StringUtils.leftPad("", 125, '-'));
-
- if (trace.getInitialPacket() != null) {
- if (verbosity1) {
- printResultOnly(trace, ipv4);
- } else if (verbosity2) {
- printVerbose(trace);
- }
- } else {
- if (trace.getEndpointHosts().isPresent()) {
- Host source = trace.getEndpointHosts().get().getLeft();
- Host destination = trace.getEndpointHosts().get().getRight();
- print("Source %s --> Destination %s", source.id(), destination.id());
- }
- print("Error in obtaining trace: %s", trace.resultMessage());
- }
- }
- }
- try {
- sleep(delay);
- } catch (InterruptedException e) {
- log.debug("interrupted while sleep");
- }
- }
- print("%s", StringUtils.rightPad("", 125, '-'));
- print("Failed Traces: %s", failedTraces.size());
- print("%s", StringUtils.rightPad("", 125, '-'));
- failedTraces.forEach(t -> {
- if (t.getEndpointHosts().isPresent()) {
- printSrc(t, ipv4, t.getEndpointHosts().get().getLeft());
- String dst = getDstString(t, ipv4, t.getEndpointHosts().get().getRight());
- dst = dst + " " + t.resultMessage();
- print("%s", dst);
- print("%s", StringUtils.rightPad("", 125, '-'));
- }
- });
- print("Summary");
- print("Total Traces %s, errors %s", totalTraces, failedTraces.size());
- }
- }
-
- private String getDstString(StaticPacketTrace trace, boolean ipv4, Host src) {
- String host;
- IpAddress ipAddress = getIpAddress(trace, ipv4, src, false);
- if (ipAddress == null) {
- host = String.format(" %s %s", trace.getEndpointHosts().get().getRight().id(),
- trace.isSuccess());
- } else {
- host = String.format(" %s (%s) %s",
- trace.getEndpointHosts().get().getRight().id(), ipAddress,
- trace.isSuccess());
- }
- return host;
- }
-
- private Host printSrc(StaticPacketTrace trace, boolean ipv4, Host src) {
- Host previousHost;
- IpAddress ipAddress = getIpAddress(trace, ipv4, src, true);
- if (ipAddress == null) {
- print("%s", src.id() + " -->");
- } else {
- print("%s (%s) -->", src.id(), ipAddress);
- }
- previousHost = src;
- return previousHost;
- }
-
- private IpAddress getIpAddress(StaticPacketTrace trace, boolean ipv4, Host host, boolean src) {
- IpAddress ipAddress;
- if (ipv4) {
- Criterion.Type type = src ? Criterion.Type.IPV4_SRC : Criterion.Type.IPV4_DST;
- if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
- ipAddress = ((IPCriterion) trace.getInitialPacket()
- .getCriterion(type)).ip().address();
- } else {
- ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp4)
- .findAny().orElse(null);
- }
- } else {
- Criterion.Type type = src ? Criterion.Type.IPV6_SRC : Criterion.Type.IPV6_DST;
- if (trace.getInitialPacket() != null && trace.getInitialPacket().getCriterion(type) != null) {
- ipAddress = ((IPCriterion) trace.getInitialPacket()
- .getCriterion(type)).ip().address();
- } else {
- ipAddress = host.ipAddresses().stream().filter(IpAddress::isIp6)
- .findAny().orElse(null);
- }
- }
- return ipAddress;
- }
-
- private void printResultOnly(StaticPacketTrace trace, boolean ipv4) {
- if (trace.getEndpointHosts().isPresent()) {
- Host source = trace.getEndpointHosts().get().getLeft();
- Host destination = trace.getEndpointHosts().get().getRight();
- IpAddress srcIP;
- IpAddress dstIP;
- if (ipv4 && trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC) != null) {
- srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_SRC)).ip().address();
- dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST)).ip().address();
- print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
- } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC) != null) {
- srcIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_SRC)).ip().address();
- dstIP = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST)).ip().address();
- print("Source %s (%s) --> Destination %s (%s)", source.id(), srcIP, destination.id(), dstIP);
- } else {
- print("Source %s --> Destination %s", source.id(), destination.id());
- }
- print("%s", trace.resultMessage());
- } else {
- print("Can't gather host information from trace");
- print("%s", trace.resultMessage());
- }
- }
-
- private void printVerbose(StaticPacketTrace trace) {
- if (trace.getEndpointHosts().isPresent()) {
- Host source = trace.getEndpointHosts().get().getLeft();
- print("Source host %s", printHost(source));
- Host destination = trace.getEndpointHosts().get().getRight();
- print("Destination host %s", printHost(destination));
- }
- print("%s", trace.getInitialPacket());
- print("%s", T3CliUtils.printTrace(trace, false, false));
- }
-
- private String printHost(Host host) {
- return String.format(FMT_SHORT, host.id(), host.mac(),
- host.locations(),
- host.vlan(), host.ipAddresses());
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java
deleted file mode 100644
index 66f5749..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootSimpleTraceCommand.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.EthTypeCompleter;
-import org.onosproject.cli.net.HostIdCompleter;
-import org.onosproject.net.HostId;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-
-import java.util.Set;
-
-import static org.onlab.packet.EthType.EtherType;
-
-/**
- * Starts a Static Packet Trace for a given input and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot-simple",
- description = "Given two hosts troubleshoots flows and groups between them, in case of segment routing")
-public class TroubleshootSimpleTraceCommand extends AbstractShellCommand {
-
- // OSGi workaround to introduce package dependency
- HostIdCompleter completer;
- @Argument(index = 0, name = "one", description = "One host ID",
- required = true, multiValued = false)
- @Completion(HostIdCompleter.class)
- String srcHost = null;
-
- @Argument(index = 1, name = "two", description = "Another host ID",
- required = true, multiValued = false)
- @Completion(HostIdCompleter.class)
- String dstHost = null;
-
- @Option(name = "-v", aliases = "--verbose", description = "Outputs complete path")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity1 = false;
-
- @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs flows and groups for every device")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity2 = false;
-
- @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
- @Completion(EthTypeCompleter.class)
- String ethType = "ipv4";
-
- @Override
- protected void doExecute() {
- TroubleshootService service = get(TroubleshootService.class);
- if (!service.checkNibValidity()) {
- // if the NIB is found invalid, fill it with the current network states so that this command can proceed
- print(T3CliUtils.NIB_AUTOFILLED);
- TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
- cmd.doExecute();
- if (!service.checkNibValidity()) {
- // if the NIB is still invalid even after auto-filled snapshots, stop and warn
- print(T3CliUtils.NIB_TERMINATE);
- return;
- }
- } else {
- print(service.printNibSummary());
- }
-
- if (srcHost.equals(dstHost)) {
- print("Source and destination are same. Use different hosts");
- return;
- }
-
- EtherType type = EtherType.valueOf(ethType.toUpperCase());
-
- //Printing the traced hosts
- print("Tracing between: %s and %s", srcHost, dstHost);
-
- //Build the traces
- Set<StaticPacketTrace> traces = service.trace(HostId.hostId(srcHost), HostId.hostId(dstHost), type);
- traces.forEach(trace -> {
- if (trace.getInitialPacket() != null) {
- print("Tracing Packet: %s", trace.getInitialPacket());
- print("%s", T3CliUtils.printTrace(trace, verbosity1, verbosity2));
- } else {
- print("Cannot obtain trace between %s and %s", srcHost, dstHost);
- print("Reason: %s", trace.resultMessage());
- }
- });
-
-
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java
deleted file mode 100644
index db7d69f..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.cli;
-
-import com.google.common.base.Preconditions;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.TpPort;
-import org.onlab.packet.VlanId;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.cli.PlaceholderCompleter;
-import org.onosproject.cli.net.ConnectPointCompleter;
-import org.onosproject.cli.net.EthTypeCompleter;
-import org.onosproject.cli.net.IpProtocolCompleter;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-
-import static org.onlab.packet.EthType.EtherType;
-
-/**
- * Starts a Static Packet Trace for a given input and prints the result.
- */
-@Service
-@Command(scope = "onos", name = "t3-troubleshoot",
- description = "troubleshoots flows and groups between source and destination")
-public class TroubleshootTraceCommand extends AbstractShellCommand {
-
-
- private static final String FLOW_SHORT_FORMAT = " %s, bytes=%s, packets=%s, "
- + "table=%s, priority=%s, selector=%s, treatment=%s";
-
- private static final String GROUP_FORMAT =
- " id=0x%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s, referenceCount=%s";
- private static final String GROUP_BUCKET_FORMAT =
- " id=0x%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
-
- private static final String CONTROLLER = "CONTROLLER";
-
- @Option(name = "-v", aliases = "--verbose", description = "Outputs complete path")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity1 = false;
-
- @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs flows and groups for every device")
- @Completion(PlaceholderCompleter.class)
- private boolean verbosity2 = false;
-
- @Option(name = "-s", aliases = "--srcIp", description = "Source IP")
- @Completion(PlaceholderCompleter.class)
- String srcIp = null;
-
- @Option(name = "-sp", aliases = "--srcPort", description = "Source Port", required = true)
- @Completion(ConnectPointCompleter.class)
- String srcPort = null;
-
- @Option(name = "-sm", aliases = "--srcMac", description = "Source MAC")
- @Completion(PlaceholderCompleter.class)
- String srcMac = null;
-
- @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
- @Completion(EthTypeCompleter.class)
- String ethType = "ipv4";
-
- @Option(name = "-stp", aliases = "--srcTcpPort", description = "Source TCP Port")
- @Completion(PlaceholderCompleter.class)
- String srcTcpPort = null;
-
- @Option(name = "-d", aliases = "--dstIp", description = "Destination IP")
- @Completion(PlaceholderCompleter.class)
- String dstIp = null;
-
- @Option(name = "-dm", aliases = "--dstMac", description = "Destination MAC")
- @Completion(PlaceholderCompleter.class)
- String dstMac = null;
-
- @Option(name = "-dtp", aliases = "--dstTcpPort", description = "destination TCP Port")
- @Completion(PlaceholderCompleter.class)
- String dstTcpPort = null;
-
- @Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
- @Completion(PlaceholderCompleter.class)
- String vlan = "None";
-
- @Option(name = "-ml", aliases = "--mplsLabel", description = "Mpls label of incoming packet")
- @Completion(PlaceholderCompleter.class)
- String mplsLabel = null;
-
- @Option(name = "-mb", aliases = "--mplsBos", description = "MPLS BOS")
- @Completion(PlaceholderCompleter.class)
- String mplsBos = null;
-
- @Option(name = "-ipp", aliases = "--ipProto", description = "IP Proto")
- @Completion(IpProtocolCompleter.class)
- String ipProto = null;
-
- @Option(name = "-udps", aliases = "--udpSrc", description = "UDP Source")
- @Completion(PlaceholderCompleter.class)
- String udpSrc = null;
-
- @Option(name = "-udpd", aliases = "--udpDst", description = "UDP Destination")
- @Completion(PlaceholderCompleter.class)
- String udpDst = null;
-
- @Override
- protected void doExecute() {
- TroubleshootService service = get(TroubleshootService.class);
- if (!service.checkNibValidity()) {
- // if the NIB is found invalid, fill it with the current network states so that this command can proceed
- print(T3CliUtils.NIB_AUTOFILLED);
- TroubleshootLoadSnapshotCommand cmd = new TroubleshootLoadSnapshotCommand();
- cmd.doExecute();
- if (!service.checkNibValidity()) {
- // if the NIB is still invalid even after auto-filled snapshots, stop and warn
- print(T3CliUtils.NIB_TERMINATE);
- return;
- }
- } else {
- print(service.printNibSummary());
- }
-
- String[] cpInfo = srcPort.split("/");
- Preconditions.checkArgument(cpInfo.length == 2, "wrong format of source port");
- ConnectPoint cp;
- //Uses input port as a convenience to carry the Controller port, proper flood behaviour is handled in the
- // troubleshoot manager.
- if (cpInfo[1].equalsIgnoreCase(CONTROLLER)) {
- cp = new ConnectPoint(DeviceId.deviceId(cpInfo[0]), PortNumber.CONTROLLER);
- } else {
- cp = ConnectPoint.deviceConnectPoint(srcPort);
- }
-
- EtherType type = EtherType.valueOf(ethType.toUpperCase());
-
- //Input Port must be specified
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder()
- .matchInPort(cp.port());
-
- if (srcIp != null) {
- if (type.equals(EtherType.IPV6)) {
- selectorBuilder.matchIPv6Src(IpAddress.valueOf(srcIp).toIpPrefix());
- } else {
- selectorBuilder.matchIPSrc(IpAddress.valueOf(srcIp).toIpPrefix());
- }
- }
-
- if (srcMac != null) {
- selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMac));
- }
-
- //if EthType option is not specified using IPv4
- selectorBuilder.matchEthType(type.ethType().toShort());
-
- if (srcTcpPort != null) {
- selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpPort)));
- }
-
- if (dstIp != null) {
- if (type.equals(EtherType.IPV6)) {
- selectorBuilder.matchIPv6Dst(IpAddress.valueOf(dstIp).toIpPrefix());
- } else {
- selectorBuilder.matchIPDst(IpAddress.valueOf(dstIp).toIpPrefix());
- }
- }
-
- if (dstMac != null) {
- selectorBuilder.matchEthDst(MacAddress.valueOf(dstMac));
- }
- if (dstTcpPort != null) {
- selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpPort)));
- }
-
- //if vlan option is not specified using NONE
- selectorBuilder.matchVlanId(VlanId.vlanId(vlan));
-
- if (mplsLabel != null) {
- selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(Integer.parseInt(mplsLabel)));
- }
-
- if (mplsBos != null) {
- selectorBuilder.matchMplsBos(Boolean.valueOf(mplsBos));
- }
-
- if (ipProto != null) {
- selectorBuilder.matchIPProtocol(Byte.valueOf(ipProto));
- }
-
- if (udpSrc != null) {
- selectorBuilder.matchUdpSrc(TpPort.tpPort(Integer.parseInt(udpSrc)));
- }
-
- if (udpDst != null) {
- selectorBuilder.matchUdpDst(TpPort.tpPort(Integer.parseInt(udpDst)));
- }
-
-
- TrafficSelector packet = selectorBuilder.build();
-
- //Printing the created packet
- print("Tracing packet: %s", packet.criteria());
-
- //Build the trace
- StaticPacketTrace trace = service.trace(packet, cp);
-
- print("%s", T3CliUtils.printTrace(trace, verbosity1, verbosity2));
-
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/cli/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/cli/package-info.java
deleted file mode 100644
index b956df2..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/cli/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics CLI.
- */
-package org.onosproject.t3.cli;
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Generator.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/Generator.java
deleted file mode 100644
index 82ad628..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Generator.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.impl;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Generator class that yields instances of T type objects as soon as they are ready.
- *
- * @param <T> type of the object.
- */
-public abstract class Generator<T> implements Iterable<T> {
-
- private class Condition {
- private boolean isSet;
-
- synchronized void set() {
- isSet = true;
- notifyAll();
- }
-
- synchronized void await() throws InterruptedException {
- try {
-
- if (isSet) {
- return;
- }
-
- while (!isSet) {
- wait();
- }
- } finally {
- isSet = false;
- }
- }
- }
-
- private static ThreadGroup threadGroup;
-
- private Thread producer;
- private boolean hasFinished;
- private final Condition itemAvailableOrHasFinished = new Condition();
- private final Condition itemRequested = new Condition();
- private T nextItem;
- private boolean nextItemAvailable;
- private RuntimeException exceptionRaisedByProducer;
-
- @Override
- public Iterator<T> iterator() {
- return new Iterator<T>() {
- @Override
- public boolean hasNext() {
- return waitForNext();
- }
-
- @Override
- public T next() {
- if (!waitForNext()) {
- throw new NoSuchElementException();
- }
- nextItemAvailable = false;
- return nextItem;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- private boolean waitForNext() {
- if (nextItemAvailable) {
- return true;
- }
- if (hasFinished) {
- return false;
- }
- if (producer == null) {
- startProducer();
- }
- itemRequested.set();
- try {
- itemAvailableOrHasFinished.await();
- } catch (InterruptedException e) {
- hasFinished = true;
- producer.interrupt();
- try {
- producer.join();
- } catch (InterruptedException e1) {
- // Interrupting the broken thread
- Thread.currentThread().interrupt();
- throw new IllegalStateException(e1);
- }
- }
- if (exceptionRaisedByProducer != null) {
- throw exceptionRaisedByProducer;
- }
- return !hasFinished;
- }
- };
- }
-
- protected abstract void run() throws InterruptedException;
-
- void yield(T element) throws InterruptedException {
- nextItem = element;
- nextItemAvailable = true;
- itemAvailableOrHasFinished.set();
- itemRequested.await();
- }
-
- private void startProducer() {
- assert producer == null;
- synchronized (this) {
- if (threadGroup == null) {
- threadGroup = new ThreadGroup("onos-t3-generator");
- }
- }
- producer = new Thread(threadGroup, () -> {
- try {
- itemRequested.await();
- Generator.this.run();
- } catch (InterruptedException e) {
- // Remaining steps in run() will shut down thread.
- } catch (RuntimeException e) {
- exceptionRaisedByProducer = e;
- }
- hasFinished = true;
- itemAvailableOrHasFinished.set();
- });
- producer.setDaemon(true);
- producer.start();
- }
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/McastGenerator.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/McastGenerator.java
deleted file mode 100644
index 7520843..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/McastGenerator.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.impl;
-
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.mcast.api.McastRouteData;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.slf4j.Logger;
-
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Implementation of the generator class that yields a set of Packet Traces.
- */
-public class McastGenerator extends Generator<Set<StaticPacketTrace>> {
-
- private static final Logger log = getLogger(McastGenerator.class);
- protected static final MacAddress IPV4_ADDRESS = MacAddress.valueOf("01:00:5E:00:00:00");
- protected static final MacAddress IPV6_ADDRESS = MacAddress.valueOf("33:33:00:00:00:00");
- private static final String NO_SINK = "There is no sink for this mcast route";
- private static final String GENERATOR_ERROR =
- "Generator for mcast route trace has benn interrupted. The trace result may be incomplete.";
-
- private final MulticastRouteNib mcastRouteNib;
- private final TroubleshootManager manager;
- private final VlanId vlanId;
-
- /**
- * Creates a generator for obtaining traces of all configured multicast routes.
- *
- * @param mcastRouteNib the multicast route NIB
- * @param manager the troubleshoot manager issuing the request.
- * @param vlanId the multicast configured VlanId.
- */
- McastGenerator(MulticastRouteNib mcastRouteNib, TroubleshootManager manager, VlanId vlanId) {
- this.mcastRouteNib = mcastRouteNib;
- this.manager = manager;
- this.vlanId = vlanId;
- }
-
- @Override
- protected void run() {
- mcastRouteNib.getRoutes().forEach(route -> {
- McastRouteData routeData = mcastRouteNib.routeData(route);
- IpAddress group = route.group();
- routeData.sources().forEach((host, sources) -> {
- sources.forEach(source -> {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
- .matchVlanId(vlanId)
- .matchInPort(source.port());
- if (group.isIp4()) {
- selector.matchEthDst(IPV4_ADDRESS)
- .matchIPDst(group.toIpPrefix())
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort());
- } else {
- selector.matchEthDst(IPV6_ADDRESS)
- .matchIPv6Dst(group.toIpPrefix())
- .matchEthType(EthType.EtherType.IPV6.ethType().toShort());
- }
-
- StaticPacketTrace trace;
- // check this mcast route has no sink
- if (routeData.allSinks().size() == 0) {
- trace = new StaticPacketTrace(selector.build(), source);
- trace.addResultMessage(NO_SINK);
- // tracing mcast route with no sink is not a failure
- trace.setSuccess(true);
- } else {
- trace = manager.trace(selector.build(), source);
- }
- try {
- yield(ImmutableSet.of(trace));
- } catch (InterruptedException e) {
- log.warn("Interrupted generator", e.getMessage());
- log.debug("exception", e);
- trace.setSuccess(false);
- trace.addResultMessage(GENERATOR_ERROR);
- }
- });
- });
- });
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/PingAllGenerator.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/PingAllGenerator.java
deleted file mode 100644
index e935fad..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/PingAllGenerator.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.impl;
-
-import com.google.common.collect.Sets;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.slf4j.Logger;
-
-import java.util.List;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Implementation of the generator class that yields a set of Packet Traces.
- */
-public class PingAllGenerator extends Generator<Set<StaticPacketTrace>> {
-
- private static final Logger log = getLogger(PingAllGenerator.class);
-
- private final EthType.EtherType etherType;
- private final HostNib hostNib;
- private final TroubleshootManager manager;
-
- /**
- * Creates a generator for obtaining traces of pings between all the hosts in the network.
- *
- * @param etherType the type of traffic we are tracing.
- * @param hostNib the host NIB
- * @param manager the troubleshoot manager issuing the request.
- */
- PingAllGenerator(EthType.EtherType etherType, HostNib hostNib, TroubleshootManager manager) {
- this.etherType = etherType;
- this.hostNib = hostNib;
- this.manager = manager;
- }
-
- @Override
- protected void run() throws InterruptedException {
- hostNib.getHosts().forEach(host -> {
- List<IpAddress> ipAddresses = manager.getIpAddresses(host, etherType, false);
- if (ipAddresses.size() > 0) {
- //check if the host has only local IPs of that ETH type
- boolean onlyLocalSrc = ipAddresses.size() == 1 && ipAddresses.get(0).isLinkLocal();
- hostNib.getHosts().forEach(hostToPing -> {
- List<IpAddress> ipAddressesToPing = manager.getIpAddresses(hostToPing, etherType, false);
- //check if the other host has only local IPs of that ETH type
- boolean onlyLocalDst = ipAddressesToPing.size() == 1 && ipAddressesToPing.get(0).isLinkLocal();
- boolean sameLocation = Sets.intersection(host.locations(), hostToPing.locations()).size() > 0;
- //Trace is done only if they are both local and under the same location
- // or not local and if they are not the same host.
- if (((sameLocation && onlyLocalDst && onlyLocalSrc) ||
- (!onlyLocalSrc && !onlyLocalDst && ipAddressesToPing.size() > 0))
- && !host.equals(hostToPing)) {
- try {
- yield(manager.trace(host.id(), hostToPing.id(), etherType));
- } catch (InterruptedException e) {
- log.warn("Interrupted generator", e.getMessage());
- log.debug("exception", e);
- }
- }
- });
- }
- });
-
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Subnet.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/Subnet.java
deleted file mode 100644
index ac5a741..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/Subnet.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.impl;
-
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * Utility class to test if an Ip is in a given subnet.
- */
-public class Subnet {
- private final int bytesSubnetCount;
- private final BigInteger bigMask;
- private final BigInteger bigSubnetMasked;
-
- /**
- * Constructor for use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57".
- * @param subnetAddress the address
- * @param bits the mask
- */
- public Subnet(InetAddress subnetAddress, int bits) {
- bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
- bigMask = BigInteger.valueOf(-1).shiftLeft(bytesSubnetCount * 8 - bits); // mask = -1 << 32 - bits
- bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(bigMask);
- }
-
- /**
- * Constructor for use via format "192.168.0.0/255.255.255.0" or single address.
- * @param subnetAddress the address
- * @param mask the mask
- */
- public Subnet(InetAddress subnetAddress, InetAddress mask) {
- bytesSubnetCount = subnetAddress.getAddress().length;
- // no mask given case is handled here.
- bigMask = null == mask ? BigInteger.valueOf(-1) : new BigInteger(mask.getAddress());
- bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(bigMask);
- }
-
- /**
- * Subnet factory method.
- *
- * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
- * or single address or "2001:db8:85a3:880:0:0:0:0/57"
- * @return a new instance
- * @throws UnknownHostException thrown if unsupported subnet mask.
- */
- public static Subnet createInstance(String subnetMask)
- throws UnknownHostException {
- final String[] stringArr = subnetMask.split("/");
- if (2 > stringArr.length) {
- return new Subnet(InetAddress.getByName(stringArr[0]), (InetAddress) null);
- } else if (stringArr[1].contains(".") || stringArr[1].contains(":")) {
- return new Subnet(InetAddress.getByName(stringArr[0]), InetAddress.getByName(stringArr[1]));
- } else {
- return new Subnet(InetAddress.getByName(stringArr[0]), Integer.parseInt(stringArr[1]));
- }
- }
-
- /**
- * Tests if the address is in the given subnet.
- * @param address the address to test.
- * @return true if inside the subnet
- */
- public boolean isInSubnet(InetAddress address) {
- byte[] bytesAddress = address.getAddress();
- if (this.bytesSubnetCount != bytesAddress.length) {
- return false;
- }
- BigInteger bigAddress = new BigInteger(bytesAddress);
- return bigAddress.and(this.bigMask).equals(this.bigSubnetMasked);
- }
-
- @Override
- public final boolean equals(Object obj) {
- if (!(obj instanceof Subnet)) {
- return false;
- }
- final Subnet other = (Subnet) obj;
- return bigSubnetMasked.equals(other.bigSubnetMasked) &&
- bigMask.equals(other.bigMask) &&
- bytesSubnetCount == other.bytesSubnetCount;
- }
-
- @Override
- public final int hashCode() {
- return bytesSubnetCount;
- }
-
- @Override
- public String toString() {
- final StringBuilder buf = new StringBuilder();
- bigInteger2IpString(buf, bigSubnetMasked, bytesSubnetCount);
- buf.append('/');
- bigInteger2IpString(buf, bigMask, bytesSubnetCount);
- return buf.toString();
- }
-
- private void bigInteger2IpString(StringBuilder buf, BigInteger bigInteger, int displayBytes) {
- boolean isIPv4 = 4 == displayBytes;
- byte[] bytes = bigInteger.toByteArray();
- int diffLen = displayBytes - bytes.length;
- byte fillByte = 0 > (int) bytes[0] ? (byte) 0xFF : (byte) 0x00;
-
- int integer;
- for (int i = 0; i < displayBytes; i++) {
- if (0 < i && !isIPv4 && i % 2 == 0) {
- buf.append(':');
- } else if (0 < i && isIPv4) {
- buf.append('.');
- }
- integer = 0xFF & (i < diffLen ? fillByte : bytes[i - diffLen]);
- if (!isIPv4 && 0x10 > integer) {
- buf.append('0');
- }
- buf.append(isIPv4 ? integer : Integer.toHexString(integer));
- }
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
deleted file mode 100644
index bc04136..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.impl;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.ConfigException;
-import org.onosproject.net.config.basics.InterfaceConfig;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.IndexTableId;
-import org.onosproject.net.flow.TableId;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intf.Interface;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.GroupsInDevice;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.MulticastRouteNib;
-import org.onosproject.t3.api.NetworkConfigNib;
-import org.onosproject.t3.api.NibProfile;
-import org.onosproject.t3.api.RouteNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.osgi.service.component.annotations.Component;
-import org.slf4j.Logger;
-
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import static org.onlab.packet.EthType.EtherType;
-import static org.onosproject.net.flow.TrafficSelector.Builder;
-import static org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
-import static org.onosproject.t3.impl.TroubleshootUtils.compareMac;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Manager to troubleshoot packets inside the network.
- * Given a representation of a packet follows it's path in the network according to the existing flows and groups in
- * the devices.
- */
-@Component(immediate = true, service = TroubleshootService.class)
-public class TroubleshootManager implements TroubleshootService {
-
- private static final Logger log = getLogger(TroubleshootManager.class);
-
- static final String PACKET_TO_CONTROLLER = "Packet goes to the controller";
-
- // uses a snapshot (cache) of NIBs instead of interacting with ONOS core in runtime
- protected FlowNib flowNib = FlowNib.getInstance();
- protected GroupNib groupNib = GroupNib.getInstance();
- protected LinkNib linkNib = LinkNib.getInstance();
- protected HostNib hostNib = HostNib.getInstance();
- protected DeviceNib deviceNib = DeviceNib.getInstance();
- protected DriverNib driverNib = DriverNib.getInstance();
- protected MastershipNib mastershipNib = MastershipNib.getInstance();
- protected EdgePortNib edgePortNib = EdgePortNib.getInstance();
- protected RouteNib routeNib = RouteNib.getInstance();
- protected NetworkConfigNib networkConfigNib = NetworkConfigNib.getInstance();
- protected MulticastRouteNib mcastRouteNib = MulticastRouteNib.getInstance();
-
- @Override
- public boolean checkNibValidity() {
- return Stream.of(flowNib, groupNib, linkNib, hostNib, deviceNib, driverNib,
- mastershipNib, edgePortNib, routeNib, networkConfigNib, mcastRouteNib)
- .allMatch(nib -> nib != null && nib.isValid());
- }
-
- @Override
- public String printNibSummary() {
- StringBuilder summary = new StringBuilder().append("*** Current NIB in valid: ***\n");
- Stream.of(flowNib, groupNib, linkNib, hostNib, deviceNib, driverNib,
- mastershipNib, edgePortNib, routeNib, networkConfigNib, mcastRouteNib)
- .forEach(nib -> {
- NibProfile profile = nib.getProfile();
- summary.append(String.format(
- nib.getClass().getName() + " created %s from %s\n",
- profile.date(), profile.sourceType()));
- });
-
- return summary.append(StringUtils.rightPad("", 125, '-')).toString();
- }
-
- @Override
- public List<StaticPacketTrace> pingAll(EtherType type) {
- ImmutableList.Builder<StaticPacketTrace> tracesBuilder = ImmutableList.builder();
- hostNib.getHosts().forEach(host -> {
- List<IpAddress> ipAddresses = getIpAddresses(host, type, false);
- if (ipAddresses.size() > 0) {
- //check if the host has only local IPs of that ETH type
- boolean onlyLocalSrc = ipAddresses.size() == 1 && ipAddresses.get(0).isLinkLocal();
- hostNib.getHosts().forEach(hostToPing -> {
- List<IpAddress> ipAddressesToPing = getIpAddresses(hostToPing, type, false);
- //check if the other host has only local IPs of that ETH type
- boolean onlyLocalDst = ipAddressesToPing.size() == 1 && ipAddressesToPing.get(0).isLinkLocal();
- boolean sameLocation = Sets.intersection(host.locations(), hostToPing.locations()).size() > 0;
- //Trace is done only if they are both local and under the same location
- // or not local and if they are not the same host.
- if (((sameLocation && onlyLocalDst && onlyLocalSrc) ||
- (!onlyLocalSrc && !onlyLocalDst && ipAddressesToPing.size() > 0))
- && !host.equals(hostToPing)) {
- tracesBuilder.addAll(trace(host.id(), hostToPing.id(), type));
- }
- });
- }
- });
- return tracesBuilder.build();
- }
-
- @Override
- public Generator<Set<StaticPacketTrace>> pingAllGenerator(EtherType type) {
- return new PingAllGenerator(type, hostNib, this);
- }
-
- @Override
- public Generator<Set<StaticPacketTrace>> traceMcast(VlanId vlanId) {
- return new McastGenerator(mcastRouteNib, this, vlanId);
- }
-
- @Override
- public Set<StaticPacketTrace> trace(HostId sourceHost, HostId destinationHost, EtherType etherType) {
- Host source = hostNib.getHost(sourceHost);
- Host destination = hostNib.getHost(destinationHost);
-
- //Temporary trace to fail in case we don't have enough information or what is provided is incoherent
- StaticPacketTrace failTrace = new StaticPacketTrace(null, null, Pair.of(source, destination));
-
- if (source == null) {
- failTrace.addResultMessage("Source Host " + sourceHost + " does not exist");
- failTrace.setSuccess(false);
-
- return ImmutableSet.of(failTrace);
- }
-
- if (destination == null) {
- failTrace.addResultMessage("Destination Host " + destinationHost + " does not exist");
- failTrace.setSuccess(false);
- return ImmutableSet.of(failTrace);
- }
-
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder()
- .matchEthType(etherType.ethType().toShort())
- .matchEthDst(source.mac())
- .matchVlanId(source.vlan());
-
-
- try {
- ImmutableSet.Builder<StaticPacketTrace> traces = ImmutableSet.builder();
- //if the location deviceId is the same, the two hosts are under same subnet and vlan on the interface
- // we are under same leaf so it's L2 Unicast.
- if (areBridged(source, destination)) {
- selectorBuilder.matchEthDst(destination.mac());
- source.locations().forEach(hostLocation -> {
- selectorBuilder.matchInPort(hostLocation.port());
- StaticPacketTrace trace = trace(selectorBuilder.build(), hostLocation);
- trace.addEndpointHosts(Pair.of(source, destination));
- traces.add(trace);
- });
- //The destination host is not dual homed, if it is the other path might be done through routing.
- if (destination.locations().size() == 1) {
- return traces.build();
- }
- }
- //handle the IPs for src and dst in case of L3
- if (etherType.equals(EtherType.IPV4) || etherType.equals(EtherType.IPV6)) {
-
- //Match on the source IP
- if (!matchIP(source, failTrace, selectorBuilder, etherType, true)) {
- return ImmutableSet.of(failTrace);
- }
-
- //Match on destination IP
- if (!matchIP(destination, failTrace, selectorBuilder, etherType, false)) {
- return ImmutableSet.of(failTrace);
- }
-
- } else {
- failTrace.addResultMessage("Host based trace supports only IPv4 or IPv6 as EtherType, " +
- "please use packet based");
- failTrace.setSuccess(false);
- return ImmutableSet.of(failTrace);
- }
-
- //l3 unicast, we get the dst mac of the leaf the source is connected to from netcfg
- SegmentRoutingDeviceConfig segmentRoutingConfig = networkConfigNib.getConfig(source.location()
- .deviceId(), SegmentRoutingDeviceConfig.class);
- if (segmentRoutingConfig != null) {
- selectorBuilder.matchEthDst(segmentRoutingConfig.routerMac());
- } else {
- failTrace.addResultMessage("Can't get " + source.location().deviceId() +
- " router MAC from segment routing config can't perform L3 tracing.");
- failTrace.setSuccess(false);
- }
- source.locations().forEach(hostLocation -> {
- selectorBuilder.matchInPort(hostLocation.port());
- StaticPacketTrace trace = trace(selectorBuilder.build(), hostLocation);
- trace.addEndpointHosts(Pair.of(source, destination));
- traces.add(trace);
- });
- return traces.build();
-
- } catch (ConfigException e) {
- failTrace.addResultMessage("Can't get config " + e.getMessage());
- return ImmutableSet.of(failTrace);
- }
- }
-
- /**
- * Matches src and dst IPs based on host information.
- *
- * @param host the host
- * @param failTrace the trace to use in case of failure
- * @param selectorBuilder the packet we are building to trace
- * @param etherType the traffic type
- * @param src is this src host or dst host
- * @return true if properly matched
- */
- private boolean matchIP(Host host, StaticPacketTrace failTrace, Builder selectorBuilder,
- EtherType etherType, boolean src) {
- List<IpAddress> ips = getIpAddresses(host, etherType, true);
-
- if (ips.size() > 0) {
- if (etherType.equals(EtherType.IPV4)) {
- if (src) {
- selectorBuilder.matchIPSrc(ips.get(0).toIpPrefix());
- } else {
- selectorBuilder.matchIPDst(ips.get(0).toIpPrefix());
- }
- } else if (etherType.equals(EtherType.IPV6)) {
- if (src) {
- selectorBuilder.matchIPv6Src(ips.get(0).toIpPrefix());
- } else {
- selectorBuilder.matchIPv6Dst(ips.get(0).toIpPrefix());
- }
- }
- } else {
- failTrace.addResultMessage("Host " + host + " has no " + etherType + " address");
- failTrace.setSuccess(false);
- return false;
- }
- return true;
- }
-
- List<IpAddress> getIpAddresses(Host host, EtherType etherType, boolean checklocal) {
- return host.ipAddresses().stream().filter(ipAddress -> {
- boolean correctIp = false;
- if (etherType.equals(EtherType.IPV4)) {
- correctIp = ipAddress.isIp4();
- } else if (etherType.equals(EtherType.IPV6)) {
- correctIp = ipAddress.isIp6();
- }
- if (checklocal) {
- correctIp = correctIp && !ipAddress.isLinkLocal();
- }
- return correctIp;
- }).collect(Collectors.toList());
- }
-
- /**
- * Checks that two hosts are bridged (L2Unicast).
- *
- * @param source the source host
- * @param destination the destination host
- * @return true if bridged.
- * @throws ConfigException if config can't be properly retrieved
- */
- private boolean areBridged(Host source, Host destination) throws ConfigException {
-
- //If the locations is not the same we don't even check vlan or subnets
- if (Collections.disjoint(source.locations(), destination.locations())) {
- return false;
- }
-
- if (!source.vlan().equals(VlanId.NONE) && !destination.vlan().equals(VlanId.NONE)
- && !source.vlan().equals(destination.vlan())) {
- return false;
- }
-
- InterfaceConfig interfaceCfgH1 = networkConfigNib.getConfig(source.location(), InterfaceConfig.class);
- InterfaceConfig interfaceCfgH2 = networkConfigNib.getConfig(destination.location(), InterfaceConfig.class);
- if (interfaceCfgH1 != null && interfaceCfgH2 != null) {
-
- //following can be optimized but for clarity is left as is
- Interface intfH1 = interfaceCfgH1.getInterfaces().stream().findFirst().get();
- Interface intfH2 = interfaceCfgH2.getInterfaces().stream().findFirst().get();
-
- if (source.vlan().equals(VlanId.NONE) && !destination.vlan().equals(VlanId.NONE)) {
- return intfH1.vlanUntagged().equals(destination.vlan()) ||
- intfH1.vlanNative().equals(destination.vlan());
- }
-
- if (!source.vlan().equals(VlanId.NONE) && destination.vlan().equals(VlanId.NONE)) {
- return intfH2.vlanUntagged().equals(source.vlan()) ||
- intfH2.vlanNative().equals(source.vlan());
- }
-
- if (!intfH1.vlanNative().equals(intfH2.vlanNative())) {
- return false;
- }
-
- if (!intfH1.vlanUntagged().equals(intfH2.vlanUntagged())) {
- return false;
- }
-
- List<InterfaceIpAddress> intersection = new ArrayList<>(intfH1.ipAddressesList());
- intersection.retainAll(intfH2.ipAddressesList());
- if (intersection.size() == 0) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public StaticPacketTrace trace(TrafficSelector packet, ConnectPoint in) {
- log.info("Tracing packet {} coming in through {}", packet, in);
- //device must exist in ONOS
- Preconditions.checkNotNull(deviceNib.getDevice(in.deviceId()),
- "Device " + in.deviceId() + " must exist in ONOS");
-
- StaticPacketTrace trace = new StaticPacketTrace(packet, in);
- boolean isDualHomed = getHosts(trace).stream().anyMatch(host -> host.locations().size() > 1);
- //FIXME this can be done recursively
- //Building output connect Points
- List<ConnectPoint> path = new ArrayList<>();
- trace = traceInDevice(trace, packet, in, isDualHomed, path);
- trace = getTrace(path, in, trace, isDualHomed);
- return trace;
- }
-
- @Override
- public List<Set<StaticPacketTrace>> getMulitcastTrace(VlanId vlanId) {
- Generator<Set<StaticPacketTrace>> gen = new McastGenerator(mcastRouteNib, this, vlanId);
- List<Set<StaticPacketTrace>> multicastTraceList =
- StreamSupport.stream(gen.spliterator(), false).collect(Collectors.toList());
- return multicastTraceList;
- }
-
- /**
- * Computes a trace for a give packet that start in the network at the given connect point.
- *
- * @param completePath the path traversed by the packet
- * @param in the input connect point
- * @param trace the trace to build
- * @param isDualHomed true if the trace we are doing starts or ends in a dual homed host
- * @return the build trace for that packet.
- */
- private StaticPacketTrace getTrace(List<ConnectPoint> completePath, ConnectPoint in, StaticPacketTrace trace,
- boolean isDualHomed) {
-
- log.debug("------------------------------------------------------------");
-
- //if the trace already contains the input connect point there is a loop
- if (pathContainsDevice(completePath, in.deviceId())) {
- trace.addResultMessage("Loop encountered in device " + in.deviceId());
- completePath.add(in);
- trace.addCompletePath(completePath);
- trace.setSuccess(false);
- return trace;
- }
-
- //let's add the input connect point
- completePath.add(in);
-
- //If the trace has no outputs for the given input we stop here
- if (trace.getGroupOuputs(in.deviceId()) == null) {
- computePath(completePath, trace, null);
- trace.addResultMessage("No output out of device " + in.deviceId() + ". Packet is dropped");
- trace.setSuccess(false);
- return trace;
- }
-
- //If the trace has outputs we analyze them all
- for (GroupsInDevice outputPath : trace.getGroupOuputs(in.deviceId())) {
-
- ConnectPoint cp = outputPath.getOutput();
- log.debug("Connect point in {}", in);
- log.debug("Output path {}", cp);
- log.debug("{}", outputPath.getFinalPacket());
-
- //Hosts for the the given output
- Set<Host> hostsList = hostNib.getConnectedHosts(cp);
- //Hosts queried from the original ip or mac
- Set<Host> hosts = getHosts(trace);
-
- if (in.equals(cp) && trace.getInitialPacket().getCriterion(Criterion.Type.VLAN_VID) != null &&
- outputPath.getFinalPacket().getCriterion(Criterion.Type.VLAN_VID) != null
- && ((VlanIdCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.VLAN_VID)).vlanId()
- .equals(((VlanIdCriterion) outputPath.getFinalPacket().getCriterion(Criterion.Type.VLAN_VID))
- .vlanId())) {
- if (trace.getGroupOuputs(in.deviceId()).size() == 1 &&
- computePath(completePath, trace, outputPath.getOutput())) {
- trace.addResultMessage("Connect point out " + cp + " is same as initial input " + in);
- trace.setSuccess(false);
- }
- } else if (!Collections.disjoint(hostsList, hosts)) {
- //If the two host collections contain the same item it means we reached the proper output
- log.debug("Stopping here because host is expected destination {}, reached through", completePath);
- if (computePath(completePath, trace, outputPath.getOutput())) {
- trace.addResultMessage("Reached required destination Host " + cp);
- trace.setSuccess(true);
- }
- break;
- } else if (cp.port().equals(PortNumber.CONTROLLER)) {
-
- //Getting the master when the packet gets sent as packet in
- NodeId master = mastershipNib.getMasterFor(cp.deviceId());
- // TODO if we don't need to print master node id, exclude mastership NIB which is used only here
- trace.addResultMessage(PACKET_TO_CONTROLLER + " " + master.id());
- computePath(completePath, trace, outputPath.getOutput());
- handleVlanToController(outputPath, trace);
-
- } else if (linkNib.getEgressLinks(cp).size() > 0) {
-
- //TODO this can be optimized if we use a Tree structure for paths.
- //if we already have outputs let's check if the one we are considering starts from one of the devices
- // in any of the ones we have.
- if (trace.getCompletePaths().size() > 0) {
- ConnectPoint inputForOutput = null;
- List<ConnectPoint> previousPath = new ArrayList<>();
- for (List<ConnectPoint> path : trace.getCompletePaths()) {
- for (ConnectPoint connect : path) {
- //if the path already contains the input for the output we've found we use it
- if (connect.equals(in)) {
- inputForOutput = connect;
- previousPath = path;
- break;
- }
- }
- }
-
- //we use the pre-existing path up to the point we fork to a new output
- if (inputForOutput != null && completePath.contains(inputForOutput)) {
- List<ConnectPoint> temp = new ArrayList<>(previousPath);
- temp = temp.subList(0, previousPath.indexOf(inputForOutput) + 1);
- if (completePath.containsAll(temp)) {
- completePath = temp;
- }
- }
- }
-
- //let's add the ouput for the input
- completePath.add(cp);
- //let's compute the links for the given output
- Set<Link> links = linkNib.getEgressLinks(cp);
- log.debug("Egress Links {}", links);
- //For each link we trace the corresponding device
- for (Link link : links) {
- ConnectPoint dst = link.dst();
- //change in-port to the dst link in port
- Builder updatedPacket = DefaultTrafficSelector.builder();
- outputPath.getFinalPacket().criteria().forEach(updatedPacket::add);
- updatedPacket.add(Criteria.matchInPort(dst.port()));
- log.debug("DST Connect Point {}", dst);
- //build the elements for that device
- traceInDevice(trace, updatedPacket.build(), dst, isDualHomed, completePath);
- //continue the trace along the path
- getTrace(completePath, dst, trace, isDualHomed);
- }
- } else if (edgePortNib.isEdgePoint(outputPath.getOutput()) &&
- trace.getInitialPacket().getCriterion(Criterion.Type.ETH_DST) != null &&
- ((EthCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.ETH_DST))
- .mac().isMulticast()) {
- trace.addResultMessage("Packet is multicast and reached output " + outputPath.getOutput() +
- " which is enabled and is edge port");
- trace.setSuccess(true);
- computePath(completePath, trace, outputPath.getOutput());
- if (!hasOtherOutput(in.deviceId(), trace, outputPath.getOutput())) {
- return trace;
- }
- } else if (deviceNib.getPort(cp) != null && deviceNib.getPort(cp).isEnabled()) {
- EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.ETH_TYPE);
- //We treat as correct output only if it's not LLDP or BDDP
- if (!(ethTypeCriterion.ethType().equals(EtherType.LLDP.ethType())
- && !ethTypeCriterion.ethType().equals(EtherType.BDDP.ethType()))) {
- if (computePath(completePath, trace, outputPath.getOutput())) {
- if (hostsList.isEmpty()) {
- trace.addResultMessage("Packet is " + ((EthTypeCriterion) outputPath.getFinalPacket()
- .getCriterion(Criterion.Type.ETH_TYPE)).ethType() + " and reached " +
- cp + " with no hosts connected ");
- } else {
- IpAddress ipAddress = null;
- if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST) != null) {
- ipAddress = ((IPCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV4_DST)).ip().address();
- } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST) != null) {
- ipAddress = ((IPCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV6_DST)).ip().address();
- }
- if (ipAddress != null) {
- IpAddress finalIpAddress = ipAddress;
- if (hostsList.stream().anyMatch(host -> host.ipAddresses().contains(finalIpAddress)) ||
- hostNib.getHostsByIp(finalIpAddress).isEmpty()) {
- trace.addResultMessage("Packet is " +
- ((EthTypeCriterion) outputPath.getFinalPacket()
- .getCriterion(Criterion.Type.ETH_TYPE)).ethType() +
- " and reached " + cp + " with hosts " + hostsList);
- } else {
- trace.addResultMessage("Wrong output " + cp + " for required destination ip " +
- ipAddress);
- trace.setSuccess(false);
- }
- } else {
- trace.addResultMessage("Packet is " + ((EthTypeCriterion) outputPath.getFinalPacket()
- .getCriterion(Criterion.Type.ETH_TYPE)).ethType() + " and reached " +
- cp + " with hosts " + hostsList);
- }
- }
- trace.setSuccess(true);
- }
- }
-
- } else {
- computePath(completePath, trace, cp);
- trace.setSuccess(false);
- if (deviceNib.getPort(cp) == null) {
- //Port is not existent on device.
- log.warn("Port {} is not available on device.", cp);
- trace.addResultMessage("Port " + cp + "is not available on device. Packet is dropped");
- } else {
- //No links means that the packet gets dropped.
- log.warn("No links out of {}", cp);
- trace.addResultMessage("No links depart from " + cp + ". Packet is dropped");
- }
- }
- }
- return trace;
- }
-
-
- /**
- * If the initial packet comes tagged with a Vlan we output it with that to ONOS.
- * If ONOS applied a vlan we remove it.
- *
- * @param outputPath the output
- * @param trace the trace we are building
- */
-
- private void handleVlanToController(GroupsInDevice outputPath, StaticPacketTrace trace) {
-
- VlanIdCriterion initialVid = (VlanIdCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.VLAN_VID);
- VlanIdCriterion finalVid = (VlanIdCriterion) outputPath.getFinalPacket().getCriterion(Criterion.Type.VLAN_VID);
-
- if (initialVid != null && !initialVid.equals(finalVid) && initialVid.vlanId().equals(VlanId.NONE)) {
-
- Set<Criterion> finalCriteria = new HashSet<>(outputPath.getFinalPacket().criteria());
- //removing the final vlanId
- finalCriteria.remove(finalVid);
- Builder packetUpdated = DefaultTrafficSelector.builder();
- finalCriteria.forEach(packetUpdated::add);
- //Initial was none so we set it to that
- packetUpdated.add(Criteria.matchVlanId(VlanId.NONE));
- //Update final packet
- outputPath.setFinalPacket(packetUpdated.build());
- }
- }
-
- /**
- * Checks if the device has other outputs than the given connect point.
- *
- * @param inDeviceId the device
- * @param trace the trace we are building
- * @param cp an output connect point
- * @return true if the device has other outputs.
- */
- private boolean hasOtherOutput(DeviceId inDeviceId, StaticPacketTrace trace, ConnectPoint cp) {
- return trace.getGroupOuputs(inDeviceId).stream().filter(groupsInDevice -> {
- return !groupsInDevice.getOutput().equals(cp);
- }).count() > 0;
- }
-
- /**
- * Checks if the path contains the device.
- *
- * @param completePath the path
- * @param deviceId the device to check
- * @return true if the path contains the device
- */
- //TODO might prove costly, improvement: a class with both CPs and DeviceIds point.
- private boolean pathContainsDevice(List<ConnectPoint> completePath, DeviceId deviceId) {
- for (ConnectPoint cp : completePath) {
- if (cp.deviceId().equals(deviceId)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Gets the hosts for the given initial packet.
- *
- * @param trace the trace we are building
- * @return set of the hosts we are trying to reach
- */
- private Set<Host> getHosts(StaticPacketTrace trace) {
- IPCriterion ipv4Criterion = ((IPCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV4_DST));
- IPCriterion ipv6Criterion = ((IPCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV6_DST));
- Set<Host> hosts = new HashSet<>();
- if (ipv4Criterion != null) {
- hosts.addAll(hostNib.getHostsByIp(ipv4Criterion.ip().address()));
- }
- if (ipv6Criterion != null) {
- hosts.addAll(hostNib.getHostsByIp(ipv6Criterion.ip().address()));
- }
- EthCriterion ethCriterion = ((EthCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.ETH_DST));
- if (ethCriterion != null) {
- hosts.addAll(hostNib.getHostsByMac(ethCriterion.mac()));
- }
- return hosts;
- }
-
- /**
- * Computes the list of traversed connect points.
- *
- * @param completePath the list of devices
- * @param trace the trace we are building
- * @param output the final output connect point
- */
- private boolean computePath(List<ConnectPoint> completePath, StaticPacketTrace trace, ConnectPoint output) {
- List<ConnectPoint> traverseList = new ArrayList<>();
- if (!completePath.contains(trace.getInitialConnectPoint())) {
- traverseList.add(trace.getInitialConnectPoint());
- }
-
- if (output != null && trace.getInitialConnectPoint().deviceId().equals(output.deviceId())) {
- trace.addCompletePath(ImmutableList.of(trace.getInitialConnectPoint(), output));
- return true;
- }
-
- traverseList.addAll(completePath);
- if (output != null && !completePath.contains(output)) {
- traverseList.add(output);
- }
- if (!trace.getCompletePaths().contains(traverseList)) {
- trace.addCompletePath(ImmutableList.copyOf(traverseList));
- return true;
- }
- return false;
- }
-
- /**
- * Traces the packet inside a device starting from an input connect point.
- *
- * @param trace the trace we are building
- * @param packet the packet we are tracing
- * @param in the input connect point.
- * @param isDualHomed true if the trace we are doing starts or ends in a dual homed host
- * @param completePath the path up until this device
- * @return updated trace
- */
- private StaticPacketTrace traceInDevice(StaticPacketTrace trace, TrafficSelector packet, ConnectPoint in,
- boolean isDualHomed, List<ConnectPoint> completePath) {
-
- boolean multipleRoutes = false;
- if (trace.getGroupOuputs(in.deviceId()) != null) {
- multipleRoutes = multipleRoutes(trace);
- }
- if (trace.getGroupOuputs(in.deviceId()) != null && !isDualHomed && !multipleRoutes) {
- log.debug("Trace already contains device and given outputs");
- return trace;
- }
-
- log.debug("Packet {} coming in from {}", packet, in);
-
- //if device is not available exit here.
- if (!deviceNib.isAvailable(in.deviceId())) {
- trace.addResultMessage("Device is offline " + in.deviceId());
- computePath(completePath, trace, null);
- return trace;
- }
-
- //handle when the input is the controller
- //NOTE, we are using the input port as a convenience to carry the CONTROLLER port number even if
- // a packet in from the controller will not actually traverse the pipeline and have no such notion
- // as the input port.
- if (in.port().equals(PortNumber.CONTROLLER)) {
- StaticPacketTrace outputTrace = inputFromController(trace, in);
- if (outputTrace != null) {
- return trace;
- }
- }
-
- List<FlowEntry> flows = new ArrayList<>();
- List<FlowEntry> outputFlows = new ArrayList<>();
- List<Instruction> deferredInstructions = new ArrayList<>();
-
- FlowEntry nextTableIdEntry = findNextTableIdEntry(in.deviceId(), -1);
- if (nextTableIdEntry == null) {
- trace.addResultMessage("No flow rules for device " + in.deviceId() + ". Aborting");
- computePath(completePath, trace, null);
- trace.setSuccess(false);
- return trace;
- }
- TableId tableId = nextTableIdEntry.table();
- FlowEntry flowEntry;
- boolean output = false;
- while (!output) {
- log.debug("Searching a Flow Entry on table {} for packet {}", tableId, packet);
- //get the rule that matches the incoming packet
- flowEntry = matchHighestPriority(packet, in, tableId);
- log.debug("Found Flow Entry {}", flowEntry);
-
- boolean isOfdpaHardware = TroubleshootUtils.hardwareOfdpaMap
- .getOrDefault(driverNib.getDriverName(in.deviceId()), false);
-
- //if the flow entry on a table is null and we are on hardware we treat as table miss, with few exceptions
- if (flowEntry == null && isOfdpaHardware) {
- log.debug("Ofdpa Hw setup, no flow rule means table miss");
-
- if (((IndexTableId) tableId).id() == 27) {
- //Apparently a miss but Table 27 on OFDPA is a fixed table
- packet = handleOfdpa27FixedTable(trace, packet);
- }
-
- //Finding next table to go In case of miss
- nextTableIdEntry = findNextTableIdEntry(in.deviceId(), ((IndexTableId) tableId).id());
- log.debug("Next table id entry {}", nextTableIdEntry);
-
- //FIXME find better solution that enable granularity greater than 0 or all rules
- //(another possibility is max tableId)
- if (nextTableIdEntry == null && flows.size() == 0) {
- trace.addResultMessage("No matching flow rules for device " + in.deviceId() + ". Aborting");
- computePath(completePath, trace, null);
- trace.setSuccess(false);
- return trace;
-
- } else if (nextTableIdEntry == null) {
- //Means that no more flow rules are present
- output = true;
-
- } else if (((IndexTableId) tableId).id() == 20) {
- //if the table is 20 OFDPA skips to table 50
- log.debug("A miss on Table 20 on OFDPA means that we skip directly to table 50");
- tableId = IndexTableId.of(50);
-
- } else if (((IndexTableId) tableId).id() == 40) {
- //if the table is 40 OFDPA skips to table 60
- log.debug("A miss on Table 40 on OFDPA means that we skip directly to table 60");
- tableId = IndexTableId.of(60);
- } else {
- tableId = nextTableIdEntry.table();
- }
-
- } else if (flowEntry == null) {
- trace.addResultMessage("Packet has no match on table " + tableId + " in device " +
- in.deviceId() + ". Dropping");
- computePath(completePath, trace, null);
- trace.setSuccess(false);
- return trace;
- } else {
-
- //IF the table has a transition
- if (flowEntry.treatment().tableTransition() != null) {
- //update the next table we transitions to
- tableId = IndexTableId.of(flowEntry.treatment().tableTransition().tableId());
- log.debug("Flow Entry has transition to table Id {}", tableId);
- flows.add(flowEntry);
- } else {
- //table has no transition so it means that it's an output rule if on the last table
- log.debug("Flow Entry has no transition to table, treating as last rule {}", flowEntry);
- flows.add(flowEntry);
- outputFlows.add(flowEntry);
- output = true;
- }
- //update the packet according to the immediate actions of this flow rule.
- packet = updatePacket(packet, flowEntry.treatment().immediate()).build();
-
- //save the deferred rules for later
- deferredInstructions.addAll(flowEntry.treatment().deferred());
-
- //If the flow requires to clear deferred actions we do so for all the ones we encountered.
- if (flowEntry.treatment().clearedDeferred()) {
- deferredInstructions.clear();
- }
-
- //On table 10 OFDPA needs two rules to apply the vlan if none and then to transition to the next table.
- if (needsSecondTable10Flow(flowEntry, isOfdpaHardware)) {
-
- //Let's get the packet vlanId instruction
- VlanIdCriterion packetVlanIdCriterion =
- (VlanIdCriterion) packet.getCriterion(Criterion.Type.VLAN_VID);
-
- //Let's get the flow entry vlan mod instructions
- ModVlanIdInstruction entryModVlanIdInstruction = (ModVlanIdInstruction) flowEntry.treatment()
- .immediate().stream()
- .filter(instruction -> instruction instanceof ModVlanIdInstruction)
- .findFirst().orElse(null);
-
- //If the entry modVlan is not null we need to make sure that the packet has been updated and there
- // is a flow rule that matches on same criteria and with updated vlanId
- if (entryModVlanIdInstruction != null) {
-
- FlowEntry secondVlanFlow = getSecondFlowEntryOnTable10(packet, in,
- packetVlanIdCriterion, entryModVlanIdInstruction);
-
- //We found the flow that we expected
- if (secondVlanFlow != null) {
- flows.add(secondVlanFlow);
- } else {
- trace.addResultMessage("Missing forwarding rule for tagged packet on " + in);
- computePath(completePath, trace, null);
- return trace;
- }
- }
-
- }
-
- }
- }
-
- //Creating a modifiable builder for the output packet
- Builder builder = DefaultTrafficSelector.builder();
- packet.criteria().forEach(builder::add);
-
- //Adding all the flows to the trace
- trace.addFlowsForDevice(in.deviceId(), ImmutableList.copyOf(flows));
-
- List<PortNumber> outputPorts = new ArrayList<>();
- List<FlowEntry> outputFlowEntries = handleFlows(trace, packet, in, outputFlows, builder, outputPorts);
-
-
- log.debug("Handling Groups");
- //Analyze Groups
- List<Group> groups = new ArrayList<>();
-
- Collection<FlowEntry> nonOutputFlows = flows;
- nonOutputFlows.removeAll(outputFlowEntries);
-
- //Handling groups pointed at by immediate instructions
- for (FlowEntry entry : flows) {
- getGroupsFromInstructions(trace, groups, entry.treatment().immediate(),
- entry.deviceId(), builder, outputPorts, in, completePath);
- }
-
- //If we have deferred instructions at this point we handle them.
- if (deferredInstructions.size() > 0) {
- builder = handleDeferredActions(trace, packet, in, deferredInstructions, outputPorts, groups, completePath);
-
- }
- packet = builder.build();
-
- log.debug("Output Packet {}", packet);
- return trace;
- }
-
- private List<FlowEntry> handleFlows(StaticPacketTrace trace, TrafficSelector packet, ConnectPoint in,
- List<FlowEntry> outputFlows, Builder builder, List<PortNumber> outputPorts) {
- //TODO optimization
- //outputFlows contains also last rule of device, so we need filtering for OUTPUT instructions.
- List<FlowEntry> outputFlowEntries = outputFlows.stream().filter(flow -> flow.treatment()
- .allInstructions().stream().filter(instruction -> instruction.type()
- .equals(Instruction.Type.OUTPUT)).count() > 0).collect(Collectors.toList());
-
- if (outputFlowEntries.size() > 1) {
- trace.addResultMessage("More than one flow rule with OUTPUT instruction");
- log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", packet);
- }
-
- if (outputFlowEntries.size() == 1) {
-
- OutputInstruction outputInstruction = (OutputInstruction) outputFlowEntries.get(0).treatment()
- .allInstructions().stream()
- .filter(instruction -> {
- return instruction.type().equals(Instruction.Type.OUTPUT);
- }).findFirst().get();
-
- //FIXME using GroupsInDevice for output even if flows.
- buildOutputFromDevice(trace, in, builder, outputPorts, outputInstruction, ImmutableList.of());
-
- }
- return outputFlowEntries;
- }
-
- private boolean multipleRoutes(StaticPacketTrace trace) {
- boolean multipleRoutes = false;
- IPCriterion ipCriterion = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV4_DST));
- IpAddress ip = null;
- if (ipCriterion != null) {
- ip = ipCriterion.ip().address();
- } else if (trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST) != null) {
- ip = ((IPCriterion) trace.getInitialPacket().getCriterion(Criterion.Type.IPV6_DST)).ip().address();
- }
- if (ip != null) {
- Optional<ResolvedRoute> optionalRoute = routeNib.longestPrefixLookup(ip);
- if (optionalRoute.isPresent()) {
- ResolvedRoute route = optionalRoute.get();
- multipleRoutes = routeNib.getAllResolvedRoutes(route.prefix()).size() > 1;
- }
- }
- return multipleRoutes;
- }
-
- /**
- * Handles the specific case where the Input is the controller.
- * Note that the in port is used as a convenience to store the port of the controller even if the packet in
- * from a controller should not have a physical input port. The in port from the Controller is used to make sure
- * the flood to all active physical ports of the device.
- *
- * @param trace the trace
- * @param in the controller port
- * @return the augmented trace.
- */
- private StaticPacketTrace inputFromController(StaticPacketTrace trace, ConnectPoint in) {
- EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.ETH_TYPE);
- //If the packet is LLDP or BDDP we flood it on all active ports of the switch.
- if (ethTypeCriterion != null && (ethTypeCriterion.ethType().equals(EtherType.LLDP.ethType())
- || ethTypeCriterion.ethType().equals(EtherType.BDDP.ethType()))) {
- //get the active ports
- List<Port> enabledPorts = deviceNib.getPorts(in.deviceId()).stream()
- .filter(Port::isEnabled)
- .collect(Collectors.toList());
- //build an output from each one
- enabledPorts.forEach(port -> {
- GroupsInDevice output = new GroupsInDevice(new ConnectPoint(port.element().id(), port.number()),
- ImmutableList.of(), trace.getInitialPacket());
- trace.addGroupOutputPath(in.deviceId(), output);
- });
- return trace;
- }
- return null;
- }
-
- private boolean needsSecondTable10Flow(FlowEntry flowEntry, boolean isOfdpaHardware) {
- return isOfdpaHardware && flowEntry.table().equals(IndexTableId.of(10))
- && flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID) != null
- && ((VlanIdCriterion) flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID))
- .vlanId().equals(VlanId.NONE);
- }
-
- /**
- * Method that finds a flow rule on table 10 that matches the packet and the VLAN of the already
- * found rule on table 10. This is because OFDPA needs two rules on table 10, first to apply the rule,
- * second to transition to following table
- *
- * @param packet the incoming packet
- * @param in the input connect point
- * @param packetVlanIdCriterion the vlan criterion from the packet
- * @param entryModVlanIdInstruction the entry vlan instruction
- * @return the second flow entry that matched
- */
- private FlowEntry getSecondFlowEntryOnTable10(TrafficSelector packet, ConnectPoint in,
- VlanIdCriterion packetVlanIdCriterion,
- ModVlanIdInstruction entryModVlanIdInstruction) {
- FlowEntry secondVlanFlow = null;
- //Check the packet has been update from the first rule.
- if (packetVlanIdCriterion.vlanId().equals(entryModVlanIdInstruction.vlanId())) {
- //find a rule on the same table that matches the vlan and
- // also all the other elements of the flow such as input port
- secondVlanFlow = Lists.newArrayList(flowNib.getFlowEntriesByState(in.deviceId(),
- FlowEntry.FlowEntryState.ADDED)
- .iterator()).stream()
- .filter(entry -> {
- return entry.table().equals(IndexTableId.of(10));
- })
- .filter(entry -> {
- VlanIdCriterion criterion = (VlanIdCriterion) entry.selector()
- .getCriterion(Criterion.Type.VLAN_VID);
- return criterion != null && match(packet, entry)
- && criterion.vlanId().equals(entryModVlanIdInstruction.vlanId());
- }).findFirst().orElse(null);
-
- }
- return secondVlanFlow;
- }
-
-
- /**
- * Handles table 27 in Ofpda which is a fixed table not visible to any controller that handles Mpls Labels.
- *
- * @param packet the incoming packet
- * @return the updated packet
- */
- private TrafficSelector handleOfdpa27FixedTable(StaticPacketTrace trace, TrafficSelector packet) {
- log.debug("Handling table 27 on OFDPA, removing mpls ETH Type and change mpls label");
- Criterion mplsCriterion = packet.getCriterion(Criterion.Type.ETH_TYPE);
- ImmutableList.Builder<Instruction> builder = ImmutableList.builder();
-
- //If the pakcet comes in with the expected elements we update it as per OFDPA spec.
- if (mplsCriterion != null && ((EthTypeCriterion) mplsCriterion).ethType()
- .equals(EtherType.MPLS_UNICAST.ethType())) {
- //TODO update with parsing with eth MPLS pop Instruction for treating label an bos
- Instruction ethInstruction = Instructions.popMpls(((EthTypeCriterion) trace.getInitialPacket()
- .getCriterion(Criterion.Type.ETH_TYPE)).ethType());
- //FIXME what do we use as L3_Unicast mpls Label ?
- //translateInstruction(builder, ethInstruction);
- builder.add(ethInstruction);
- }
- packet = updatePacket(packet, builder.build()).build();
- return packet;
- }
-
- /**
- * Finds the flow entry with the minimun next table Id.
- *
- * @param deviceId the device to search
- * @param currentId the current id. the search will use this as minimum
- * @return the flow entry with the minimum table Id after the given one.
- */
- private FlowEntry findNextTableIdEntry(DeviceId deviceId, int currentId) {
-
- final Comparator<FlowEntry> comparator = Comparator.comparing((FlowEntry f) -> ((IndexTableId) f.table()).id());
- return Lists.newArrayList(flowNib.getFlowEntriesByState(deviceId, FlowEntry.FlowEntryState.ADDED)
- .iterator()).stream()
- .filter(f -> ((IndexTableId) f.table()).id() > currentId).min(comparator).orElse(null);
- }
-
- private Builder handleDeferredActions(StaticPacketTrace trace, TrafficSelector packet,
- ConnectPoint in, List<Instruction> deferredInstructions,
- List<PortNumber> outputPorts, List<Group> groups,
- List<ConnectPoint> completePath) {
-
- //Update the packet with the deferred instructions
- Builder builder = updatePacket(packet, deferredInstructions);
-
- //Gather any output instructions from the deferred instruction
- List<Instruction> outputFlowInstruction = deferredInstructions.stream().filter(instruction -> {
- return instruction.type().equals(Instruction.Type.OUTPUT);
- }).collect(Collectors.toList());
-
- //We are considering deferred instructions from flows, there can only be one output.
- if (outputFlowInstruction.size() > 1) {
- trace.addResultMessage("More than one flow rule with OUTPUT instruction");
- log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", packet);
- }
- //If there is one output let's go through that
- if (outputFlowInstruction.size() == 1) {
- buildOutputFromDevice(trace, in, builder, outputPorts, (OutputInstruction) outputFlowInstruction.get(0),
- ImmutableList.of());
- }
- //If there is no output let's see if there any deferred instruction point to groups.
- if (outputFlowInstruction.size() == 0) {
- getGroupsFromInstructions(trace, groups, deferredInstructions,
- in.deviceId(), builder, outputPorts, in, completePath);
- }
- return builder;
- }
-
- /**
- * Gets group information from instructions.
- *
- * @param trace the trace we are building
- * @param groupsForDevice the set of groups for this device
- * @param instructions the set of instructions we are searching for groups.
- * @param deviceId the device we are considering
- * @param builder the builder of the input packet
- * @param outputPorts the output ports for that packet
- */
- private void getGroupsFromInstructions(StaticPacketTrace trace, List<Group> groupsForDevice,
- List<Instruction> instructions, DeviceId deviceId,
- Builder builder, List<PortNumber> outputPorts,
- ConnectPoint in, List<ConnectPoint> completePath) {
- List<Instruction> groupInstructionlist = new ArrayList<>();
- // sort instructions according to priority (larger Instruction.Type ENUM constant first)
- // which enables to treat other actions before the OUTPUT action
- //TODO improve the priority scheme according to the OpenFlow ActionSet spec
- List<Instruction> instructionsSorted = new ArrayList<>();
- instructionsSorted.addAll(instructions);
- instructionsSorted.sort((instr1, instr2) -> {
- return Integer.compare(instr2.type().ordinal(), instr1.type().ordinal());
- });
-
- for (Instruction instruction : instructionsSorted) {
- log.debug("Considering Instruction {}", instruction);
- //if the instruction is not group we need to update the packet or add the output
- //to the possible outputs for this packet
- if (!instruction.type().equals(Instruction.Type.GROUP)) {
- //if the instruction is not group we need to update the packet or add the output
- //to the possible outputs for this packet
- if (instruction.type().equals(Instruction.Type.OUTPUT)) {
- buildOutputFromDevice(trace, in, builder, outputPorts,
- (OutputInstruction) instruction, ImmutableList.copyOf(groupsForDevice));
- //clearing the groups because we start from the top.
- groupsForDevice.clear();
- } else {
- builder = translateInstruction(builder, instruction);
- }
- } else {
- //if the instuction is pointing to a group we need to get the group
- groupInstructionlist.add(instruction);
- }
- }
- //handle all the internal instructions pointing to a group.
- for (Instruction instr : groupInstructionlist) {
- GroupInstruction groupInstruction = (GroupInstruction) instr;
- Group group = Lists.newArrayList(groupNib.getGroups(deviceId)).stream().filter(groupInternal -> {
- return groupInternal.id().equals(groupInstruction.groupId());
- }).findAny().orElse(null);
- if (group == null) {
- trace.addResultMessage("Null group for Instruction " + instr);
- trace.setSuccess(false);
- break;
- }
- if (group.buckets().buckets().size() == 0) {
- trace.addResultMessage("Group " + group.id() + " has no buckets");
- trace.setSuccess(false);
- computePath(completePath, trace, null);
- break;
- }
-
- //Cycle in each of the group's buckets and add them to the groups for this Device.
- for (GroupBucket bucket : group.buckets().buckets()) {
-
- //add the group to the traversed groups
- if (!groupsForDevice.contains(group)) {
- groupsForDevice.add(group);
- }
-
- getGroupsFromInstructions(trace, groupsForDevice, bucket.treatment().allInstructions(),
- deviceId, builder, outputPorts, in, completePath);
- }
- }
- }
-
- /**
- * Check if the output is the input port, if so adds a dop result message, otherwise builds
- * a possible output from this device.
- *
- * @param trace the trace
- * @param in the input connect point
- * @param builder the packet builder
- * @param outputPorts the list of output ports for this device
- * @param outputInstruction the output instruction
- * @param groupsForDevice the groups we output from
- */
- private void buildOutputFromDevice(StaticPacketTrace trace, ConnectPoint in, Builder builder,
- List<PortNumber> outputPorts, OutputInstruction outputInstruction,
- List<Group> groupsForDevice) {
- ConnectPoint output = new ConnectPoint(in.deviceId(), outputInstruction.port());
-
- outputPorts.add(outputInstruction.port());
-
- GroupsInDevice device = new GroupsInDevice(output, groupsForDevice, builder.build());
- if (trace.getGroupOuputs(output.deviceId()) != null
- && trace.getGroupOuputs(output.deviceId()).contains(device)) {
- return;
- }
- trace.addGroupOutputPath(in.deviceId(),
- new GroupsInDevice(output, groupsForDevice, builder.build()));
- }
-
- /**
- * Applies all give instructions to the input packet.
- *
- * @param packet the input packet
- * @param instructions the set of instructions
- * @return the packet with the applied instructions
- */
- private Builder updatePacket(TrafficSelector packet, List<Instruction> instructions) {
- Builder newSelector = DefaultTrafficSelector.builder();
- packet.criteria().forEach(newSelector::add);
- //FIXME optimize
- for (Instruction instruction : instructions) {
- newSelector = translateInstruction(newSelector, instruction);
- }
- return newSelector;
- }
-
- /**
- * Applies an instruction to the packet in the form of a selector.
- *
- * @param newSelector the packet selector
- * @param instruction the instruction to be translated
- * @return the new selector with the applied instruction
- */
- private Builder translateInstruction(Builder newSelector, Instruction instruction) {
- log.debug("Translating instruction {}", instruction);
- log.debug("New Selector {}", newSelector.build());
- //TODO add as required
- Criterion criterion = null;
- switch (instruction.type()) {
- case L2MODIFICATION:
- L2ModificationInstruction l2Instruction = (L2ModificationInstruction) instruction;
- switch (l2Instruction.subtype()) {
- case VLAN_ID:
- ModVlanIdInstruction vlanIdInstruction =
- (ModVlanIdInstruction) instruction;
- VlanId id = vlanIdInstruction.vlanId();
- criterion = Criteria.matchVlanId(id);
- break;
- case VLAN_POP:
- criterion = Criteria.matchVlanId(VlanId.NONE);
- break;
- case MPLS_PUSH:
- ModMplsHeaderInstruction mplsEthInstruction =
- (ModMplsHeaderInstruction) instruction;
- criterion = Criteria.matchEthType(mplsEthInstruction.ethernetType().toShort());
- break;
- case MPLS_POP:
- ModMplsHeaderInstruction mplsPopInstruction =
- (ModMplsHeaderInstruction) instruction;
- criterion = Criteria.matchEthType(mplsPopInstruction.ethernetType().toShort());
-
- //When popping MPLS we remove label and BOS
- TrafficSelector temporaryPacket = newSelector.build();
- if (temporaryPacket.getCriterion(Criterion.Type.MPLS_LABEL) != null) {
- Builder noMplsSelector = DefaultTrafficSelector.builder();
- temporaryPacket.criteria().stream().filter(c -> {
- return !c.type().equals(Criterion.Type.MPLS_LABEL) &&
- !c.type().equals(Criterion.Type.MPLS_BOS);
- }).forEach(noMplsSelector::add);
- newSelector = noMplsSelector;
- }
-
- break;
- case MPLS_LABEL:
- ModMplsLabelInstruction mplsLabelInstruction =
- (ModMplsLabelInstruction) instruction;
- criterion = Criteria.matchMplsLabel(mplsLabelInstruction.label());
- newSelector.matchMplsBos(true);
- break;
- case ETH_DST:
- ModEtherInstruction modEtherDstInstruction =
- (ModEtherInstruction) instruction;
- criterion = Criteria.matchEthDst(modEtherDstInstruction.mac());
- break;
- case ETH_SRC:
- ModEtherInstruction modEtherSrcInstruction =
- (ModEtherInstruction) instruction;
- criterion = Criteria.matchEthSrc(modEtherSrcInstruction.mac());
- break;
- default:
- log.debug("Unsupported L2 Instruction");
- break;
- }
- break;
- default:
- log.debug("Unsupported Instruction");
- break;
- }
- if (criterion != null) {
- log.debug("Adding criterion {}", criterion);
- newSelector.add(criterion);
- }
- return newSelector;
- }
-
- /**
- * Finds the rule in the device that mathces the input packet and has the highest priority.
- *
- * @param packet the input packet
- * @param in the connect point the packet comes in from
- * @param tableId the table to search
- * @return the flow entry
- */
- private FlowEntry matchHighestPriority(TrafficSelector packet, ConnectPoint in, TableId tableId) {
- //Computing the possible match rules.
- final Comparator<FlowEntry> comparator = Comparator.comparing(FlowRule::priority);
- return Lists.newArrayList(flowNib.getFlowEntriesByState(in.deviceId(), FlowEntry.FlowEntryState.ADDED)
- .iterator()).stream()
- .filter(flowEntry -> {
- return flowEntry.table().equals(tableId);
- })
- .filter(flowEntry -> {
- return match(packet, flowEntry);
- }).max(comparator).orElse(null);
- }
-
- /**
- * Matches the packet with the given flow entry.
- *
- * @param packet the packet to match
- * @param flowEntry the flow entry to match the packet against
- * @return true if the packet matches the flow.
- */
- private boolean match(TrafficSelector packet, FlowEntry flowEntry) {
- return flowEntry.selector().criteria().stream().allMatch(criterion -> {
- Criterion.Type type = criterion.type();
- //If the criterion has IP we need to do LPM to establish matching.
- if (type.equals(Criterion.Type.IPV4_SRC) || type.equals(Criterion.Type.IPV4_DST) ||
- type.equals(Criterion.Type.IPV6_SRC) || type.equals(Criterion.Type.IPV6_DST)) {
- return matchIp(packet, (IPCriterion) criterion);
- //we check that the packet contains the criterion provided by the flow rule.
- } else if (type.equals(Criterion.Type.ETH_SRC_MASKED)) {
- return matchMac(packet, (EthCriterion) criterion, false);
- } else if (type.equals(Criterion.Type.ETH_DST_MASKED)) {
- return matchMac(packet, (EthCriterion) criterion, true);
- } else {
- return packet.criteria().contains(criterion);
- }
- });
- }
-
- /**
- * Checks if the packet has an dst or src IP and if that IP matches the subnet of the ip criterion.
- *
- * @param packet the incoming packet
- * @param criterion the criterion to match
- * @return true if match
- */
- private boolean matchIp(TrafficSelector packet, IPCriterion criterion) {
- IPCriterion matchCriterion = (IPCriterion) packet.getCriterion(criterion.type());
- //if the packet does not have an IPv4 or IPv6 criterion we return true
- if (matchCriterion == null) {
- return false;
- }
- try {
- log.debug("Checking if {} is under {}", matchCriterion.ip(), criterion.ip());
- Subnet subnet = Subnet.createInstance(criterion.ip().toString());
- return subnet.isInSubnet(matchCriterion.ip().address().toInetAddress());
- } catch (UnknownHostException e) {
- return false;
- }
- }
-
- /**
- * Checks if the packet has a dst or src MAC and if that Mac matches the mask of the mac criterion.
- *
- * @param packet the incoming packet
- * @param hitCriterion the criterion to match
- * @param dst true if we are checking DST MAC
- * @return true if match
- */
- private boolean matchMac(TrafficSelector packet, EthCriterion hitCriterion, boolean dst) {
- //Packet can have only one EthCriterion
- EthCriterion matchCriterion;
- if (dst) {
- matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 -> {
- return criterion1.type().equals(Criterion.Type.ETH_DST_MASKED) ||
- criterion1.type().equals(Criterion.Type.ETH_DST);
- }).findFirst().orElse(null);
- } else {
- matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 -> {
- return criterion1.type().equals(Criterion.Type.ETH_SRC_MASKED) ||
- criterion1.type().equals(Criterion.Type.ETH_SRC);
- }).findFirst().orElse(null);
- }
- //if the packet does not have an ETH criterion we return true
- if (matchCriterion == null) {
- return true;
- }
- log.debug("Checking if {} is under {}/{}", matchCriterion.mac(), hitCriterion.mac(), hitCriterion.mask());
- return compareMac(matchCriterion.mac(), hitCriterion.mac(), hitCriterion.mask());
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java
deleted file mode 100644
index 097fa92..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.impl;
-
-import com.google.common.collect.ImmutableMap;
-import org.onlab.packet.MacAddress;
-
-import java.util.Map;
-
-/**
- * Utility class for the troubleshooting tool.
- */
-final class TroubleshootUtils {
-
- private TroubleshootUtils() {
- //Banning construction
- }
-
- /**
- * Map defining if a specific driver is for a HW switch.
- */
- //Done with builder() instead of of() for clarity
- static Map<String, Boolean> hardwareOfdpaMap = ImmutableMap.<String, Boolean>builder()
- .put("ofdpa", true)
- .put("ofdpa3", true)
- .put("qmx-ofdpa3", true)
- .put("as7712-32x-premium", true)
- .put("as5912-54x-premium", true)
- .put("as5916-54x-premium", true)
- .put("accton-ofdpa3", true)
- .put("delta-ofdpa3", true)
- .put("znyx-ofdpa", true)
- .build();
-
- /**
- * Checks if the Mac Address is inside a range between the min MAC and the mask.
- * @param macAddress the MAC address to check
- * @param minAddr the min MAC address
- * @param maskAddr the mask
- * @return true if in range, false otherwise.
- */
- static boolean compareMac(MacAddress macAddress, MacAddress minAddr, MacAddress maskAddr) {
- byte[] mac = macAddress.toBytes();
- byte[] min = minAddr.toBytes();
- byte[] mask = maskAddr.toBytes();
- boolean inRange = true;
-
- int i = 0;
-
- //if mask is 00 stop
- while (inRange && i < mask.length && (mask[i] & 0xFF) != 0) {
- int ibmac = mac[i] & 0xFF;
- int ibmin = min[i] & 0xFF;
- int ibmask = mask[i] & 0xFF;
- if (ibmask == 255) {
- inRange = ibmac == ibmin;
- } else if (ibmac < ibmin || ibmac >= ibmask) {
- inRange = false;
- break;
- }
- i++;
- }
-
- return inRange;
- }
-}
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/impl/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/impl/package-info.java
deleted file mode 100644
index dfcc294..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics implementation.
- */
-package org.onosproject.t3.impl;
diff --git a/apps/t3/app/src/main/java/org/onosproject/t3/package-info.java b/apps/t3/app/src/main/java/org/onosproject/t3/package-info.java
deleted file mode 100644
index 2dae6e2..0000000
--- a/apps/t3/app/src/main/java/org/onosproject/t3/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics.
- */
-package org.onosproject.t3;
diff --git a/apps/t3/app/src/test/java/org/onosproject/t3/impl/T3TestObjects.java b/apps/t3/app/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
deleted file mode 100644
index 2ec39b4..0000000
--- a/apps/t3/app/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.t3.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.MplsLabel;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.DefaultApplicationId;
-import org.onosproject.core.GroupId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultFlowEntry;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.group.DefaultGroup;
-import org.onosproject.net.group.DefaultGroupBucket;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.group.GroupBuckets;
-import org.onosproject.net.provider.ProviderId;
-
-/**
- * Helper class for objects related to the Troubleshoot Manager Test.
- */
-final class T3TestObjects {
-
- private T3TestObjects() {
- //banning construction
- }
-
- private static final String HOST_ONE_MAC = "00:00:00:00:00:01";
- private static final String HOST_TWO_MAC = "00:00:00:00:00:02";
- private static final String HOST_ONE_VLAN = "None";
- private static final String HOST_TWO_VLAN = "None";
- private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
- private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
- private static final String HOST_DUAL_HOMED_MAC = "00:00:00:00:00:03";
- private static final String HOST_DUAL_HOMED_VLAN = "None";
- private static final String HOST_DUAL_HOMED = HOST_DUAL_HOMED_MAC + "/" + HOST_DUAL_HOMED_VLAN;
-
- //offline device
- static final DeviceId OFFLINE_DEVICE = DeviceId.deviceId("offlineDevice");
-
- //Single Flow Test
- static final DeviceId SINGLE_FLOW_DEVICE = DeviceId.deviceId("SingleFlowDevice");
- private static final TrafficSelector SINGLE_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .build();
-
- private static final TrafficTreatment OUTPUT_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(2)).build();
- private static final FlowRule SINGLE_FLOW = DefaultFlowEntry.builder().forDevice(SINGLE_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(OUTPUT_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry SINGLE_FLOW_ENTRY = new DefaultFlowEntry(SINGLE_FLOW);
-
- static final ConnectPoint SINGLE_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(SINGLE_FLOW_DEVICE + "/" + 1);
-
- static final ConnectPoint SINGLE_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(SINGLE_FLOW_DEVICE + "/" + 2);
-
- //same output as input
- static final DeviceId SAME_OUTPUT_FLOW_DEVICE = DeviceId.deviceId("sameOutputDevice");
-
- private static final TrafficTreatment SAME_OUTPUT_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(1)).build();
- private static final FlowRule SAME_OUTPUT_FLOW = DefaultFlowEntry.builder().forDevice(SAME_OUTPUT_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(SAME_OUTPUT_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry SAME_OUTPUT_FLOW_ENTRY = new DefaultFlowEntry(SAME_OUTPUT_FLOW);
-
- static final ConnectPoint SAME_OUTPUT_FLOW_CP = ConnectPoint.deviceConnectPoint(SAME_OUTPUT_FLOW_DEVICE + "/" + 1);
-
- //ARP
- static final DeviceId ARP_FLOW_DEVICE = DeviceId.deviceId("ArpDevice");
-
- private static final TrafficSelector ARP_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchEthType(EthType.EtherType.ARP.ethType().toShort())
- .build();
-
- private static final TrafficTreatment ARP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.CONTROLLER).build();
- private static final FlowRule ARP_FLOW = DefaultFlowEntry.builder().forDevice(ARP_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(ARP_FLOW_SELECTOR)
- .withTreatment(ARP_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry ARP_FLOW_ENTRY = new DefaultFlowEntry(ARP_FLOW);
-
- static final ConnectPoint ARP_FLOW_CP = ConnectPoint.deviceConnectPoint(ARP_FLOW_DEVICE + "/" + 1);
-
-
- //Dual Flow Test
- static final DeviceId DUAL_FLOW_DEVICE = DeviceId.deviceId("DualFlowDevice");
- private static final TrafficTreatment TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setVlanId(VlanId.vlanId((short) 100))
- .transition(10)
- .build();
- private static final TrafficSelector VLAN_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchVlanId(VlanId.vlanId((short) 100))
- .build();
- private static final FlowRule FIRST_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(TRANSITION_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry FIRST_FLOW_ENTRY = new DefaultFlowEntry(FIRST_FLOW);
- private static final FlowRule SECOND_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_FLOW_DEVICE)
- .forTable(10)
- .withPriority(100)
- .withSelector(VLAN_FLOW_SELECTOR)
- .withTreatment(OUTPUT_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry SECOND_FLOW_ENTRY = new DefaultFlowEntry(SECOND_FLOW);
-
- static final ConnectPoint DUAL_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(DUAL_FLOW_DEVICE + "/" + 1);
-
- static final ConnectPoint DUAL_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(DUAL_FLOW_DEVICE + "/" + 2);
-
- //Flow and Group Test
- static final DeviceId GROUP_FLOW_DEVICE = DeviceId.deviceId("GroupFlowDevice");
-
- private static final GroupId GROUP_ID = GroupId.valueOf(1);
-
- private static final TrafficTreatment GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .pushMpls()
- .setMpls(MplsLabel.mplsLabel(100))
- .group(GROUP_ID)
- .build();
- private static final FlowRule GROUP_FLOW = DefaultFlowEntry.builder().forDevice(GROUP_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(GROUP_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry GROUP_FLOW_ENTRY = new DefaultFlowEntry(GROUP_FLOW);
-
- private static final TrafficTreatment OUTPUT_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
- .popMpls(EthType.EtherType.IPV4.ethType())
- .setOutput(PortNumber.portNumber(2)).build();
-
- private static final GroupBucket BUCKET = DefaultGroupBucket.createSelectGroupBucket(OUTPUT_GROUP_TREATMENT);
-
- private static final GroupBuckets BUCKETS = new GroupBuckets(ImmutableList.of(BUCKET));
-
- static final Group GROUP = new DefaultGroup(GROUP_ID, GROUP_FLOW_DEVICE, Group.Type.SELECT, BUCKETS);
-
- static final ConnectPoint GROUP_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(GROUP_FLOW_DEVICE + "/" + 1);
-
- static final ConnectPoint GROUP_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(GROUP_FLOW_DEVICE + "/" + 2);
-
- // Group multiple action order test
- static final DeviceId ACTION_ORDER_DEVICE = DeviceId.deviceId("ActionOrderDevice");
- private static final VlanId ACTION_ORDER_VLAN_ID = VlanId.vlanId("999");
- static final MplsLabel ACTION_ORDER_MPLS_LABEL = MplsLabel.mplsLabel("999");
- private static final TrafficTreatment ACTION_ORDER_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .pushVlan()
- .setVlanId(ACTION_ORDER_VLAN_ID)
- .group(GROUP_ID)
- .build();
- private static final FlowRule ACTION_ORDER_FLOW = DefaultFlowEntry.builder().forDevice(ACTION_ORDER_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(ACTION_ORDER_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry ACTION_ORDER_FLOW_ENTRY = new DefaultFlowEntry(ACTION_ORDER_FLOW);
- private static final TrafficTreatment ACTION_ORDER_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
- // make lower order actions come first
- .setOutput(PortNumber.portNumber(2))
- .setMpls(ACTION_ORDER_MPLS_LABEL)
- .pushMpls()
- .popVlan()
- .build();
- private static final GroupBucket ACTION_ORDER_BUCKET = DefaultGroupBucket
- .createSelectGroupBucket(ACTION_ORDER_GROUP_TREATMENT);
- private static final GroupBuckets ACTION_ORDER_BUCKETS = new GroupBuckets(ImmutableList.of(ACTION_ORDER_BUCKET));
- static final Group ACTION_ORDER_GROUP = new DefaultGroup(
- GROUP_ID, ACTION_ORDER_DEVICE, Group.Type.SELECT, ACTION_ORDER_BUCKETS);
- static final ConnectPoint ACTION_ORDER_IN_CP = ConnectPoint.deviceConnectPoint(ACTION_ORDER_DEVICE + "/" + 1);
- static final ConnectPoint ACTION_ORDER_OUT_CP = ConnectPoint.deviceConnectPoint(ACTION_ORDER_DEVICE + "/" + 2);
-
- //topology
-
- static final DeviceId TOPO_FLOW_DEVICE = DeviceId.deviceId("SingleFlowDevice1");
-
- static final DeviceId TOPO_FLOW_2_DEVICE = DeviceId.deviceId("SingleFlowDevice2");
-
- static final DeviceId TOPO_FLOW_3_DEVICE = DeviceId.deviceId("SingleFlowDevice3");
-
- private static final TrafficSelector TOPO_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
- .build();
-
- private static final FlowRule TOPO_SINGLE_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(TOPO_FLOW_SELECTOR)
- .withTreatment(OUTPUT_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry TOPO_SINGLE_FLOW_ENTRY = new DefaultFlowEntry(TOPO_SINGLE_FLOW);
-
- static final ConnectPoint TOPO_FLOW_1_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_DEVICE + "/" + 1);
-
- static final ConnectPoint TOPO_FLOW_1_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_DEVICE + "/" + 2);
-
- static final ConnectPoint TOPO_FLOW_2_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_2_DEVICE + "/" + 1);
-
- static final ConnectPoint TOPO_FLOW_2_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_2_DEVICE + "/" + 2);
-
- static final ConnectPoint TOPO_FLOW_3_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 1);
-
- static final ConnectPoint TOPO_FLOW_3_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 2);
-
-
- //Topology with Groups
-
- static final DeviceId TOPO_GROUP_FLOW_DEVICE = DeviceId.deviceId("TopoGroupFlowDevice");
-
- private static final TrafficSelector TOPO_SECOND_INPUT_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(3))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
- .build();
-
- private static final FlowRule TOPO_SECOND_INPUT_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(TOPO_SECOND_INPUT_FLOW_SELECTOR)
- .withTreatment(OUTPUT_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- private static final TrafficTreatment OUTPUT_2_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(3)).build();
-
-
- private static final GroupId TOPO_GROUP_ID = GroupId.valueOf(1);
-
- private static final TrafficTreatment TOPO_GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .group(TOPO_GROUP_ID)
- .build();
- private static final FlowRule TOPO_GROUP_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_GROUP_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(TOPO_FLOW_SELECTOR)
- .withTreatment(TOPO_GROUP_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry TOPO_GROUP_FLOW_ENTRY = new DefaultFlowEntry(TOPO_GROUP_FLOW);
-
- private static final GroupBucket BUCKET_2 = DefaultGroupBucket.createSelectGroupBucket(OUTPUT_2_FLOW_TREATMENT);
-
- private static final GroupBuckets BUCKETS_MULTIPLE = new GroupBuckets(ImmutableList.of(BUCKET, BUCKET_2));
-
- static final Group TOPO_GROUP = new DefaultGroup(TOPO_GROUP_ID, TOPO_GROUP_FLOW_DEVICE,
- Group.Type.SELECT, BUCKETS_MULTIPLE);
-
- static final FlowEntry TOPO_SECOND_INPUT_FLOW_ENTRY = new DefaultFlowEntry(TOPO_SECOND_INPUT_FLOW);
-
- static final DeviceId TOPO_FLOW_4_DEVICE = DeviceId.deviceId("SingleFlowDevice4");
-
- static final ConnectPoint TOPO_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 1);
-
- static final ConnectPoint TOPO_FLOW_OUT_CP_1 = ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 2);
-
- protected static final ConnectPoint TOPO_FLOW_OUT_CP_2 =
- ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 3);
-
- static final ConnectPoint TOPO_FLOW_4_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_4_DEVICE + "/" + 1);
-
- static final ConnectPoint TOPO_FLOW_3_IN_2_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 3);
-
- static final ConnectPoint TOPO_FLOW_4_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_4_DEVICE + "/" + 2);
-
-
- //hardware
-
- static final DeviceId HARDWARE_DEVICE = DeviceId.deviceId("HardwareDevice");
-
- static final ConnectPoint HARDWARE_DEVICE_IN_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE + "/" + 1);
-
- static final ConnectPoint HARDWARE_DEVICE_OUT_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE + "/" + 2);
-
- private static final TrafficSelector HARDWARE_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .build();
-
- private static final TrafficTreatment HW_TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .pushMpls()
- .transition(27)
- .build();
-
- private static final FlowRule HARDWARE_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(HARDWARE_FLOW_SELECTOR)
- .withTreatment(HW_TRANSITION_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry HARDWARE_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_FLOW);
-
- private static final TrafficSelector HARDWARE_ETH_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .build();
-
- private static final FlowRule HARDWARE_ETH_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
- .forTable(30)
- .withPriority(100)
- .withSelector(HARDWARE_ETH_FLOW_SELECTOR)
- .withTreatment(OUTPUT_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry HARDWARE_ETH_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_ETH_FLOW);
-
- //HW Double Rule on 10
-
- static final DeviceId HARDWARE_DEVICE_10 = DeviceId.deviceId("HardwareDevice10");
-
- static final ConnectPoint HARDWARE_DEVICE_10_IN_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE_10 + "/" + 1);
-
- static final ConnectPoint HARDWARE_DEVICE_10_OUT_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE_10 + "/" + 2);
-
- private static final TrafficSelector HARDWARE_10_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .matchVlanId(VlanId.NONE)
- .build();
-
- private static final TrafficTreatment HARDWARE_10_TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setVlanId(VlanId.vlanId("10"))
- .transition(20)
- .build();
-
- private static final FlowRule HARDWARE_DEVICE_10_FLOW = DefaultFlowEntry.builder().forDevice(HARDWARE_DEVICE_10)
- .forTable(10)
- .withPriority(100)
- .withSelector(HARDWARE_10_FLOW_SELECTOR)
- .withTreatment(HARDWARE_10_TRANSITION_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry HARDWARE_10_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_DEVICE_10_FLOW);
-
- private static final TrafficSelector HARDWARE_10_SECOND_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchVlanId(VlanId.vlanId("10"))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .build();
-
- private static final FlowRule HARDWARE_10_SECOND_FLOW = DefaultFlowEntry.builder().forDevice(HARDWARE_DEVICE_10)
- .forTable(10)
- .withPriority(100)
- .withSelector(HARDWARE_10_SECOND_SELECTOR)
- .withTreatment(HARDWARE_10_TRANSITION_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry HARDWARE_10_SECOND_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_10_SECOND_FLOW);
-
- private static final FlowRule HARDWARE_10_OUTPUT_FLOW = DefaultFlowEntry.builder().forDevice(HARDWARE_DEVICE_10)
- .forTable(20)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(OUTPUT_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry HARDWARE_10_OUTPUT_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_10_OUTPUT_FLOW);
-
- //Dual Links
- // - (1) Device 1 (2-3) - (1-4) Device 2 (2-3) - (1-2) Device 3 (3) -
- static final DeviceId DUAL_LINK_1 = DeviceId.deviceId("DualLink1");
- static final DeviceId DUAL_LINK_2 = DeviceId.deviceId("DualLink2");
- static final DeviceId DUAL_LINK_3 = DeviceId.deviceId("DualLink3");
-
- static final ConnectPoint DUAL_LINK_1_CP_1_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_1 + "/" + 1);
- static final ConnectPoint DUAL_LINK_1_CP_2_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_1 + "/" + 2);
- static final ConnectPoint DUAL_LINK_1_CP_3_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_1 + "/" + 3);
- static final ConnectPoint DUAL_LINK_2_CP_1_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 1);
- static final ConnectPoint DUAL_LINK_2_CP_4_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 4);
- static final ConnectPoint DUAL_LINK_2_CP_2_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 2);
- static final ConnectPoint DUAL_LINK_2_CP_3_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_2 + "/" + 3);
- static final ConnectPoint DUAL_LINK_3_CP_1_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_3 + "/" + 1);
- static final ConnectPoint DUAL_LINK_3_CP_2_IN = ConnectPoint.deviceConnectPoint(DUAL_LINK_3 + "/" + 2);
- static final ConnectPoint DUAL_LINK_3_CP_3_OUT = ConnectPoint.deviceConnectPoint(DUAL_LINK_3 + "/" + 3);
-
- //match on port 1 and point to group for device 1 and 2
- private static final TrafficTreatment DUAL_LINK_1_GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .pushMpls()
- .setMpls(MplsLabel.mplsLabel(100))
- .group(GROUP_ID)
- .build();
- private static final FlowRule DUAL_LINK_1_GROUP_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_LINK_1)
- .forTable(0)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(DUAL_LINK_1_GROUP_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry DUAL_LINK_1_GROUP_FLOW_ENTRY = new DefaultFlowEntry(DUAL_LINK_1_GROUP_FLOW);
-
- //Match on port 4 and point to group for device 2
- private static final TrafficSelector DUAL_LINK_2_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(4))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .build();
-
- private static final FlowRule DUAL_LINK_2_GROUP_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_LINK_2)
- .forTable(0)
- .withPriority(100)
- .withSelector(DUAL_LINK_2_FLOW_SELECTOR)
- .withTreatment(DUAL_LINK_1_GROUP_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry DUAL_LINK_2_GROUP_FLOW_ENTRY = new DefaultFlowEntry(DUAL_LINK_2_GROUP_FLOW);
-
- //Flows for device 3 to ouput on port 3
- private static final TrafficTreatment DUAL_LINK_1_OUTPUT_TREATMENT = DefaultTrafficTreatment.builder()
- .popMpls(EthType.EtherType.IPV4.ethType())
- .setOutput(PortNumber.portNumber(3)).build();
-
- private static final TrafficSelector DUAL_LINK_3_FLOW_SELECTOR_1 = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .build();
- private static final FlowRule DUAL_LINK_3_FLOW_1 = DefaultFlowEntry.builder().forDevice(DUAL_LINK_3)
- .forTable(0)
- .withPriority(100)
- .withSelector(DUAL_LINK_3_FLOW_SELECTOR_1)
- .withTreatment(DUAL_LINK_1_OUTPUT_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry DUAL_LINK_3_FLOW_ENTRY = new DefaultFlowEntry(DUAL_LINK_3_FLOW_1);
-
- private static final TrafficSelector DUAL_LINK_3_FLOW_SELECTOR_2 = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(2))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .build();
- private static final FlowRule DUAL_LINK_3_FLOW_2 = DefaultFlowEntry.builder().forDevice(DUAL_LINK_3)
- .forTable(0)
- .withPriority(100)
- .withSelector(DUAL_LINK_3_FLOW_SELECTOR_2)
- .withTreatment(DUAL_LINK_1_OUTPUT_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry DUAL_LINK_3_FLOW_ENTRY_2 = new DefaultFlowEntry(DUAL_LINK_3_FLOW_2);
-
- //Group with two buckets to output on port 2 and 3 of device 1 and 2
-
- private static final GroupBucket BUCKET_2_DUAL =
- DefaultGroupBucket.createSelectGroupBucket(DUAL_LINK_1_OUTPUT_TREATMENT);
-
- private static final GroupBuckets BUCKETS_DUAL = new GroupBuckets(ImmutableList.of(BUCKET, BUCKET_2_DUAL));
-
- static final Group DUAL_LINK_GROUP = new DefaultGroup(GROUP_ID, DUAL_LINK_1, Group.Type.SELECT, BUCKETS_DUAL);
-
- //Clear Deferred
- static final DeviceId DEFERRED_1 = DeviceId.deviceId("Deferred");
-
- static final ConnectPoint DEFERRED_CP_1_IN = ConnectPoint.deviceConnectPoint(DEFERRED_1 + "/" + 1);
- static final ConnectPoint DEFERRED_CP_2_OUT = ConnectPoint.deviceConnectPoint(DEFERRED_1 + "/" + 2);
-
- //match on port 1 and apply deferred actions
- private static final TrafficTreatment DEFERRED_1_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .transition(10)
- .deferred()
- .pushMpls()
- .setMpls(MplsLabel.mplsLabel(100))
- .build();
- private static final FlowRule DEFERRED_FLOW = DefaultFlowEntry.builder().forDevice(DEFERRED_1)
- .forTable(0)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(DEFERRED_1_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry DEFERRED_FLOW_ENTRY = new DefaultFlowEntry(DEFERRED_FLOW);
-
- //Multicast Flow and Group Test
- static final DeviceId MULTICAST_GROUP_FLOW_DEVICE = DeviceId.deviceId("MulticastGroupFlowDevice");
-
- private static final TrafficSelector MULTICAST_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPDst(IpPrefix.valueOf("224.0.0.1/32"))
- .matchEthDst(MacAddress.valueOf("01:00:5e:00:00:01"))
- .build();
-
- private static final FlowRule MULTICAST_GROUP_FLOW =
- DefaultFlowEntry.builder().forDevice(MULTICAST_GROUP_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(MULTICAST_FLOW_SELECTOR)
- .withTreatment(GROUP_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
-
- static final FlowEntry MULTICAST_GROUP_FLOW_ENTRY = new DefaultFlowEntry(MULTICAST_GROUP_FLOW);
-
- static final Group MULTICAST_GROUP = new DefaultGroup(GROUP_ID, MULTICAST_GROUP_FLOW_DEVICE,
- Group.Type.SELECT, BUCKETS_MULTIPLE);
-
- static final ConnectPoint MULTICAST_IN_CP = ConnectPoint.deviceConnectPoint(MULTICAST_GROUP_FLOW_DEVICE + "/" + 1);
-
- static final ConnectPoint MULTICAST_OUT_CP = ConnectPoint.deviceConnectPoint(MULTICAST_GROUP_FLOW_DEVICE + "/" + 3);
-
- static final ConnectPoint MULTICAST_OUT_CP_2 =
- ConnectPoint.deviceConnectPoint(MULTICAST_GROUP_FLOW_DEVICE + "/" + 2);
-
- //match on port 1, clear deferred actions and output
- private static final TrafficTreatment DEFERRED_CLEAR_1_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .wipeDeferred()
- .setOutput(PortNumber.portNumber(2))
- .build();
- private static final FlowRule DEFERRED_CLEAR_FLOW = DefaultFlowEntry.builder().forDevice(DEFERRED_1)
- .forTable(10)
- .withPriority(100)
- .withSelector(SINGLE_FLOW_SELECTOR)
- .withTreatment(DEFERRED_CLEAR_1_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry DEFERRED_CLEAR_FLOW_ENTRY = new DefaultFlowEntry(DEFERRED_CLEAR_FLOW);
-
- //LLDP
-
- static final DeviceId LLDP_FLOW_DEVICE = DeviceId.deviceId("LldpDevice");
-
- private static final TrafficSelector LLDP_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchEthType(EthType.EtherType.LLDP.ethType().toShort())
- .build();
-
- private static final TrafficTreatment LLDP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.CONTROLLER).build();
- private static final FlowRule LLDP_FLOW = DefaultFlowEntry.builder().forDevice(LLDP_FLOW_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(LLDP_FLOW_SELECTOR)
- .withTreatment(LLDP_FLOW_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry LLDP_FLOW_ENTRY = new DefaultFlowEntry(LLDP_FLOW);
-
- static final ConnectPoint LLDP_FLOW_CP = ConnectPoint.deviceConnectPoint(LLDP_FLOW_DEVICE + "/" + 1);
-
- //No Buckets
-
- static final DeviceId NO_BUCKET_DEVICE = DeviceId.deviceId("nobucket");
-
- private static final TrafficSelector NO_BUCKET_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .build();
-
- private static final GroupId NO_BUCKET_GROUP_ID = GroupId.valueOf(1);
-
- private static final TrafficTreatment NO_BUCKET_TREATMENT = DefaultTrafficTreatment.builder()
- .group(NO_BUCKET_GROUP_ID)
- .build();
- private static final FlowRule NO_BUCKET_FLOW = DefaultFlowEntry.builder().forDevice(NO_BUCKET_DEVICE)
- .forTable(0)
- .withPriority(100)
- .withSelector(NO_BUCKET_SELECTOR)
- .withTreatment(NO_BUCKET_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry NO_BUCKET_ENTRY = new DefaultFlowEntry(NO_BUCKET_FLOW);
-
- private static final GroupBuckets NO_BUCKETS = new GroupBuckets(ImmutableList.of());
-
- static final Group NO_BUCKET_GROUP =
- new DefaultGroup(NO_BUCKET_GROUP_ID, NO_BUCKET_DEVICE, Group.Type.SELECT, NO_BUCKETS);
-
- static final ConnectPoint NO_BUCKET_CP = ConnectPoint.deviceConnectPoint(NO_BUCKET_DEVICE + "/" + 1);
-
- //Dual Homing
-
- static final DeviceId DUAL_HOME_DEVICE_1 = DeviceId.deviceId("DualHomeDevice1");
-
- static final DeviceId DUAL_HOME_DEVICE_2 = DeviceId.deviceId("DualHomeDevice2");
-
- static final DeviceId DUAL_HOME_DEVICE_3 = DeviceId.deviceId("DualHomeDevice3");
-
- static final ConnectPoint DUAL_HOME_CP_1_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 1);
- static final ConnectPoint DUAL_HOME_CP_1_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 2);
- static final ConnectPoint DUAL_HOME_CP_1_3 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 3);
-
- static final ConnectPoint DUAL_HOME_CP_2_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_2 + "/" + 1);
- static final ConnectPoint DUAL_HOME_CP_2_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_2 + "/" + 2);
-
- static final ConnectPoint DUAL_HOME_CP_3_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_3 + "/" + 1);
- static final ConnectPoint DUAL_HOME_CP_3_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_3 + "/" + 2);
-
-
- private static final TrafficSelector DUAL_HOME_INPUT_FLOW_SELECTOR = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .build();
-
- private static final GroupId DUAL_HOME_GROUP_ID = GroupId.valueOf(1);
-
- private static final TrafficTreatment DUAL_HOME_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
- .group(DUAL_HOME_GROUP_ID)
- .build();
- private static final FlowRule DUAL_HOME_INPUT_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_HOME_DEVICE_1)
- .forTable(0)
- .withPriority(100)
- .withSelector(DUAL_HOME_INPUT_FLOW_SELECTOR)
- .withTreatment(DUAL_HOME_GROUP_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry DUAL_HOME_FLOW_ENTRY = new DefaultFlowEntry(DUAL_HOME_INPUT_FLOW);
-
- private static final TrafficTreatment DUAL_HOME_OUTPUT_1_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(2)).build();
- private static final TrafficTreatment DUAL_HOME_OUTPUT_2_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(3)).build();
-
- private static final GroupBucket BUCKET_1_DUAL_HOMED =
- DefaultGroupBucket.createSelectGroupBucket(DUAL_HOME_OUTPUT_1_FLOW_TREATMENT);
-
- private static final GroupBucket BUCKET_2_DUAL_HOMED =
- DefaultGroupBucket.createSelectGroupBucket(DUAL_HOME_OUTPUT_2_FLOW_TREATMENT);
-
- private static final GroupBuckets BUCKETS_MULTIPLE_DUAL = new GroupBuckets(ImmutableList.of(BUCKET_1_DUAL_HOMED,
- BUCKET_2_DUAL_HOMED));
-
- static final Group DUAL_HOME_GROUP = new DefaultGroup(DUAL_HOME_GROUP_ID, DUAL_HOME_DEVICE_1,
- Group.Type.SELECT, BUCKETS_MULTIPLE_DUAL);
-
- private static final TrafficTreatment DUAL_HOME_TREATMENT = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber("2"))
- .build();
- private static final FlowRule DUAL_HOME_OUT_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_HOME_DEVICE_2)
- .forTable(0)
- .withPriority(100)
- .withSelector(DUAL_HOME_INPUT_FLOW_SELECTOR)
- .withTreatment(DUAL_HOME_TREATMENT)
- .fromApp(new DefaultApplicationId(0, "TestApp"))
- .makePermanent()
- .build();
- static final FlowEntry DUAL_HOME_OUT_FLOW_ENTRY = new DefaultFlowEntry(DUAL_HOME_OUT_FLOW);
-
- //helper elements
-
- static final String MASTER_1 = "Master1";
-
- static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_ONE), MacAddress.valueOf(100),
- VlanId.NONE, new HostLocation(SINGLE_FLOW_DEVICE, PortNumber.portNumber(2), 0),
- ImmutableSet.of(IpAddress.valueOf("127.0.0.2")));
-
- static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_TWO), MacAddress.valueOf(100),
- VlanId.NONE, new HostLocation(TOPO_FLOW_3_DEVICE, PortNumber.portNumber(2), 0),
- ImmutableSet.of(IpAddress.valueOf("127.0.0.3")));
-
- static final Host DUAL_HOME_H = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_DUAL_HOMED),
- MacAddress.valueOf(HOST_DUAL_HOMED_MAC),
- VlanId.NONE, ImmutableSet.of(new HostLocation(DUAL_HOME_DEVICE_2, PortNumber.portNumber(2), 0),
- new HostLocation(DUAL_HOME_DEVICE_3, PortNumber.portNumber(2), 0)),
- ImmutableSet.of(IpAddress.valueOf("127.0.0.4")), true, DefaultAnnotations.builder().build());
-
- static final TrafficSelector PACKET_OK = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
- .matchVlanId(VlanId.NONE)
- .build();
-
- static final TrafficSelector PACKET_OK_TOPO = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
- .build();
-
- static final TrafficSelector PACKET_ARP = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPDst(IpPrefix.valueOf("255.255.255.255/32"))
- .matchEthType(EthType.EtherType.ARP.ethType().toShort())
- .build();
-
- static final TrafficSelector PACKET_LLDP = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchEthType(EthType.EtherType.LLDP.ethType().toShort())
- .build();
-
- static final TrafficSelector PACKET_OK_MULTICAST = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .matchEthDst(MacAddress.valueOf("01:00:5e:00:00:01"))
- .matchIPDst(IpPrefix.valueOf("224.0.0.1/32"))
- .build();
-
- static final TrafficSelector PACKET_DUAL_HOME = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.4/32"))
- .build();
-
- static final TrafficSelector PACKET_FAIL = DefaultTrafficSelector.builder()
- .matchInPort(PortNumber.portNumber(1))
- .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
- .matchIPDst(IpPrefix.valueOf("127.0.0.99/32"))
- .build();
-}
diff --git a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java b/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
deleted file mode 100644
index d1eba21..0000000
--- a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
+++ /dev/null
@@ -1,695 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.t3.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.ChassisId;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultDevice;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPort;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.MplsCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.group.Group;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.routeservice.ResolvedRoute;
-import org.onosproject.t3.api.DeviceNib;
-import org.onosproject.t3.api.DriverNib;
-import org.onosproject.t3.api.EdgePortNib;
-import org.onosproject.t3.api.FlowNib;
-import org.onosproject.t3.api.GroupNib;
-import org.onosproject.t3.api.HostNib;
-import org.onosproject.t3.api.LinkNib;
-import org.onosproject.t3.api.MastershipNib;
-import org.onosproject.t3.api.RouteNib;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.slf4j.Logger;
-
-import java.util.Optional;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.onosproject.net.Device.Type.SWITCH;
-import static org.onosproject.t3.impl.T3TestObjects.*;
-import static org.onosproject.t3.impl.TroubleshootManager.PACKET_TO_CONTROLLER;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Test Class for Troubleshoot Manager.
- */
-public class TroubleshootManagerTest {
-
- private static final Logger log = getLogger(TroubleshootManager.class);
-
- private TroubleshootManager mngr;
-
- @Before
- public void setUp() throws Exception {
- mngr = new TroubleshootManager();
-
- mngr.flowNib = new TestFlowRuleService();
- mngr.groupNib = new TestGroupService();
- mngr.hostNib = new TestHostService();
- mngr.linkNib = new TestLinkService();
- mngr.deviceNib = new TestDeviceService();
- mngr.driverNib = new TestDriverService();
- mngr.mastershipNib = new TestMastershipService();
- mngr.edgePortNib = new TestEdgePortService();
- mngr.routeNib = new TestRouteService();
-
- assertNotNull("Manager should not be null", mngr);
-
- assertNotNull("Flow rule Service should not be null", mngr.flowNib);
- assertNotNull("Group Service should not be null", mngr.groupNib);
- assertNotNull("Host Service should not be null", mngr.hostNib);
- assertNotNull("Link Service should not be null", mngr.linkNib);
- assertNotNull("Device Service should not be null", mngr.deviceNib);
- assertNotNull("Driver Service should not be null", mngr.driverNib);
- assertNotNull("Mastership Service should not be null", mngr.driverNib);
- assertNotNull("EdgePort Service should not be null", mngr.driverNib);
- assertNotNull("Route Service should not be null", mngr.routeNib);
- }
-
- /**
- * Tests failure on non existent device.
- */
- @Test(expected = NullPointerException.class)
- public void nonExistentDevice() {
- StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("nonexistent" + "/1"));
- }
-
- /**
- * Tests failure on offline device.
- */
- @Test
- public void offlineDevice() {
- StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint(OFFLINE_DEVICE + "/1"));
- assertNotNull("Trace should not be null", traceFail);
- assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
- }
-
- /**
- * Tests failure on same output.
- */
- @Test
- public void sameOutput() {
- StaticPacketTrace traceFail = mngr.trace(PACKET_OK, SAME_OUTPUT_FLOW_CP);
- assertNotNull("Trace should not be null", traceFail);
- assertTrue("Trace should be unsuccessful",
- traceFail.resultMessage().contains("is same as initial input"));
- log.info("trace {}", traceFail.resultMessage());
- }
-
- /**
- * Tests ARP to controller.
- */
- @Test
- public void arpToController() {
- StaticPacketTrace traceSuccess = mngr.trace(PACKET_ARP, ARP_FLOW_CP);
- assertNotNull("Trace should not be null", traceSuccess);
- assertTrue("Trace should be successful",
- traceSuccess.resultMessage().contains(PACKET_TO_CONTROLLER));
- assertTrue("Master should be Master1",
- traceSuccess.resultMessage().contains(MASTER_1));
- ConnectPoint connectPoint = traceSuccess.getGroupOuputs(ARP_FLOW_DEVICE).get(0).getOutput();
- assertEquals("Packet Should go to CONTROLLER", PortNumber.CONTROLLER, connectPoint.port());
- assertNull("VlanId should be null", traceSuccess.getGroupOuputs(ARP_FLOW_DEVICE).get(0)
- .getFinalPacket().getCriterion(Criterion.Type.VLAN_VID));
- log.info("trace {}", traceSuccess.resultMessage());
- }
-
-
- /**
- * Tests failure on device with no flows.
- */
- @Test
- public void noFlows() {
- StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("test/1"));
- assertNotNull("Trace should not be null", traceFail);
- assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
- log.info("trace {}", traceFail.resultMessage());
- }
-
- /**
- * Test group with no buckets.
- */
- @Test
- public void noBucketsTest() throws Exception {
-
- StaticPacketTrace traceFail = mngr.trace(PACKET_OK, NO_BUCKET_CP);
- assertNotNull("Trace should not be null", traceFail);
- assertTrue("Trace should be unsuccessful",
- traceFail.resultMessage().contains("no buckets"));
- log.info("trace {}", traceFail.resultMessage());
-
- }
-
- /**
- * Test a single flow rule that has output port in it.
- */
- @Test
- public void testSingleFlowRule() {
-
- testSuccess(PACKET_OK, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE, SINGLE_FLOW_OUT_CP, 1, 1);
-
- testFailure(PACKET_FAIL, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE);
- }
-
- /**
- * Tests two flow rule the last one of which has output port in it.
- */
- @Test
- public void testDualFlowRule() {
-
- //Test Success
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE,
- DUAL_FLOW_OUT_CP, 1, 1);
-
- //Testing Vlan
- Criterion criterion = traceSuccess.getGroupOuputs(DUAL_FLOW_DEVICE).get(0).
- getFinalPacket().getCriterion(Criterion.Type.VLAN_VID);
- assertNotNull("Packet Should have Vlan", criterion);
-
- VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion;
-
- assertEquals("Vlan should be 100", VlanId.vlanId((short) 100), vlanIdCriterion.vlanId());
-
- //Test Faliure
- testFailure(PACKET_FAIL, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE);
-
- }
-
- /**
- * Test a single flow rule that points to a group with output port in it.
- */
- @Test
- public void flowAndGroup() throws Exception {
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, GROUP_FLOW_IN_CP, GROUP_FLOW_DEVICE,
- GROUP_FLOW_OUT_CP, 1, 1);
-
- assertTrue("Wrong Output Group", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
- .get(0).getGroups().contains(GROUP));
- assertEquals("Packet should not have MPLS Label", EthType.EtherType.IPV4.ethType(),
- ((EthTypeCriterion) traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
- .get(0).getFinalPacket().getCriterion(Criterion.Type.ETH_TYPE)).ethType());
- assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
- .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));
- assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
- .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_BOS));
-
- }
-
- /**
- * Test a single flow rule that points to a group with multiple actions
- * that need to be executed in the order specified in the OpenFlow spec.
- */
- @Test
- public void testGroupMultipleActionsOrdered() {
-
- StaticPacketTrace traceSuccess = testSuccess(
- PACKET_OK, ACTION_ORDER_IN_CP, ACTION_ORDER_DEVICE, ACTION_ORDER_OUT_CP, 1, 1);
-
- assertEquals("Packet should not have VLAN ID",
- VlanId.NONE,
- ((VlanIdCriterion) traceSuccess.getGroupOuputs(ACTION_ORDER_DEVICE)
- .get(0).getFinalPacket().getCriterion(Criterion.Type.VLAN_VID)).vlanId());
- assertEquals("Packet should have MPLS label",
- ACTION_ORDER_MPLS_LABEL,
- ((MplsCriterion) traceSuccess.getGroupOuputs(ACTION_ORDER_DEVICE)
- .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL)).label());
-
- }
-
- /**
- * Test path through a 3 device topology.
- */
- @Test
- public void singlePathTopology() throws Exception {
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_1_IN_CP,
- TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 1, 1);
-
- assertTrue("Incorrect path",
- traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_IN_CP));
- assertTrue("Incorrect path",
- traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_OUT_CP));
- assertTrue("Incorrect path",
- traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_3_IN_CP));
-
- }
-
- /**
- * Test path through a 4 device topology with first device that has groups with multiple output buckets.
- */
- @Test
- public void testGroupTopo() throws Exception {
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_IN_CP,
- TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 2, 1);
-
- log.info("{}", traceSuccess);
-
- assertTrue("Incorrect groups",
- traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(0).getGroups().contains(TOPO_GROUP));
- assertTrue("Incorrect bucket",
- traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(1).getGroups().contains(TOPO_GROUP));
- }
-
- /**
- * Test HW support in a single device with 2 flow rules to check hit of static HW rules.
- */
- @Test
- public void hardwareTest() throws Exception {
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, HARDWARE_DEVICE_IN_CP,
- HARDWARE_DEVICE, HARDWARE_DEVICE_OUT_CP, 1, 1);
-
- assertEquals("wrong ETH type", EthType.EtherType.IPV4.ethType(),
- ((EthTypeCriterion) traceSuccess.getGroupOuputs(HARDWARE_DEVICE).get(0).getFinalPacket()
- .getCriterion(Criterion.Type.ETH_TYPE)).ethType());
-
- }
-
- /**
- * Test that HW has two rules on table 10 for untagged packets.
- */
- @Test
- public void hardwareTable10Test() throws Exception {
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, HARDWARE_DEVICE_10_IN_CP,
- HARDWARE_DEVICE_10, HARDWARE_DEVICE_10_OUT_CP, 1, 1);
-
- assertTrue("Second flow rule is absent", traceSuccess.getFlowsForDevice(HARDWARE_DEVICE_10)
- .contains(HARDWARE_10_SECOND_FLOW_ENTRY));
-
- }
-
- /**
- * Test dual links between 3 topology elements.
- */
- @Test
- public void dualLinks() throws Exception {
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_LINK_1_CP_1_IN,
- DUAL_LINK_3, DUAL_LINK_3_CP_3_OUT, 4, 1);
-
- //TODO tests
-
- }
-
- /**
- * Test proper clear deferred behaviour.
- */
- @Test
- public void clearDeferred() throws Exception {
-
- StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DEFERRED_CP_1_IN,
- DEFERRED_1, DEFERRED_CP_2_OUT, 1, 1);
-
- assertNull("MPLS should have been not applied due to clear deferred", traceSuccess
- .getGroupOuputs(DEFERRED_1).get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));
-
- }
-
-
- /**
- * Test LLDP output to controller.
- */
- @Test
- public void lldpToController() {
- StaticPacketTrace traceSuccess = mngr.trace(PACKET_LLDP, LLDP_FLOW_CP);
- assertNotNull("Trace should not be null", traceSuccess);
- assertTrue("Trace should be successful",
- traceSuccess.resultMessage().contains("Packet goes to the controller"));
- assertTrue("Master should be Master1",
- traceSuccess.resultMessage().contains(MASTER_1));
- ConnectPoint connectPoint = traceSuccess.getGroupOuputs(LLDP_FLOW_DEVICE).get(0).getOutput();
- assertEquals("Packet Should go to CONTROLLER", PortNumber.CONTROLLER, connectPoint.port());
- log.info("trace {}", traceSuccess.resultMessage());
- }
-
- /**
- * Test multicast in single device.
- */
- @Test
- public void multicastTest() throws Exception {
-
- StaticPacketTrace traceSuccess = mngr.trace(PACKET_OK_MULTICAST, MULTICAST_IN_CP);
-
- log.info("trace {}", traceSuccess);
-
- log.info("trace {}", traceSuccess.resultMessage());
-
- assertNotNull("trace should not be null", traceSuccess);
- assertEquals("Trace should have " + 2 + " output", 2,
- traceSuccess.getGroupOuputs(MULTICAST_GROUP_FLOW_DEVICE).size());
- assertEquals("Trace should only have " + 2 + "output", 2,
- traceSuccess.getCompletePaths().size());
- assertTrue("Trace should be successful",
- traceSuccess.resultMessage().contains("reached output"));
- assertEquals("Incorrect Output CP", MULTICAST_OUT_CP_2,
- traceSuccess.getGroupOuputs(MULTICAST_GROUP_FLOW_DEVICE).get(0).getOutput());
- assertEquals("Incorrect Output CP", MULTICAST_OUT_CP,
- traceSuccess.getGroupOuputs(MULTICAST_GROUP_FLOW_DEVICE).get(1).getOutput());
-
- }
-
- /**
- * Tests dual homing of a host.
- */
- @Test
- public void dualhomedTest() throws Exception {
- StaticPacketTrace traceSuccess = mngr.trace(PACKET_DUAL_HOME, DUAL_HOME_CP_1_1);
-
- assertNotNull("trace should not be null", traceSuccess);
- assertTrue("Should have 2 output paths", traceSuccess.getCompletePaths().size() == 2);
- assertTrue("Should contain proper path", traceSuccess.getCompletePaths()
- .contains(ImmutableList.of(DUAL_HOME_CP_1_1, DUAL_HOME_CP_1_2, DUAL_HOME_CP_2_1, DUAL_HOME_CP_2_2)));
- assertTrue("Should contain proper path", traceSuccess.getCompletePaths()
- .contains(ImmutableList.of(DUAL_HOME_CP_1_1, DUAL_HOME_CP_1_3, DUAL_HOME_CP_3_1, DUAL_HOME_CP_3_2)));
-
- }
-
-
- private StaticPacketTrace testSuccess(TrafficSelector packet, ConnectPoint in, DeviceId deviceId, ConnectPoint out,
- int paths, int outputs) {
- StaticPacketTrace traceSuccess = mngr.trace(packet, in);
-
- log.info("trace {}", traceSuccess);
-
- log.info("trace {}", traceSuccess.resultMessage());
-
- assertNotNull("trace should not be null", traceSuccess);
- assertEquals("Trace should have " + outputs + " output", outputs,
- traceSuccess.getGroupOuputs(deviceId).size());
- assertEquals("Trace should only have " + paths + "output", paths, traceSuccess.getCompletePaths().size());
- assertTrue("Trace should be successful",
- traceSuccess.resultMessage().contains("Reached required destination Host"));
- assertEquals("Incorrect Output CP", out,
- traceSuccess.getGroupOuputs(deviceId).get(0).getOutput());
-
- return traceSuccess;
- }
-
- private void testFailure(TrafficSelector packet, ConnectPoint in, DeviceId deviceId) {
- StaticPacketTrace traceFail = mngr.trace(packet, in);
-
- log.info("trace {}", traceFail.resultMessage());
-
- assertNotNull("Trace should not be null", traceFail);
- assertNull("Trace should have 0 output", traceFail.getGroupOuputs(deviceId));
- }
-
- private class TestFlowRuleService extends FlowNib {
- @Override
- public Iterable<FlowEntry> getFlowEntriesByState(DeviceId deviceId, FlowEntry.FlowEntryState state) {
- if (deviceId.equals(SINGLE_FLOW_DEVICE)) {
- return ImmutableList.of(SINGLE_FLOW_ENTRY);
- } else if (deviceId.equals(DUAL_FLOW_DEVICE)) {
- return ImmutableList.of(FIRST_FLOW_ENTRY, SECOND_FLOW_ENTRY);
- } else if (deviceId.equals(GROUP_FLOW_DEVICE)) {
- return ImmutableList.of(GROUP_FLOW_ENTRY);
- } else if (deviceId.equals(TOPO_FLOW_DEVICE) ||
- deviceId.equals(TOPO_FLOW_2_DEVICE) ||
- deviceId.equals(TOPO_FLOW_3_DEVICE) ||
- deviceId.equals(TOPO_FLOW_4_DEVICE)) {
- return ImmutableList.of(TOPO_SINGLE_FLOW_ENTRY, TOPO_SECOND_INPUT_FLOW_ENTRY);
- } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
- return ImmutableList.of(TOPO_GROUP_FLOW_ENTRY);
- } else if (deviceId.equals(HARDWARE_DEVICE)) {
- return ImmutableList.of(HARDWARE_ETH_FLOW_ENTRY, HARDWARE_FLOW_ENTRY);
- } else if (deviceId.equals(SAME_OUTPUT_FLOW_DEVICE)) {
- return ImmutableList.of(SAME_OUTPUT_FLOW_ENTRY);
- } else if (deviceId.equals(ARP_FLOW_DEVICE)) {
- return ImmutableList.of(ARP_FLOW_ENTRY);
- } else if (deviceId.equals(DUAL_LINK_1)) {
- return ImmutableList.of(DUAL_LINK_1_GROUP_FLOW_ENTRY);
- } else if (deviceId.equals(DUAL_LINK_2)) {
- return ImmutableList.of(DUAL_LINK_1_GROUP_FLOW_ENTRY, DUAL_LINK_2_GROUP_FLOW_ENTRY);
- } else if (deviceId.equals(DUAL_LINK_3)) {
- return ImmutableList.of(DUAL_LINK_3_FLOW_ENTRY, DUAL_LINK_3_FLOW_ENTRY_2);
- } else if (deviceId.equals(DEFERRED_1)) {
- return ImmutableList.of(DEFERRED_FLOW_ENTRY, DEFERRED_CLEAR_FLOW_ENTRY);
- } else if (deviceId.equals(HARDWARE_DEVICE_10)) {
- return ImmutableList.of(HARDWARE_10_FLOW_ENTRY, HARDWARE_10_SECOND_FLOW_ENTRY,
- HARDWARE_10_OUTPUT_FLOW_ENTRY);
- } else if (deviceId.equals(LLDP_FLOW_DEVICE)) {
- return ImmutableList.of(LLDP_FLOW_ENTRY);
- } else if (deviceId.equals(MULTICAST_GROUP_FLOW_DEVICE)) {
- return ImmutableList.of(MULTICAST_GROUP_FLOW_ENTRY);
- } else if (deviceId.equals(NO_BUCKET_DEVICE)) {
- return ImmutableList.of(NO_BUCKET_ENTRY);
- } else if (deviceId.equals(DUAL_HOME_DEVICE_1)) {
- return ImmutableList.of(DUAL_HOME_FLOW_ENTRY);
- } else if (deviceId.equals(DUAL_HOME_DEVICE_2) || deviceId.equals(DUAL_HOME_DEVICE_3)) {
- return ImmutableList.of(DUAL_HOME_OUT_FLOW_ENTRY);
- } else if (deviceId.equals(ACTION_ORDER_DEVICE)) {
- return ImmutableList.of(ACTION_ORDER_FLOW_ENTRY);
- }
- return ImmutableList.of();
- }
- }
-
- private class TestGroupService extends GroupNib {
- @Override
- public Iterable<Group> getGroups(DeviceId deviceId) {
- if (deviceId.equals(GROUP_FLOW_DEVICE)) {
- return ImmutableList.of(GROUP);
- } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
- return ImmutableList.of(TOPO_GROUP);
- } else if (deviceId.equals(DUAL_LINK_1) || deviceId.equals(DUAL_LINK_2)) {
- return ImmutableList.of(DUAL_LINK_GROUP);
- } else if (deviceId.equals(MULTICAST_GROUP_FLOW_DEVICE)) {
- return ImmutableList.of(MULTICAST_GROUP);
- } else if (deviceId.equals(NO_BUCKET_DEVICE)) {
- return ImmutableList.of(NO_BUCKET_GROUP);
- } else if (deviceId.equals(DUAL_HOME_DEVICE_1)) {
- return ImmutableList.of(DUAL_HOME_GROUP);
- } else if (deviceId.equals(ACTION_ORDER_DEVICE)) {
- return ImmutableList.of(ACTION_ORDER_GROUP);
- }
- return ImmutableList.of();
- }
- }
-
- private class TestHostService extends HostNib {
- @Override
- public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
- if (connectPoint.equals(TOPO_FLOW_3_OUT_CP)) {
- return ImmutableSet.of(H2);
- } else if (connectPoint.equals(DUAL_LINK_1_CP_2_OUT) || connectPoint.equals(DUAL_LINK_1_CP_3_OUT) ||
- connectPoint.equals(DUAL_LINK_2_CP_2_OUT) || connectPoint.equals(DUAL_LINK_2_CP_3_OUT)) {
- return ImmutableSet.of();
- }
- if (connectPoint.equals(SINGLE_FLOW_OUT_CP) ||
- connectPoint.equals(DUAL_FLOW_OUT_CP) ||
- connectPoint.equals(GROUP_FLOW_OUT_CP) ||
- connectPoint.equals(HARDWARE_DEVICE_OUT_CP) ||
- connectPoint.equals(HARDWARE_DEVICE_10_OUT_CP) ||
- connectPoint.equals(DEFERRED_CP_2_OUT) ||
- connectPoint.equals(DUAL_LINK_3_CP_3_OUT) ||
- connectPoint.equals(ACTION_ORDER_OUT_CP)) {
- return ImmutableSet.of(H1);
- }
- if (connectPoint.equals(DUAL_HOME_CP_2_2) || connectPoint.equals(DUAL_HOME_CP_3_2)) {
- return ImmutableSet.of(DUAL_HOME_H);
- }
- return ImmutableSet.of();
- }
-
- @Override
- public Set<Host> getHostsByMac(MacAddress mac) {
- if (mac.equals(H1.mac())) {
- return ImmutableSet.of(H1);
- } else if (mac.equals(H2.mac())) {
- return ImmutableSet.of(H2);
- } else if (mac.equals(DUAL_HOME_H.mac())) {
- return ImmutableSet.of(DUAL_HOME_H);
- }
- return ImmutableSet.of();
- }
-
- @Override
- public Set<Host> getHostsByIp(IpAddress ip) {
- if ((H1.ipAddresses().contains(ip))) {
- return ImmutableSet.of(H1);
- } else if ((H2.ipAddresses().contains(ip))) {
- return ImmutableSet.of(H2);
- } else if ((DUAL_HOME_H.ipAddresses().contains(ip))) {
- return ImmutableSet.of(DUAL_HOME_H);
- }
- return ImmutableSet.of();
- }
- }
-
- private class TestLinkService extends LinkNib {
- @Override
- public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
- if (connectPoint.equals(TOPO_FLOW_1_OUT_CP)
- || connectPoint.equals(TOPO_FLOW_OUT_CP_1)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(connectPoint)
- .dst(TOPO_FLOW_2_IN_CP)
- .build());
- } else if (connectPoint.equals(TOPO_FLOW_2_OUT_CP)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(TOPO_FLOW_2_OUT_CP)
- .dst(TOPO_FLOW_3_IN_CP)
- .build());
- } else if (connectPoint.equals(TOPO_FLOW_OUT_CP_2)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(TOPO_FLOW_OUT_CP_2)
- .dst(TOPO_FLOW_4_IN_CP)
- .build());
- } else if (connectPoint.equals(TOPO_FLOW_4_OUT_CP)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(TOPO_FLOW_4_OUT_CP)
- .dst(TOPO_FLOW_3_IN_2_CP)
- .build());
- } else if (connectPoint.equals(DUAL_LINK_1_CP_2_OUT)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(DUAL_LINK_1_CP_2_OUT)
- .dst(DUAL_LINK_2_CP_1_IN)
- .build());
- } else if (connectPoint.equals(DUAL_LINK_1_CP_3_OUT)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(DUAL_LINK_1_CP_3_OUT)
- .dst(DUAL_LINK_2_CP_4_IN)
- .build());
- } else if (connectPoint.equals(DUAL_LINK_2_CP_2_OUT)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(DUAL_LINK_2_CP_2_OUT)
- .dst(DUAL_LINK_3_CP_1_IN)
- .build());
- } else if (connectPoint.equals(DUAL_LINK_2_CP_3_OUT)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(DUAL_LINK_2_CP_3_OUT)
- .dst(DUAL_LINK_3_CP_2_IN)
- .build());
- } else if (connectPoint.equals(DUAL_HOME_CP_1_2)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(DUAL_HOME_CP_1_2)
- .dst(DUAL_HOME_CP_2_1)
- .build());
- } else if (connectPoint.equals(DUAL_HOME_CP_1_3)) {
- return ImmutableSet.of(DefaultLink.builder()
- .providerId(ProviderId.NONE)
- .type(Link.Type.DIRECT)
- .src(DUAL_HOME_CP_1_3)
- .dst(DUAL_HOME_CP_3_1)
- .build());
- }
- return ImmutableSet.of();
- }
- }
-
- private class TestDeviceService extends DeviceNib {
- @Override
- public Device getDevice(DeviceId deviceId) {
- if (deviceId.equals(DeviceId.deviceId("nonexistent"))) {
- return null;
- }
- return new DefaultDevice(ProviderId.NONE, DeviceId.deviceId("test"), SWITCH,
- "test", "test", "test", "test", new ChassisId(),
- DefaultAnnotations.builder().set("foo", "bar").build());
- }
-
- @Override
- public Port getPort(ConnectPoint cp) {
- return new DefaultPort(null, cp.port(), true, DefaultAnnotations.builder().build());
- }
-
- @Override
- public boolean isAvailable(DeviceId deviceId) {
- return !deviceId.equals(OFFLINE_DEVICE);
- }
- }
-
- private class TestDriverService extends DriverNib {
- @Override
- public String getDriverName(DeviceId deviceId) {
- if (deviceId.equals(HARDWARE_DEVICE) || deviceId.equals(HARDWARE_DEVICE_10)) {
- return "ofdpa";
- }
- return "NotHWDriver";
- }
- }
-
- private class TestMastershipService extends MastershipNib {
- @Override
- public NodeId getMasterFor(DeviceId deviceId) {
- return NodeId.nodeId(MASTER_1);
- }
- }
-
- private class TestEdgePortService extends EdgePortNib {
- @Override
- public boolean isEdgePoint(ConnectPoint point) {
- return point.equals(MULTICAST_OUT_CP) ||
- point.equals(MULTICAST_OUT_CP_2);
- }
- }
-
- private class TestRouteService extends RouteNib {
- @Override
- public Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip) {
- return Optional.empty();
- }
- }
-
-}
\ No newline at end of file
diff --git a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootUtilsTest.java b/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootUtilsTest.java
deleted file mode 100644
index c8195c0..0000000
--- a/apps/t3/app/src/test/java/org/onosproject/t3/impl/TroubleshootUtilsTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.t3.impl;
-
-import org.junit.Test;
-import org.onlab.packet.MacAddress;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test for util methods of the Trellis Troubleshoot Toolkit.
- */
-public class TroubleshootUtilsTest {
-
- @Test
- public void testMacMatch() {
-
- MacAddress min = MacAddress.valueOf("01:00:5E:00:00:00");
- MacAddress mask = MacAddress.valueOf("FF:FF:FF:80:00:00");
- MacAddress macOk = MacAddress.valueOf("01:00:5E:00:00:01");
-
- assertTrue("False on correct match", TroubleshootUtils.compareMac(macOk, min, mask));
-
- MacAddress macWrong = MacAddress.valueOf("01:00:5E:80:00:00");
-
- assertFalse("True on false match", TroubleshootUtils.compareMac(macWrong, min, mask));
-
- MacAddress maskEmpty = MacAddress.valueOf("00:00:00:00:00:00");
-
- assertTrue("False on empty Mask", TroubleshootUtils.compareMac(macOk, min, maskEmpty));
-
- MacAddress maskFull = MacAddress.valueOf("FF:FF:FF:FF:FF:FF");
-
- assertFalse("True on full Mask", TroubleshootUtils.compareMac(macOk, min, maskFull));
-
- }
-}
\ No newline at end of file
diff --git a/apps/t3/web/BUILD b/apps/t3/web/BUILD
deleted file mode 100644
index 0fd733f..0000000
--- a/apps/t3/web/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-COMPILE_DEPS = CORE_DEPS + KRYO + JACKSON + REST + CLI + [
- "@jersey_server//jar",
- "//apps/t3/app:onos-apps-t3-app",
-]
-
-osgi_jar(
- api_description = "REST API for T3",
- api_package = "org.onosproject.t3.rest",
- api_title = "T3 REST API",
- api_version = "1.0",
- web_context = "/onos/v1/t3",
- deps = COMPILE_DEPS,
-)
diff --git a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebApplication.java b/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebApplication.java
deleted file mode 100644
index 5f6a548..0000000
--- a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebApplication.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.rest;
-
-
-import org.onlab.rest.AbstractWebApplication;
-
-import java.util.Set;
-
-public class T3WebApplication extends AbstractWebApplication {
- @Override
- public Set<Class<?>> getClasses() {
- return getClasses(T3WebResource.class);
- }
-
-}
diff --git a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebResource.java b/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebResource.java
deleted file mode 100644
index 275be8c..0000000
--- a/apps/t3/web/src/main/java/org/onosproject/t3/rest/T3WebResource.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.t3.rest;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.onlab.packet.EthType;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.HostId;
-import org.onosproject.net.flow.FlowEntry;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.group.Group;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.t3.api.GroupsInDevice;
-import org.onosproject.t3.api.StaticPacketTrace;
-import org.onosproject.t3.api.TroubleshootService;
-import org.slf4j.Logger;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Trellis Troubleshooting Tool REST API.
- */
-@Path("t3")
-public class T3WebResource extends AbstractWebResource {
- private final ObjectMapper mapper = new ObjectMapper();
- private static final Logger LOG = getLogger(T3WebResource.class);
-
- /**
- * Returns the trace non verbose result for the given source and destination ips.
- *
- * @param srcHost source ip identifier
- * @param dstHost destination ip identifier
- * @param ethType ethernet type identifier
- * @return 200 OK with component properties of given component and variable
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("simple/{srcHost}/{dstHost}/{ethType}")
- public Response getT3Simple(@PathParam("srcHost") String srcHost, @PathParam("dstHost") String dstHost,
- @PathParam("ethType") String ethType) {
-
- ObjectNode node;
- try {
- node = getT3JsonOutput(srcHost, dstHost, ethType, false);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException(e);
- }
- return Response.status(200).entity(node).build();
-
- }
-
- /**
- * Returns the trace verbose result for the given source and destination ips.
- *
- * @param srcHost source ip identifier
- * @param dstHost destination ip identifier
- * @param ethType ethernet type identifier
- * @return 200 OK with component properties of given component and variable
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("simple/{srcHost}/{dstHost}/{ethType}/verbose")
- public Response getT3SimpleVerbose(@PathParam("srcHost") String srcHost, @PathParam("dstHost") String dstHost,
- @PathParam("ethType") String ethType) {
-
- ObjectNode node;
- try {
- node = getT3JsonOutput(srcHost, dstHost, ethType, true);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException(e);
- }
- return Response.status(200).entity(node).build();
- }
-
- /**
- * Returns the mcast trace non verbose result.
- *
- * @return 200 OK
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("mcast")
- public Response getT3Mcast() {
- ObjectNode node = null;
- try {
- node = getT3McastJsonOutput(false);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException(e);
- }
- return Response.status(200).entity(node).build();
- }
-
- /**
- * Returns the mcast trace verbose result.
- *
- * @return 200 OK
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Path("mcast/verbose")
- public Response getT3McastVerbose() {
- ObjectNode node;
- try {
- node = getT3McastJsonOutput(true);
-
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException(e);
- }
- return Response.status(200).entity(node).build();
- }
-
- /**
- * Returns trace verbose or non verbose json output for the given trace.
- *
- * @param verbose based on verbosity level
- * @return a json representing the trace.
- */
- private ObjectNode getT3McastJsonOutput(boolean verbose) {
- TroubleshootService troubleshootService = get(TroubleshootService.class);
- final ObjectNode nodeOutput = mapper.createObjectNode();
- nodeOutput.put("title", "Tracing all Multicast routes in the System");
-
- //Create the generator for the list of traces.
- List<Set<StaticPacketTrace>> generator = troubleshootService.getMulitcastTrace(VlanId.vlanId("None"));
- int totalTraces = 0;
- List<StaticPacketTrace> failedTraces = new ArrayList<>();
- StaticPacketTrace previousTrace = null;
- ArrayNode traceArray = mapper.createArrayNode();
- for (Set<StaticPacketTrace> traces : generator) {
- ObjectNode genNode = mapper.createObjectNode();
- totalTraces++;
- //Print also Route if possible or packet
- ArrayNode traceOutput = mapper.createArrayNode();
- if (verbose) {
- traces.forEach(trace -> {
- ObjectNode traceObj = mapper.createObjectNode();
- ArrayNode node = mapper.createArrayNode();
- for (Criterion packet : trace.getInitialPacket().criteria()) {
- node.add(packet.toString());
- }
- traceObj.set("input packet", node);
- traceObj.set("trace", getTraceJson(trace, verbose));
- traceOutput.add(traceObj);
- });
- } else {
- for (StaticPacketTrace trace : traces) {
- ObjectNode traceObject = mapper.createObjectNode();
- traceObject.set("trace", traceNode(previousTrace, trace));
- if (previousTrace == null || !previousTrace.equals(trace)) {
- previousTrace = trace;
- }
- traceObject.put("result", trace.isSuccess());
- if (!trace.isSuccess()) {
- traceObject.put("reason", trace.resultMessage());
- failedTraces.add(trace);
- }
- traceOutput.add(traceObject);
- }
- }
- genNode.set("traces", traceOutput);
- traceArray.add(genNode);
- }
- nodeOutput.set("tracing packet", traceArray);
-
- if (!verbose) {
- if (failedTraces.size() != 0) {
- nodeOutput.put("failed traces", failedTraces.size());
- }
- previousTrace = null;
- for (StaticPacketTrace trace : failedTraces) {
- if (previousTrace == null || !previousTrace.equals(trace)) {
- previousTrace = trace;
- }
- nodeOutput.set("trace", traceNode(previousTrace, trace));
- if (trace != null) {
- nodeOutput.put("failure", trace.resultMessage());
- }
- }
- nodeOutput.put("total traces", totalTraces);
- nodeOutput.put("errors", failedTraces.size());
- }
- return nodeOutput;
- }
-
- /**
- * Returns verbose or non verbose json output for the given trace. *
- *
- * @param previousTrace the trace
- * @param trace based on verbosity level
- * @return a json representing the trace.
- */
- private ObjectNode traceNode(StaticPacketTrace previousTrace, StaticPacketTrace trace) {
- ObjectNode obj = mapper.createObjectNode();
- if (previousTrace == null || !previousTrace.equals(trace)) {
- previousTrace = trace;
- ConnectPoint initialConnectPoint = trace.getInitialConnectPoint();
- TrafficSelector initialPacket = trace.getInitialPacket();
- boolean isIPv4 = ((EthTypeCriterion) initialPacket.getCriterion(Criterion.Type.ETH_TYPE))
- .ethType().equals(EthType.EtherType.IPV4.ethType()
- );
- IpPrefix group = ((IPCriterion) (isIPv4 ? trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV4_DST) : trace.getInitialPacket()
- .getCriterion(Criterion.Type.IPV6_DST))).ip();
- obj.put("source", initialConnectPoint.toString());
- obj.put("group", group.toString());
- }
- ArrayNode nodePath = mapper.createArrayNode();
- for (List<ConnectPoint> listPaths : trace.getCompletePaths()) {
- nodePath.add(listPaths.get(listPaths.size() - 1).toString());
- }
- if (trace.getCompletePaths().size() > 1) {
- obj.set("sinks", nodePath);
- } else {
- obj.set("sink", nodePath);
- }
- return obj;
- }
-
- /**
- * Returns trace verbose or non verbose json output for the given trace.
- *
- * @param srcHost source ip identifier
- * @param dstHost destination ip identifier
- * @param ethType the ethernet Type
- * @param verbose based on verbosity level
- * @return a json representing the trace.
- */
- private ObjectNode getT3JsonOutput(String srcHost, String dstHost, String ethType, Boolean verbose) {
- TroubleshootService troubleshootService = get(TroubleshootService.class);
- final ObjectNode nodeOutput = mapper.createObjectNode();
- //Tracing between host ips
- ArrayNode ipList = mapper.createArrayNode();
- ipList.add(srcHost);
- ipList.add(dstHost);
- nodeOutput.set("hostIps ", ipList);
- EthType.EtherType type = EthType.EtherType.valueOf(ethType.toUpperCase());
-
- //Build the traces
- Set<StaticPacketTrace> traces = troubleshootService.trace(HostId.hostId(srcHost), HostId.hostId(dstHost), type);
- traces.forEach(trace -> {
-
- if (trace.getInitialPacket() != null) {
- ArrayNode node = mapper.createArrayNode();
- for (Criterion packet : trace.getInitialPacket().criteria()) {
- node.add(packet.toString());
- }
- nodeOutput.set("input packet", node);
- nodeOutput.set("trace", getTraceJson(trace, verbose));
- } else {
- LOG.debug("cannot obtain trace between: ", srcHost, dstHost);
- nodeOutput.set("failed trace", ipList);
- nodeOutput.put("reason", trace.resultMessage());
- }
- });
- return nodeOutput;
- }
-
- /**
- * Returns verbose or non verbose json output for the given trace. *
- *
- * @param trace the trace
- * @param verbosity based on verbosity level
- * @return a json representing the trace.
- */
- public ObjectNode getTraceJson(StaticPacketTrace trace, boolean verbosity) {
- ObjectNode nodeOutput = mapper.createObjectNode();
- if (verbosity) {
- nodeOutput.set("trace", getTrace(trace, verbosity));
- } else {
- ArrayNode nodePath = mapper.createArrayNode();
- for (List<ConnectPoint> listPaths : trace.getCompletePaths()) {
- ArrayNode node = mapper.createArrayNode();
- for (ConnectPoint path : listPaths) {
- node.add(path.toString());
- }
- nodePath.add(node);
- }
- nodeOutput.set("paths", nodePath);
- }
-
- nodeOutput.put("result", trace.resultMessage());
- return nodeOutput;
- }
-
- /**
- * Returns verbose json output for the given trace. *
- *
- * @param trace the trace
- * @return a json representing the trace.
- */
- private ObjectNode getTrace(StaticPacketTrace trace, boolean verbose) {
-
- ObjectNode nodeOutput = mapper.createObjectNode();
-
- List<List<ConnectPoint>> paths = trace.getCompletePaths();
- ArrayNode nodePath = mapper.createArrayNode();
- for (List<ConnectPoint> path : paths) {
- ArrayNode pathNode = mapper.createArrayNode();
- for (ConnectPoint pathItr : path) {
- pathNode.add(pathItr.toString());
- }
- nodePath.add(pathNode);
-
- ConnectPoint previous = null;
-
- if (path.size() == 1) {
- ConnectPoint connectPoint = path.get(0);
- nodeOutput.put("device", connectPoint.deviceId().toString());
- nodeOutput.put("input", connectPoint.toString());
- nodeOutput.put("flowCount", trace.getFlowsForDevice(connectPoint.deviceId()).size());
- nodeOutput.set("flows", getFlowArray(trace, connectPoint, verbose));
-
- List<GroupsInDevice> groupsInDevice = trace.getGroupOuputs(connectPoint.deviceId());
-
- if (groupsInDevice != null) {
- groupsInDevice.forEach(output -> {
- nodeOutput.set("groups", getGroupObj(connectPoint, output, verbose));
- });
- }
-
- } else {
- for (ConnectPoint connectPoint : path) {
- if (previous == null || !previous.deviceId().equals(connectPoint.deviceId())) {
- nodeOutput.put("device", connectPoint.deviceId().toString());
- nodeOutput.put("input", connectPoint.toString());
- nodeOutput.put("flows", trace.getFlowsForDevice(connectPoint.deviceId()).size());
- nodeOutput.put("verbose", verbose);
- nodeOutput.set("flows", getFlowArray(trace, connectPoint, verbose));
- } else {
- List<GroupsInDevice> groupsInDevice = trace.getGroupOuputs(connectPoint.deviceId());
- if (groupsInDevice != null) {
- groupsInDevice.forEach(output -> {
- nodeOutput.set("groups", getGroupObj(connectPoint, output, verbose));
- });
-
- }
-
- }
- previous = connectPoint;
- }
- }
- }
- nodeOutput.set("path", nodePath);
- return nodeOutput;
- }
-
- //Return groups Object for a given trace and a specified level of verbosity
- private ObjectNode getGroupObj(ConnectPoint connectPoint, GroupsInDevice output, boolean verbose) {
- ArrayNode groupArray = mapper.createArrayNode();
- ObjectNode groupsObj = mapper.createObjectNode();
- if (output.getOutput().equals(connectPoint)) {
- output.getGroups().forEach(group -> {
- ObjectNode groups = mapper.createObjectNode();
- if (verbose) {
- groups = codec(Group.class).encode(group, this);
- } else {
- groups.put("groupId", group.id().toString());
- }
- groupArray.add(groups);
- });
- ArrayNode node = mapper.createArrayNode();
- for (Criterion packet : output.getFinalPacket().criteria()) {
- node.add(packet.toString());
- }
- groupsObj.set("outgoing packet", node);
- }
- groupsObj.set("groups", groupArray);
- return groupsObj;
- }
-
- //Return flows Object for a given trace and a specified level of verbosity
- private ArrayNode getFlowArray(StaticPacketTrace trace, ConnectPoint connectPoint, boolean verbose) {
- ArrayNode flowArray = mapper.createArrayNode();
- trace.getFlowsForDevice(connectPoint.deviceId()).forEach(f -> {
- ObjectNode flows = mapper.createObjectNode();
- if (verbose) {
- flows = codec(FlowEntry.class).encode(f, this);
- } else {
- flows.put("flowId: ", f.id().toString());
- flows.put("table: ", f.table().toString());
- flows.put("selector: ", f.selector().criteria().toString());
- }
- flowArray.add(flows);
- });
- return flowArray;
- }
-
-}
diff --git a/apps/t3/web/src/main/java/org/onosproject/t3/rest/package-info.java b/apps/t3/web/src/main/java/org/onosproject/t3/rest/package-info.java
deleted file mode 100644
index e390f3e..0000000
--- a/apps/t3/web/src/main/java/org/onosproject/t3/rest/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Troubleshooting toolkit for trellis fabrics implementation.
- */
-package org.onosproject.t3.rest;
diff --git a/apps/t3/web/src/main/webapp/WEB-INF/web.xml b/apps/t3/web/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 9bed969..0000000
--- a/apps/t3/web/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright 2018-present Open Networking Foundation
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- id="ONOS" version="2.5">
- <display-name>T3 REST API v1.0</display-name>
-
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>Secured</web-resource-name>
- <url-pattern>/*</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>admin</role-name>
- <role-name>viewer</role-name>
- </auth-constraint>
- </security-constraint>
-
- <security-role>
- <role-name>admin</role-name>
- <role-name>viewer</role-name>
- </security-role>
-
- <login-config>
- <auth-method>BASIC</auth-method>
- <realm-name>karaf</realm-name>
- </login-config>
-
- <servlet>
- <servlet-name>JAX-RS Service</servlet-name>
- <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
- <init-param>
- <param-name>javax.ws.rs.Application</param-name>
- <param-value>org.onosproject.t3.rest.T3WebApplication</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>JAX-RS Service</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-</web-app>
diff --git a/tools/build/bazel/modules.bzl b/tools/build/bazel/modules.bzl
index c1c3e0a..e9386db 100644
--- a/tools/build/bazel/modules.bzl
+++ b/tools/build/bazel/modules.bzl
@@ -289,9 +289,7 @@
"//apps/routing/fpm:onos-apps-routing-fpm-oar": [],
"//apps/scalablegateway:onos-apps-scalablegateway-oar": [],
"//apps/sdnip:onos-apps-sdnip-oar": [],
- "//apps/segmentrouting:onos-apps-segmentrouting-oar": ["seba"],
"//apps/simplefabric:onos-apps-simplefabric-oar": [],
- "//apps/t3:onos-apps-t3-oar": [],
# "//apps/tenbi:onos-apps-tenbi-oar": [],
# "//apps/tenbi/yangmodel:onos-apps-tenbi-yangmodel-feature": [],
"//apps/test/cluster-ha:onos-apps-test-cluster-ha-oar": [],