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 index d951b53033..b9912accad 100644 --- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java +++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java @@ -15,8 +15,6 @@ */ package org.onosproject.segmentrouting; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; @@ -94,7 +92,6 @@ 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.PwaasConfig; import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig; import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig; import org.onosproject.segmentrouting.config.XConnectConfig; @@ -104,9 +101,13 @@ import org.onosproject.segmentrouting.grouphandler.NextNeighbors; import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel; import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelHandler; import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy; +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 org.onosproject.segmentrouting.storekey.McastStoreKey; import org.onosproject.segmentrouting.storekey.PortNextObjectiveStoreKey; @@ -142,6 +143,7 @@ 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.pwaas.PwaasUtil.configurationValidity; /** * Segment routing manager. @@ -234,7 +236,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { private RouteHandler routeHandler = null; LinkHandler linkHandler = null; private SegmentRoutingNeighbourDispatcher neighbourHandler = null; - private L2TunnelHandler l2TunnelHandler = null; + private DefaultL2TunnelHandler l2TunnelHandler = null; private InternalEventHandler eventHandler = new InternalEventHandler(); private final InternalHostListener hostListener = new InternalHostListener(); private final InternalConfigListener cfgListener = new InternalConfigListener(this); @@ -314,16 +316,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { } }; - private final ConfigFactory pwaasConfigFactory = - new ConfigFactory( - SubjectFactories.APP_SUBJECT_FACTORY, - PwaasConfig.class, "pwaas") { - @Override - public PwaasConfig createConfig() { - return new PwaasConfig(); - } - }; - private static final Object THREAD_SCHED_LOCK = new Object(); private static int numOfEventsQueued = 0; private static int numOfEventsExecuted = 0; @@ -430,7 +422,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { cfgService.registerConfigFactory(appConfigFactory); cfgService.registerConfigFactory(xConnectConfigFactory); cfgService.registerConfigFactory(mcastConfigFactory); - cfgService.registerConfigFactory(pwaasConfigFactory); log.info("Configuring network before adding listeners"); cfgListener.configureNetwork(); @@ -474,7 +465,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { cfgService.unregisterConfigFactory(appConfigFactory); cfgService.unregisterConfigFactory(xConnectConfigFactory); cfgService.unregisterConfigFactory(mcastConfigFactory); - cfgService.unregisterConfigFactory(pwaasConfigFactory); compCfgService.unregisterProperties(getClass(), false); hostService.removeListener(hostListener); @@ -567,55 +557,90 @@ public class SegmentRoutingManager implements SegmentRoutingService { } @Override - public L2TunnelHandler.Result addPseudowire(String tunnelId, String pwLabel, String cP1, - String cP1InnerVlan, String cP1OuterVlan, String cP2, - String cP2InnerVlan, String cP2OuterVlan, - String mode, String sdTag) { - // Try to inject an empty Pwaas config if it is not found for the first time - PwaasConfig config = cfgService.getConfig(appId(), PwaasConfig.class); - if (config == null) { - log.debug("Pwaas config not found. Try to create an empty one."); - cfgService.applyConfig(appId(), PwaasConfig.class, new ObjectMapper().createObjectNode()); - config = cfgService.getConfig(appId(), PwaasConfig.class); + public L2TunnelHandler.Result addPseudowire(L2TunnelDescription l2TunnelDescription) { + + List tunnels = getL2Tunnels(); + List policies = getL2Policies(); + + // combine polices and tunnels to pseudowires + List pseudowires = 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.toList()); + + + // creating a new list with the new pseudowire + Set newPseudowires = new HashSet<>(pseudowires); + + // corner case where we try to add the exact same pseudowire + if (newPseudowires.contains(l2TunnelDescription)) { + log.info("Pseudowire with {} already exists!", l2TunnelDescription); + return L2TunnelHandler.Result.SUCCESS; } - ObjectNode object = config.addPseudowire(tunnelId, pwLabel, - cP1, cP1InnerVlan, cP1OuterVlan, - cP2, cP2InnerVlan, cP2OuterVlan, - mode, sdTag); - if (object == null) { - log.warn("Could not add pseudowire to the configuration!"); + // add the new pseudowire to the Set + newPseudowires.add(l2TunnelDescription); + + // validate the new set of pseudowires + boolean res = configurationValidity(newPseudowires); + if (res) { + + // deploy a set with ONLY the new pseudowire + newPseudowires = new HashSet<>(); + newPseudowires.add(l2TunnelDescription); + l2TunnelHandler.deploy(newPseudowires); + + log.info("Pseudowire with {} deployment started, check log for any errors in this process!", + l2TunnelDescription.l2Tunnel().tunnelId()); + return L2TunnelHandler.Result.SUCCESS; + } else { + + log.error("Pseudowire with {} can not be added!", l2TunnelDescription.l2Tunnel().tunnelId()); return L2TunnelHandler.Result.ADDITION_ERROR; } - - // inform everyone about the valid change in the pw configuration - cfgService.applyConfig(appId(), PwaasConfig.class, object); - return L2TunnelHandler.Result.SUCCESS; } @Override - public L2TunnelHandler.Result removePseudowire(String pwId) { + public L2TunnelHandler.Result removePseudowire(Integer pwId) { - PwaasConfig config = cfgService.getConfig(appId(), PwaasConfig.class); - if (config == null) { - log.warn("Configuration for Pwaas class could not be found!"); - return L2TunnelHandler.Result.CONFIG_NOT_FOUND; - } + List tunnels = getL2Tunnels(); + List policies = getL2Policies(); - ObjectNode object = config.removePseudowire(pwId); - if (object == null) { - log.warn("Could not delete pseudowire from configuration!"); + // get the pseudowire, if it exists + List pseudowires = tunnels.stream().map(l2Tunnel -> { + L2TunnelPolicy policy = null; + for (L2TunnelPolicy l2Policy : policies) { + if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) { + policy = l2Policy; + break; + } + } + + return new DefaultL2TunnelDescription(l2Tunnel, policy); + }).filter(l2desc -> + l2desc.l2Tunnel().tunnelId() == pwId + ).collect(Collectors.toList()); + + if (pseudowires.size() == 0) { + log.error("Pseudowire with id {} does not exist", pwId); return L2TunnelHandler.Result.REMOVAL_ERROR; + } else { + + l2TunnelHandler.tearDown(new HashSet<>(pseudowires)); + + log.info("Removal of pseudowire with {} started, check log for any errors in this process!", + pwId); + return L2TunnelHandler.Result.SUCCESS; } - - // sanity check, this should never fail since we removed a pw - // and we always check when we update the configuration - config.isValid(); - - // inform everyone - cfgService.applyConfig(appId(), PwaasConfig.class, object); - - return L2TunnelHandler.Result.SUCCESS; } @Override @@ -1411,21 +1436,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { default: break; } - } else if (event.configClass().equals(PwaasConfig.class)) { - checkState(l2TunnelHandler != null, "DefaultL2TunnelHandler is not initialized"); - switch (event.type()) { - case CONFIG_ADDED: - l2TunnelHandler.processPwaasConfigAdded(event); - break; - case CONFIG_UPDATED: - l2TunnelHandler.processPwaasConfigUpdated(event); - break; - case CONFIG_REMOVED: - l2TunnelHandler.processPwaasConfigRemoved(event); - break; - default: - break; - } } } @@ -1440,8 +1450,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { if (!event.configClass().equals(SegmentRoutingDeviceConfig.class) && !event.configClass().equals(SegmentRoutingAppConfig.class) && !event.configClass().equals(InterfaceConfig.class) && - !event.configClass().equals(XConnectConfig.class) && - !event.configClass().equals(PwaasConfig.class)) { + !event.configClass().equals(XConnectConfig.class)) { log.debug("Ignore event {} due to class mismatch", event); return false; } 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 index 6f115e4f09..fa7b7d643e 100644 --- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java +++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java @@ -25,6 +25,7 @@ import org.onosproject.segmentrouting.grouphandler.NextNeighbors; 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; @@ -101,33 +102,20 @@ public interface SegmentRoutingService { List getL2Policies(); /** - * Removes pw. Essentially updates configuration for PwaasConfig - * and sends event for removal. The rest are handled by DefaultL2TunnelHandler + * Removes pseudowire. Used ONLY by the REST api. * - * @param pwId The pseudowire id + * @param pwId The id of the pseudowire. * @return SUCCESS if operation successful or a descriptive error otherwise. */ - L2TunnelHandler.Result removePseudowire(String pwId); + L2TunnelHandler.Result removePseudowire(Integer pwId); /** * Adds a Pseudowire to the configuration. * - * @param tunnelId The pseudowire id - * @param pwLabel Pw label - * @param cP1 Connection Point 1 of pw - * @param cP1InnerVlan Outer vlan of cp2 - * @param cP1OuterVlan Outer vlan of cp1 - * @param cP2 Connection Point 2 of pw - * @param cP2InnerVlan Inner vlan of cp2 - * @param cP2OuterVlan Outer vlan of cp1 - * @param mode Mode of pw - * @param sdTag Service Delimiting tag of pw + * @param tunnel The pseudowire tunnel. * @return SUCCESS if operation is successful or a descriptive error otherwise. */ - L2TunnelHandler.Result addPseudowire(String tunnelId, String pwLabel, String cP1, - String cP1InnerVlan, String cP1OuterVlan, String cP2, - String cP2InnerVlan, String cP2OuterVlan, - String mode, String sdTag); + L2TunnelHandler.Result addPseudowire(L2TunnelDescription tunnel); /** * Creates a policy. 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 index d9168237c9..ab80affebf 100644 --- 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 @@ -19,8 +19,17 @@ package org.onosproject.segmentrouting.cli; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; 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.*; /** @@ -86,16 +95,36 @@ public class PseudowireAddCommand extends AbstractShellCommand { SegmentRoutingService srService = AbstractShellCommand.get(SegmentRoutingService.class); - L2TunnelHandler.Result res = srService.addPseudowire(pwId, pwLabel, - cP1, cP1InnerVlan, cP1OuterVlan, - cP2, cP2InnerVlan, cP2OuterVlan, - mode, sDTag); + L2Tunnel tun; + L2TunnelPolicy policy; + + try { + tun = new DefaultL2Tunnel(parseMode(mode), parseVlan(sDTag), parsePwId(pwId), parsePWLabel(pwLabel)); + } catch (Exception e) { + print("Exception while parsing L2Tunnel : {}", e); + return; + } + + try { + policy = new DefaultL2TunnelPolicy(parsePwId(pwId), + ConnectPoint.deviceConnectPoint(cP1), parseVlan(cP1InnerVlan), + parseVlan(cP1OuterVlan), ConnectPoint.deviceConnectPoint(cP2), + parseVlan(cP2InnerVlan), parseVlan(cP2OuterVlan)); + + } catch (Exception e) { + print("Exception while parsing L2TunnelPolicy : {}", e); + return; + } + + L2TunnelDescription pw = new DefaultL2TunnelDescription(tun, policy); + L2TunnelHandler.Result res = srService.addPseudowire(pw); + switch (res) { case ADDITION_ERROR: - print("Pseudowire could not be added, error in configuration, please check logs for more details!"); + print("Pseudowire could not be added, please check logs for more details!"); break; - case CONFIG_NOT_FOUND: - print("Configuration for pwaas was not found! Initialize the configuration first through netcfg."); + case SUCCESS: + print("Pseudowire was added succesfully!"); break; default: break; 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 index 098bbf9d94..0f027b2596 100644 --- 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 @@ -23,6 +23,8 @@ 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. @@ -44,8 +46,15 @@ public class PseudowireRemoveCommand extends AbstractShellCommand { // remove the pseudowire SegmentRoutingManager mngr = (SegmentRoutingManager) srService; - L2TunnelHandler.Result res = mngr.removePseudowire(pwId); + int pwIntId; + try { + pwIntId = parsePwId(pwId); + } catch (Exception e) { + print("Exception while parsing pseudowire id : {}", e); + return; + } + L2TunnelHandler.Result res = mngr.removePseudowire(pwIntId); switch (res) { case REMOVAL_ERROR: error("Error in deletion, pseudowire not found!"); 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 index 2dc9de2504..4b3272de33 100644 --- 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 @@ -30,7 +30,6 @@ import org.onosproject.net.DeviceId; import org.onosproject.net.Link; import org.onosproject.net.Path; import org.onosproject.net.PortNumber; -import org.onosproject.net.config.NetworkConfigEvent; import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficSelector; @@ -49,7 +48,6 @@ import org.onosproject.net.flowobjective.ObjectiveError; import org.onosproject.segmentrouting.SegmentRoutingManager; import org.onosproject.segmentrouting.SegmentRoutingService; import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; -import org.onosproject.segmentrouting.config.PwaasConfig; import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.service.ConsistentMap; import org.onosproject.store.service.DistributedSet; @@ -64,7 +62,6 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import static com.google.common.base.Preconditions.checkArgument; 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; @@ -168,28 +165,14 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { } /** - * Deploys any pre-existing pseudowires in the configuration. * Used by manager only in initialization. */ @Override public void init() { - - PwaasConfig config = srManager.cfgService.getConfig(srManager.appId(), PwaasConfig.class); - if (config == null) { - return; - } - - log.info("Deploying existing pseudowires"); - - // gather pseudowires - Set pwToAdd = config - .getPwIds() - .stream() - .map(config::getPwDescription) - .collect(Collectors.toSet()); - - // deploy pseudowires - deploy(pwToAdd); + // 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. } /** @@ -254,25 +237,6 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { pwToUpdate.forEach(tun -> updatePw(tun, tun)); } - @Override - public void processPwaasConfigAdded(NetworkConfigEvent event) { - checkArgument(event.config().isPresent(), - "Config is not presented in PwaasConfigAdded event {}", event); - - log.info("Network event : Pseudowire configuration added!"); - PwaasConfig config = (PwaasConfig) event.config().get(); - - // gather pseudowires - Set pwToAdd = config - .getPwIds() - .stream() - .map(config::getPwDescription) - .collect(Collectors.toSet()); - - // deploy pseudowires - deploy(pwToAdd); - } - /** * Returns the new vlan id for an ingress point of a * pseudowire. For double tagged, it is the outer, @@ -334,10 +298,7 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { } /** - * Adds a single pseudowire from leaf to a leaf. - * This method can be called from cli commands - * without configuration updates, thus it does not check for mastership - * of the ingress pseudowire device. + * Adds a single pseudowire. * * @param pw The pseudowire * @param spinePw True if pseudowire is from leaf to spine @@ -490,15 +451,10 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { /** * To deploy a number of pseudo wires. - *

- * Called ONLY when configuration changes, thus the check - * for the mastership of the device. - *

- * Only the master of CP1 will deploy this pseudowire. * * @param pwToAdd the set of pseudo wires to add */ - private void deploy(Set pwToAdd) { + public void deploy(Set pwToAdd) { Result result; @@ -507,11 +463,6 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2(); long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId(); - // only the master of CP1 will program this pseudowire - if (!srManager.isMasterOf(cp1)) { - log.debug("Not the master of {}. Ignore pseudo wire deployment id={}", cp1, tunnelId); - continue; - } try { // differentiate between leaf-leaf pseudowires and leaf-spine @@ -550,57 +501,6 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { } } - - @Override - public void processPwaasConfigUpdated(NetworkConfigEvent event) { - checkArgument(event.config().isPresent(), - "Config is not presented in PwaasConfigUpdated event {}", event); - checkArgument(event.prevConfig().isPresent(), - "PrevConfig is not presented in PwaasConfigUpdated event {}", event); - - log.info("Pseudowire configuration updated."); - - // We retrieve the old pseudo wires. - PwaasConfig prevConfig = (PwaasConfig) event.prevConfig().get(); - Set prevPws = prevConfig.getPwIds(); - - // We retrieve the new pseudo wires. - PwaasConfig config = (PwaasConfig) event.config().get(); - Set newPws = config.getPwIds(); - - // We compute the pseudo wires to update. - Set updPws = newPws.stream() - .filter(tunnelId -> prevPws.contains(tunnelId) - && !config.getPwDescription(tunnelId).equals(prevConfig.getPwDescription(tunnelId))) - .collect(Collectors.toSet()); - - // The pseudo wires to remove. - Set rmvPWs = prevPws.stream() - .filter(tunnelId -> !newPws.contains(tunnelId)).collect(Collectors.toSet()); - - Set pwToRemove = rmvPWs.stream() - .map(prevConfig::getPwDescription) - .collect(Collectors.toSet()); - tearDown(pwToRemove); - - // The pseudo wires to add. - Set addedPWs = newPws.stream() - .filter(tunnelId -> !prevPws.contains(tunnelId)) - .collect(Collectors.toSet()); - Set pwToAdd = addedPWs.stream() - .map(config::getPwDescription) - .collect(Collectors.toSet()); - deploy(pwToAdd); - - - // The pseudo wires to update. - updPws.forEach(tunnelId -> updatePw(prevConfig.getPwDescription(tunnelId), - config.getPwDescription(tunnelId))); - - log.info("Pseudowires removed : {}, Pseudowires updated : {}, Pseudowires added : {}", rmvPWs, - updPws, addedPWs); - } - /** * Helper function to update a pw. *

@@ -621,11 +521,6 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { ConnectPoint oldCp1 = oldPw.l2TunnelPolicy().cP1(); long tunnelId = oldPw.l2Tunnel().tunnelId(); - // only the master of CP1 will update this pseudowire - if (!srManager.isMasterOf(oldPw.l2TunnelPolicy().cP1())) { - log.debug("Not the master of {}. Ignore pseudo wire update id={}", oldCp1, tunnelId); - return; - } // only determine if the new pseudowire is leaf-spine, because // removal process is the same for both leaf-leaf and leaf-spine pws boolean newPwSpine; @@ -815,24 +710,6 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { }); } - @Override - public void processPwaasConfigRemoved(NetworkConfigEvent event) { - checkArgument(event.prevConfig().isPresent(), - "PrevConfig is not presented in PwaasConfigRemoved event {}", event); - - log.info("Network event : Pseudowire configuration removed!"); - PwaasConfig config = (PwaasConfig) event.prevConfig().get(); - - Set pwToRemove = config - .getPwIds() - .stream() - .map(config::getPwDescription) - .collect(Collectors.toSet()); - - // We teardown all the pseudo wire deployed - tearDown(pwToRemove); - } - /** * Helper function for removing a single pseudowire. *

@@ -957,12 +834,6 @@ public class DefaultL2TunnelHandler implements L2TunnelHandler { ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2(); long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId(); - // only the master of CP1 will program this pseudowire - if (!srManager.isMasterOf(cp1)) { - log.debug("Not the master of {}. Ignore pseudo wire removal id={}", cp1, tunnelId); - continue; - } - // no need to differentiate here between leaf-leaf and leaf-spine, because // the only change is in the groups, which we do not remove either way log.info("Removing pseudowire {}", tunnelId); 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 index 044ad416ac..5fce13787c 100644 --- 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 @@ -17,7 +17,6 @@ package org.onosproject.segmentrouting.pwaas; import org.onosproject.net.Link; -import org.onosproject.net.config.NetworkConfigEvent; import java.util.List; import java.util.Set; @@ -47,27 +46,6 @@ public interface L2TunnelHandler { */ void processLinkDown(Link link); - /** - * Processes Pwaas Config added event. - * - * @param event network config add event - */ - void processPwaasConfigAdded(NetworkConfigEvent event); - - /** - * Processes PWaaS Config updated event. - * - * @param event network config updated event - */ - void processPwaasConfigUpdated(NetworkConfigEvent event); - - /** - * Processes Pwaas Config removed event. - * - * @param event network config removed event - */ - void processPwaasConfigRemoved(NetworkConfigEvent event); - /** * Helper function to handle the pw removal. *

diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java similarity index 58% rename from apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java rename to apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java index 31cad7e3dd..fa2807e537 100644 --- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java +++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-present Open Networking Foundation + * 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. @@ -14,145 +14,130 @@ * limitations under the License. */ -package org.onosproject.segmentrouting.config; +package org.onosproject.segmentrouting.pwaas; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.collect.ImmutableSet; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.onlab.packet.MplsLabel; import org.onlab.packet.VlanId; import org.onosproject.cli.AbstractShellCommand; -import org.onosproject.core.ApplicationId; import org.onosproject.net.ConnectPoint; -import org.onosproject.net.config.Config; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.intf.InterfaceService; -import org.onosproject.segmentrouting.pwaas.L2Tunnel; -import org.onosproject.segmentrouting.pwaas.L2TunnelDescription; -import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; + +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.intf.InterfaceService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * App configuration object for Pwaas. + * Utility class with static methods that help + * parse pseudowire related information and also + * verify that a pseudowire combination is valid. */ -public class PwaasConfig extends Config { +public final class PwaasUtil { + + private static final Logger log = LoggerFactory.getLogger(PwaasUtil.class); @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - public DeviceService deviceService; + public static DeviceService deviceService = AbstractShellCommand.get(DeviceService.class);; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - public InterfaceService intfService; + public static InterfaceService intfService = AbstractShellCommand.get(InterfaceService.class); - private static Logger log = LoggerFactory - .getLogger(PwaasConfig.class); - - private static final String SRC_CP = "cP1"; - private static final String DST_CP = "cP2"; - private static final String SRC_OUTER_TAG = "cP1OuterTag"; - private static final String DST_OUTER_TAG = "cP2OuterTag"; - private static final String SRC_INNER_TAG = "cP1InnerTag"; - private static final String DST_INNER_TAG = "cP2InnerTag"; - private static final String MODE = "mode"; - private static final String SD_TAG = "sdTag"; - private static final String PW_LABEL = "pwLabel"; - - public PwaasConfig(DeviceService devS, InterfaceService intfS) { - - super(); - - deviceService = devS; - intfService = intfS; + private PwaasUtil() { + return; } - public PwaasConfig() { - - super(); - - deviceService = AbstractShellCommand.get(DeviceService.class); - intfService = AbstractShellCommand.get(InterfaceService.class); - } /** - * Error message for missing parameters. - */ - private static final String MISSING_PARAMS = "Missing parameters in pseudo wire description"; - - /** - * Error message for invalid l2 mode. - */ - private static final String INVALID_L2_MODE = "Invalid pseudo wire mode"; - - /** - * Error message for invalid VLAN. - */ - private static final String INVALID_VLAN = "Vlan should be either int or */-"; - - /** - * Error message for invalid PW label. - */ - private static final String INVALID_PW_LABEL = "Pseudowire label should be an integer"; - - /** - * Verify if the pwaas configuration block is valid. + * Parses a vlan as a string. Returns the VlanId if + * provided String can be parsed as an integer or is '' / '*' * - * Here we try to ensure that the provided pseudowires will get instantiated - * correctly in the network. We also check for any collisions with already used - * interfaces and also between different pseudowires. Most of the restrictions stem - * from the fact that all vlan matching is done in table 10 of ofdpa. - * - * @return true, if the configuration block is valid. - * False otherwise. + * @param vlan string as read from configuration + * @return VlanId null if error */ - @Override - public boolean isValid() { + public static VlanId parseVlan(String vlan) { - Set pseudowires; - try { - pseudowires = getPwIds().stream() - .map(this::getPwDescription) - .collect(Collectors.toSet()); - - // check semantics now and return - return configurationValidity(pseudowires); - - } catch (IllegalArgumentException e) { - log.warn("{}", e.getMessage()); - return false; + if (vlan.equals("*") || vlan.equals("Any")) { + return VlanId.vlanId("Any"); + } else if (vlan.equals("") || vlan.equals("None")) { + return VlanId.vlanId("None"); + } else { + try { + VlanId newVlan = VlanId.vlanId(vlan); + return newVlan; + } catch (IllegalArgumentException e) { + return null; + } } } + /** + * + * @param mode RAW or TAGGED + * @return the L2Mode if input is correct + */ + public static L2Mode parseMode(String mode) { + + if (!mode.equals("RAW") && !mode.equals("TAGGED")) { + return null; + } + + 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) { + + try { + MplsLabel pwLabel = MplsLabel.mplsLabel(label); + return pwLabel; + } catch (Exception e) { + return null; + } + } + + /** + * 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) { + try { + return Integer.parseInt(id); + } catch (Exception e) { + return null; + } + } + + /** * Helper method to verify if the tunnel is whether or not * supported. * * @param l2Tunnel the tunnel to verify - * @return the result of the verification */ - private void verifyTunnel(L2Tunnel l2Tunnel) { + 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())); + "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())); + l2Tunnel.tunnelId())); } // Raw mode without service delimiting tag @@ -168,9 +153,8 @@ public class PwaasConfig extends Config { * @param ingressOuter the ingress outer tag * @param egressInner the egress inner tag * @param egressOuter the egress outer tag - * @return the result of verification */ - private void verifyPolicy(ConnectPoint cP1, + private static void verifyPolicy(ConnectPoint cP1, ConnectPoint cP2, VlanId ingressInner, VlanId ingressOuter, @@ -180,7 +164,7 @@ public class PwaasConfig extends Config { if (cP1.deviceId().equals(cP2.deviceId())) { throw new IllegalArgumentException(String.format("Pseudowire connection points can not reside in the " + - "same node, in pseudowire %d.", tunnelId)); + "same node, in pseudowire %d.", tunnelId)); } // We can have multiple tags, all of them can be NONE, @@ -188,14 +172,15 @@ public class PwaasConfig extends Config { // not have value if the inner tag is None if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) { throw new IllegalArgumentException(String.format("Inner tag should not be empty when " + - "outer tag is set for pseudowire %d for cP1.", - tunnelId)); + "outer tag is set for pseudowire %d for cP1.", + tunnelId)); } if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) { throw new IllegalArgumentException(String.valueOf(String.format("Inner tag should not be empty when" + - " outer tag is set for pseudowire %d " + - "for cP2.", tunnelId))); + " outer tag is set for " + + "pseudowire %d " + + "for cP2.", tunnelId))); } if (ingressInner.equals(VlanId.ANY) || @@ -203,7 +188,7 @@ public class PwaasConfig extends Config { egressInner.equals(VlanId.ANY) || egressOuter.equals(VlanId.ANY)) { throw new IllegalArgumentException(String.valueOf(String.format("Wildcard VLAN matching not yet " + - "supported for pseudowire %d.", + "supported for pseudowire %d.", tunnelId))); } @@ -218,50 +203,52 @@ public class PwaasConfig extends Config { if ((!ingressInner.equals(VlanId.NONE) && ingressOuter.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) - || (egressOuter.equals(VlanId.NONE) && + || (egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE))) { - throw new IllegalArgumentException(String.valueOf(String.format("Support for double-tag<->" + - "single-tag is not supported" + - " for pseudowire %d.", tunnelId))); + throw new IllegalArgumentException(String.valueOf(String.format("Support for double-tag<->" + + "single-tag is not supported" + + " for pseudowire %d.", tunnelId))); } if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)) || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) { throw new IllegalArgumentException(String.valueOf(String.format("single-tag <-> untag is not supported" + - " for pseudowire %d.", tunnelId))); + " for pseudowire %d.", tunnelId))); } if (!ingressInner.equals(egressInner) && !ingressOuter.equals(egressOuter)) { throw new IllegalArgumentException(String.valueOf(String.format("We do not support changing both tags " + - "in double tagged pws, only the outer," + - " for pseudowire %d.", tunnelId))); + "in double tagged pws, only the " + + "outer," + + " for pseudowire %d.", tunnelId))); } // check if cp1 and port of cp1 exist if (deviceService.getDevice(cP1.deviceId()) == null) { throw new IllegalArgumentException(String.valueOf(String.format("cP1 device %s does not exist for" + - " pseudowire %d.", cP1.deviceId(), + " pseudowire %d.", cP1.deviceId(), tunnelId))); } if (deviceService.getPort(cP1) == null) { throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP1 device %s does not" + - " exist for pseudowire %d.", cP1.port(), + " exist for pseudowire %d.", + cP1.port(), cP1.deviceId(), tunnelId))); } // check if cp2 and port of cp2 exist if (deviceService.getDevice(cP2.deviceId()) == null) { throw new IllegalArgumentException(String.valueOf(String.format("cP2 device %s does not exist for" + - " pseudowire %d.", cP2.deviceId(), + " pseudowire %d.", cP2.deviceId(), tunnelId))); } if (deviceService.getPort(cP2) == null) { throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP2 device %s does " + - "not exist for pseudowire %d.", + "not exist for pseudowire %d.", cP2.port(), cP2.deviceId(), tunnelId))); } } @@ -277,7 +264,7 @@ public class PwaasConfig extends Config { * @param vlanSet Vlan set used with this configuration * @param tunnelSet Tunnel set used with this configuration */ - private void verifyGlobalValidity(L2Tunnel tunnel, + private static void verifyGlobalValidity(L2Tunnel tunnel, L2TunnelPolicy policy, Set labelSet, Map> vlanSet, @@ -285,8 +272,9 @@ public class PwaasConfig extends Config { 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(), + " another pseudowire, in " + + "pseudowire %d!", + tunnel.tunnelId(), tunnel.tunnelId()))); } tunnelSet.add(tunnel.tunnelId()); @@ -321,23 +309,25 @@ public class PwaasConfig extends Config { if (labelSet.contains(tunnel.pwLabel())) { throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" + - " pseudowire, in pseudowire %d!", + " 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, + "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, + " by another pseudowire, in" + + " pseudowire %d!", vlanToCheckCP2, + cP2, tunnel.tunnelId()))); } vlanSet.get(cP2).add(vlanToCheckCP2); @@ -349,8 +339,9 @@ public class PwaasConfig extends Config { // 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!", + " used for this" + + " interface, in" + + " pseudowire %d!", vlanToCheckCP1, cP1, tunnel.tunnelId()))); } @@ -359,29 +350,33 @@ public class PwaasConfig extends Config { // 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()))); + "%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()))); + "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 already" + - " used for this interface, " + - "in pseudowire %d!", + throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s " + + " used for " + + "this interface, " + + "in pseudowire %d!", vlanToCheckCP2, cP2, tunnel.tunnelId()))); } @@ -389,10 +384,12 @@ public class PwaasConfig extends Config { // 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!", + throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic " + + "for cP2 %s " + + "already " + + "used for this" + + " interface, " + + "in pseudowire %d!", cP2, tunnel.tunnelId()))); } @@ -400,9 +397,10 @@ public class PwaasConfig extends Config { // 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!", + " already" + + " used for " + + "this interface, " + + "in pseudowire %d!", cP2, tunnel.tunnelId()))); } }); @@ -413,9 +411,8 @@ public class PwaasConfig extends Config { * Helper method to verify the integrity of the pseudo wire. * * @param l2TunnelDescription the pseudo wire description - * @return the result of the check */ - private void verifyPseudoWire(L2TunnelDescription l2TunnelDescription, + private static void verifyPseudoWire(L2TunnelDescription l2TunnelDescription, Set labelSet, Map> vlanset, Set tunnelSet) { @@ -443,14 +440,7 @@ public class PwaasConfig extends Config { } - /** - * Checks if the configured pseudowires will create problems in the network. - * If yes, then no pseudowires is deployed from this configuration. - * - * @param pseudowires Set of pseudowries to validate - * @return returns true if everything goes well. - */ - public boolean configurationValidity(Set pseudowires) { + public static boolean configurationValidity(Set pseudowires) { // structures to keep pw information // in order to see if instantiating them will create @@ -459,213 +449,30 @@ public class PwaasConfig extends Config { Set labelsUsed = new HashSet<>(); Map> vlanIds = new HashMap<>(); - // 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) { - verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds); + // 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) { + verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds); + } + } catch (Exception e) { + + log.error("Caught exception while validating pseudowire : {}", e.getMessage()); + return false; } + // return true return true; } - /** - * Returns all pseudo wire keys. - * - * @return all keys (tunnels id) - * @throws IllegalArgumentException if wrong format - */ - public Set getPwIds() { - ImmutableSet.Builder builder = ImmutableSet.builder(); - object.fields().forEachRemaining(entry -> { - Long tunnelId = Long.parseLong(entry.getKey()); - builder.add(tunnelId); - }); - return builder.build(); - } - - /** - * 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 - * @throws IllegalArgumentException if wrong format of vlan - */ - public 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 { - try { - VlanId newVlan = VlanId.vlanId(vlan); - return newVlan; - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(INVALID_VLAN); - } - } - } - - /** - * - * @param mode RAW or TAGGED - * @return the L2Mode if input is correct - * @throws IllegalArgumentException if not supported mode - */ - public L2Mode parseMode(String mode) { - - if (!mode.equals("RAW") && !mode.equals("TAGGED")) { - throw new IllegalArgumentException(INVALID_L2_MODE); - } - - return L2Mode.valueOf(mode); - } - - /** - * - * @param label the mpls label of the pseudowire - * @return the MplsLabel - * @throws IllegalArgumentException if label is invalid - */ - public MplsLabel parsePWLabel(String label) { - - try { - MplsLabel pwLabel = MplsLabel.mplsLabel(label); - return pwLabel; - } catch (Exception e) { - throw new IllegalArgumentException(INVALID_PW_LABEL); - } - } - - /** - * Returns pw description of given pseudo wire id. - * - * @param tunnelId pseudo wire key - * @return set of l2 tunnel descriptions - * @throws IllegalArgumentException if wrong format - */ - public L2TunnelDescription getPwDescription(Long tunnelId) { - JsonNode pwDescription = object.get(tunnelId.toString()); - if (!hasFields((ObjectNode) pwDescription, - SRC_CP, SRC_INNER_TAG, SRC_OUTER_TAG, - DST_CP, DST_INNER_TAG, DST_OUTER_TAG, - MODE, SD_TAG, PW_LABEL)) { - throw new IllegalArgumentException(MISSING_PARAMS); - } - String tempString; - - tempString = pwDescription.get(SRC_CP).asText(); - ConnectPoint srcCp = ConnectPoint.deviceConnectPoint(tempString); - - tempString = pwDescription.get(DST_CP).asText(); - ConnectPoint dstCp = ConnectPoint.deviceConnectPoint(tempString); - - tempString = pwDescription.get(SRC_INNER_TAG).asText(); - VlanId srcInnerTag = parseVlan(tempString); - - tempString = pwDescription.get(SRC_OUTER_TAG).asText(); - VlanId srcOuterTag = parseVlan(tempString); - - tempString = pwDescription.get(DST_INNER_TAG).asText(); - VlanId dstInnerTag = parseVlan(tempString); - - tempString = pwDescription.get(DST_OUTER_TAG).asText(); - VlanId dstOuterTag = parseVlan(tempString); - - tempString = pwDescription.get(MODE).asText(); - L2Mode l2Mode = parseMode(tempString); - - tempString = pwDescription.get(SD_TAG).asText(); - VlanId sdTag = parseVlan(tempString); - - tempString = pwDescription.get(PW_LABEL).asText(); - MplsLabel pwLabel = parsePWLabel(tempString); - - L2Tunnel l2Tunnel = new DefaultL2Tunnel( - l2Mode, - sdTag, - tunnelId, - pwLabel - ); - - L2TunnelPolicy l2TunnelPolicy = new DefaultL2TunnelPolicy( - tunnelId, - srcCp, - srcInnerTag, - srcOuterTag, - dstCp, - dstInnerTag, - dstOuterTag - ); - - return new DefaultL2TunnelDescription(l2Tunnel, l2TunnelPolicy); - } - - /** - * Removes a pseudowire from the configuration tree. - * @param pwId Pseudowire id - * @return null if pwId did not exist, or the object representing the - * udpated configuration tree - */ - public ObjectNode removePseudowire(String pwId) { - - JsonNode value = object.remove(pwId); - if (value == null) { - return (ObjectNode) value; - } else { - return object; - } - } - - /** - * Adds a pseudowire to the configuration tree of pwwas. It also checks - * if the configuration is valid, if not return null and does not add the node, - * if yes return the new configuration. Caller will propagate update events. - * - * If the pseudowire already exists in the configuration it gets updated. - * - * @param tunnelId Id of tunnel - * @param pwLabel PW label of tunnel - * @param cP1 Connection point 1 - * @param cP1InnerVlan Inner vlan of cp1 - * @param cP1OuterVlan Outer vlan of cp2 - * @param cP2 Connection point 2 - * @param cP2InnerVlan Inner vlan of cp2 - * @param cP2OuterVlan Outer vlan of cp2 - * @param mode Mode for the pw - * @param sdTag Service delimiting tag for the pw - * @return The ObjectNode config if configuration is valid with the new pseudowire - * or null. - */ - public ObjectNode addPseudowire(String tunnelId, String pwLabel, String cP1, - String cP1InnerVlan, String cP1OuterVlan, String cP2, - String cP2InnerVlan, String cP2OuterVlan, - String mode, String sdTag) { - - - ObjectNode newPw = new ObjectNode(JsonNodeFactory.instance); - - // add fields for pseudowire - newPw.put(SRC_CP, cP1); - newPw.put(DST_CP, cP2); - newPw.put(PW_LABEL, pwLabel); - newPw.put(SRC_INNER_TAG, cP1InnerVlan); - newPw.put(SRC_OUTER_TAG, cP1OuterVlan); - newPw.put(DST_INNER_TAG, cP2InnerVlan); - newPw.put(DST_OUTER_TAG, cP2OuterVlan); - newPw.put(SD_TAG, sdTag); - newPw.put(MODE, mode); - - object.set(tunnelId, newPw); - - if (!isValid()) { - log.info("Pseudowire could not be created : {}"); - object.remove(tunnelId); - return null; - } - - return object; - } } diff --git a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java b/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java deleted file mode 100644 index 23d1233e4f..0000000000 --- a/apps/segmentrouting/app/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java +++ /dev/null @@ -1,399 +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.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.Lists; -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.MplsLabel; -import org.onlab.packet.VlanId; -import org.onosproject.TestApplicationId; -import org.onosproject.core.ApplicationId; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultHost; -import org.onosproject.net.Device; -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.Config; -import org.onosproject.net.config.ConfigApplyDelegate; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.host.InterfaceIpAddress; -import org.onosproject.net.intf.Interface; -import org.onosproject.net.intf.InterfaceService; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.segmentrouting.config.PwaasConfig; - -import org.onosproject.segmentrouting.pwaas.L2Tunnel; -import org.onosproject.segmentrouting.pwaas.L2TunnelDescription; -import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy; -import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel; -import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy; -import org.onosproject.segmentrouting.pwaas.L2Mode; - -import java.io.InputStream; -import java.util.Set; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.*; - -/** - * Unit tests for class {@link PwaasConfig}. - */ -public class PwaasConfigTest { - - private static final String TUNNEL_ID_1 = "1"; - private static final String TUNNEL_ID_2 = "20"; - private static final String NOT_PRESENT_TUNNEL_ID = "2"; - private static final ConnectPoint INGRESS_1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1"); - private static final ConnectPoint INGRESS_2 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1"); - private static final ConnectPoint EGRESS_1 = ConnectPoint.deviceConnectPoint("of:0000000000000002/1"); - private static final ConnectPoint EGRESS_2 = ConnectPoint.deviceConnectPoint("of:0000000000000002/1"); - private static final VlanId INGRESS_INNER_TAG_1 = VlanId.vlanId("10"); - private static final VlanId INGRESS_INNER_TAG_2 = VlanId.vlanId("100"); - private static final VlanId INGRESS_OUTER_TAG_1 = VlanId.vlanId("20"); - private static final VlanId INGRESS_OUTER_TAG_2 = VlanId.vlanId("200"); - private static final VlanId EGRESS_INNER_TAG_1 = VlanId.vlanId("10"); - private static final VlanId EGRESS_INNER_TAG_2 = VlanId.vlanId("100"); - private static final VlanId EGRESS_OUTER_TAG_1 = VlanId.vlanId("21"); - private static final VlanId EGRESS_OUTER_TAG_2 = VlanId.vlanId("210"); - private static final String MODE_1 = "RAW"; - private static final String MODE_2 = "RAW"; - private static final VlanId SD_TAG_1 = VlanId.NONE; - private static final VlanId SD_TAG_2 = VlanId.NONE; - private static final MplsLabel PW_LABEL_1 = MplsLabel.mplsLabel("255"); - private static final MplsLabel PW_LABEL_2 = MplsLabel.mplsLabel("1255"); - - /* - * Configuration below copied from host handler test. - */ - - // 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_IP32 = IpAddress.valueOf("10.0.3.2"); - // 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 CP41 = new ConnectPoint(DEV4, P1); - private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 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 Set INTF_VLAN_TAGGED = Sets.newHashSet(VlanId.vlanId((short) 20)); - private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30); - private static final Set 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_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 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 HOSTS = Sets.newHashSet(HOST1); - // A set of devices of which we have mastership - private static final Set LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4); - // A set of interfaces - private static final Set INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21, - INTF22, INTF31, INTF32, INTF39, INTF41, INTF49); - - private PwaasConfig config; - private PwaasConfig invalidConfigVlan; - private PwaasConfig invalidConfigMode; - private PwaasConfig invalidConfigLabel; - private PwaasConfig invalidConfigConflictingVlan; - - @Before - public void setUp() throws Exception { - InputStream jsonStream = PwaasConfig.class - .getResourceAsStream("/pwaas.json"); - InputStream jsonStreamInvalid1 = PwaasConfig.class - .getResourceAsStream("/pwaas-invalid-mode.json"); - InputStream jsonStreamInvalid2 = PwaasConfig.class - .getResourceAsStream("/pwaas-invalid-pwlabel.json"); - InputStream jsonStreamInvalid3 = PwaasConfig.class - .getResourceAsStream("/pwaas-invalid-vlan.json"); - InputStream jsonStreamInvalid4 = PwaasConfig.class - .getResourceAsStream("/pwaas-conflicting-vlan.json"); - - String key = SegmentRoutingManager.APP_NAME; - ApplicationId subject = new TestApplicationId(key); - ObjectMapper mapper = new ObjectMapper(); - - JsonNode jsonNode = mapper.readTree(jsonStream); - JsonNode jsonNodeInvalid1 = mapper.readTree(jsonStreamInvalid1); - JsonNode jsonNodeInvalid2 = mapper.readTree(jsonStreamInvalid2); - JsonNode jsonNodeInvalid3 = mapper.readTree(jsonStreamInvalid3); - JsonNode jsonNodeInvalid4 = mapper.readTree(jsonStreamInvalid4); - - ConfigApplyDelegate delegate = new MockDelegate(); - - DeviceService devService = new MockDeviceService(); - InterfaceService infService = new MockInterfaceService(INTERFACES); - - // create two devices and add them - DefaultAnnotations.Builder builderDev1 = DefaultAnnotations.builder(); - DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder(); - - Device dev1 = new MockDevice(DEV1, builderDev1.build()); - Device dev2 = new MockDevice(DEV2, builderDev2.build()); - ((MockDeviceService) devService).addDevice(dev1); - ((MockDeviceService) devService).addDevice(dev2); - - config = new PwaasConfig(devService, infService); - invalidConfigVlan = new PwaasConfig(devService, infService); - invalidConfigMode = new PwaasConfig(devService, infService); - invalidConfigLabel = new PwaasConfig(devService, infService); - invalidConfigConflictingVlan = new PwaasConfig(devService, infService); - - config.init(subject, key, jsonNode, mapper, delegate); - invalidConfigVlan.init(subject, key, jsonNodeInvalid1, mapper, delegate); - invalidConfigMode.init(subject, key, jsonNodeInvalid2, mapper, delegate); - invalidConfigLabel.init(subject, key, jsonNodeInvalid3, mapper, delegate); - invalidConfigConflictingVlan.init(subject, key, jsonNodeInvalid4, mapper, delegate); - - config.deviceService = devService; - config.intfService = infService; - - invalidConfigVlan.deviceService = devService; - invalidConfigVlan.intfService = infService; - - invalidConfigLabel.deviceService = devService; - invalidConfigLabel.intfService = infService; - - invalidConfigMode.deviceService = devService; - invalidConfigMode.intfService = infService; - - invalidConfigConflictingVlan.deviceService = devService; - invalidConfigConflictingVlan.intfService = infService; - } - - /** - * Tests config validity. - */ - @Test - public void testIsValid() { - try { - assertTrue(config.isValid()); - } catch (IllegalArgumentException e) { - assertTrue(false); - } - } - - /** - * Tests config in-validity. - */ - @Test - public void testValid1() { - assertFalse(invalidConfigVlan.isValid()); - } - - @Test - public void testValid2() { - assertFalse(invalidConfigMode.isValid()); - } - - @Test - public void testValid3() { - assertFalse(invalidConfigLabel.isValid()); - } - - @Test - public void testValid4() { - assertFalse(invalidConfigConflictingVlan.isValid()); - } - - /** - * Tests getPwIds. - */ - @Test - public void testGetPwIds() { - Set pwIds = config.getPwIds(); - - assertThat(pwIds.size(), is(2)); - assertTrue(pwIds.contains(Long.parseLong(TUNNEL_ID_1))); - assertTrue(pwIds.contains(Long.parseLong(TUNNEL_ID_2))); - assertFalse(pwIds.contains(Long.parseLong(NOT_PRESENT_TUNNEL_ID))); - } - - /** - * Tests getPwDescription. - */ - @Test - public void testGetPwDescription() { - L2TunnelDescription l2TunnelDescription = null; - - L2Tunnel l2Tunnel = new DefaultL2Tunnel( - L2Mode.valueOf(MODE_1), - SD_TAG_1, - Long.parseLong(TUNNEL_ID_1), - PW_LABEL_1 - ); - L2TunnelPolicy l2TunnelPolicy = new DefaultL2TunnelPolicy( - Long.parseLong(TUNNEL_ID_1), - INGRESS_1, - INGRESS_INNER_TAG_1, - INGRESS_OUTER_TAG_1, - EGRESS_1, - EGRESS_INNER_TAG_1, - EGRESS_OUTER_TAG_1 - ); - - l2TunnelDescription = config.getPwDescription(Long.parseLong(TUNNEL_ID_1)); - assertThat(l2TunnelDescription.l2Tunnel().pwMode(), is(l2Tunnel.pwMode())); - assertThat(l2TunnelDescription.l2Tunnel().sdTag(), is(l2Tunnel.sdTag())); - assertThat(l2TunnelDescription.l2Tunnel().tunnelId(), is(l2Tunnel.tunnelId())); - assertThat(l2TunnelDescription.l2Tunnel().pwLabel(), is(l2Tunnel.pwLabel())); - assertThat(l2TunnelDescription.l2TunnelPolicy().tunnelId(), is(l2TunnelPolicy.tunnelId())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP1InnerTag(), is(l2TunnelPolicy.cP1InnerTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP1OuterTag(), is(l2TunnelPolicy.cP1OuterTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP2InnerTag(), is(l2TunnelPolicy.cP2InnerTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP2OuterTag(), is(l2TunnelPolicy.cP2OuterTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP1(), is(l2TunnelPolicy.cP1())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP2(), is(l2TunnelPolicy.cP2())); - - l2Tunnel = new DefaultL2Tunnel( - L2Mode.valueOf(MODE_2), - SD_TAG_2, - Long.parseLong(TUNNEL_ID_2), - PW_LABEL_2 - ); - l2TunnelPolicy = new DefaultL2TunnelPolicy( - Long.parseLong(TUNNEL_ID_2), - INGRESS_2, - INGRESS_INNER_TAG_2, - INGRESS_OUTER_TAG_2, - EGRESS_2, - EGRESS_INNER_TAG_2, - EGRESS_OUTER_TAG_2 - ); - - l2TunnelDescription = config.getPwDescription(Long.parseLong(TUNNEL_ID_2)); - assertThat(l2TunnelDescription.l2Tunnel().pwMode(), is(l2Tunnel.pwMode())); - assertThat(l2TunnelDescription.l2Tunnel().sdTag(), is(l2Tunnel.sdTag())); - assertThat(l2TunnelDescription.l2Tunnel().tunnelId(), is(l2Tunnel.tunnelId())); - assertThat(l2TunnelDescription.l2Tunnel().pwLabel(), is(l2Tunnel.pwLabel())); - assertThat(l2TunnelDescription.l2TunnelPolicy().tunnelId(), is(l2TunnelPolicy.tunnelId())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP1InnerTag(), is(l2TunnelPolicy.cP1InnerTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP1OuterTag(), is(l2TunnelPolicy.cP1OuterTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP2OuterTag(), is(l2TunnelPolicy.cP2OuterTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP2OuterTag(), is(l2TunnelPolicy.cP2OuterTag())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP1(), is(l2TunnelPolicy.cP1())); - assertThat(l2TunnelDescription.l2TunnelPolicy().cP2(), is(l2TunnelPolicy.cP2())); - } - - private class MockDelegate implements ConfigApplyDelegate { - @Override - public void onApply(Config config) { - } - } - -} diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/package-info.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/package-info.java index ff9555ea12..1d50ba9534 100644 --- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/package-info.java +++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/package-info.java @@ -15,6 +15,6 @@ */ /** - * Segment routing application components. + * Segment routing REST implementation. */ package org.onosproject.segmentrouting.web; \ No newline at end of file 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 index abfba3c223..cebcf84a6b 100644 --- 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 @@ -26,7 +26,6 @@ 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; @@ -37,7 +36,7 @@ import java.util.List; /** * Query, create and remove segment routing plicies. */ -@Path("policy") +// @Path("policy") public class PolicyWebResource extends AbstractWebResource { private static final PolicyCodec POLICY_CODEC = new PolicyCodec(); 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 new file mode 100644 index 0000000000..f2fe786d6f --- /dev/null +++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java @@ -0,0 +1,158 @@ +/* + * 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.node.ObjectNode; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*; + +/** + * Codec of PseudowireCodec class. + */ +public final class PseudowireCodec extends JsonCodec { + + // 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 = "cP2OouterTag"; + private static final String MODE = "mode"; + private static final String SERVICE_DELIM_TAG = "serviceTag"; + private static final String PW_LABEL = "pwLabel"; + + 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(MODE, pseudowire.l2Tunnel().pwMode() == L2Mode.RAW ? "RAW" : "TAGGED"); + result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString()); + result.put(PW_LABEL, pseudowire.l2Tunnel().pwLabel().toString()); + + return result; + } + + /** + * Decodes a json containg a single field with the pseudowire id. + * + * @param json Json to decode. + * @return The pseudowire id. + */ + public Integer decodeId(ObjectNode json) { + + Integer id = parsePwId(json.path(PW_ID).asText()); + if (id == null) { + log.error("Pseudowire id is not an integer!"); + return null; + } + + return id; + } + + @Override + public DefaultL2TunnelDescription decode(ObjectNode json, CodecContext context) { + + String tempString; + + Integer id = parsePwId(json.path(PW_ID).asText()); + if (id == null) { + log.error("Pseudowire id is not an integer"); + return null; + } + + ConnectPoint cP1, cP2; + try { + tempString = json.path(CP1).asText(); + cP1 = ConnectPoint.deviceConnectPoint(tempString); + } catch (Exception e) { + log.error("cP1 is not a valid connect point!"); + return null; + } + + try { + tempString = json.path(CP2).asText(); + cP2 = ConnectPoint.deviceConnectPoint(tempString); + } catch (Exception e) { + log.error("cP2 is not a valid connect point!"); + return null; + } + + VlanId cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText()); + VlanId cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText()); + VlanId cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText()); + VlanId cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText()); + if ((cP1InnerVlan == null) || (cP1OuterVlan == null) || + (cP2InnerVlan == null) || (cP2OuterVlan == null)) { + log.error("One or more vlan for cp1 or cp2 is malformed, it shouldbe an integer / Any / None / *"); + return null; + } + + L2Mode mode = parseMode(json.path(MODE).asText()); + if (mode == null) { + log.error("Mode should be RAW or TAGGED!"); + return null; + } + + VlanId sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText()); + if (sdTag == null) { + log.error("SD tag is malformed, it should be an integer / Any / None / *"); + return null; + } + + MplsLabel pwLabel = parsePWLabel(json.path(PW_LABEL).asText()); + if (pwLabel == null) { + log.error("PW label is malformed, should be an integer!"); + return null; + } + + DefaultL2Tunnel l2Tunnel; + DefaultL2TunnelPolicy l2Policy; + + l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel); + 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 new file mode 100644 index 0000000000..ba151a1d9f --- /dev/null +++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java @@ -0,0 +1,166 @@ +/* + * 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.pwaas.DefaultL2TunnelDescription; +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.List; +import java.util.stream.Collectors; + +/** + * Query, create and remove pseudowires. + */ +@Path("pseudowire") +public class PseudowireWebResource extends AbstractWebResource { + + private static final PseudowireCodec PSEUDOWIRE_CODEC = new PseudowireCodec(); + + 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 policies = srService.getL2Policies(); + List tunnels = srService.getL2Tunnels(); + List 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 = (ObjectNode) mapper.readTree(input); + SegmentRoutingService srService = get(SegmentRoutingService.class); + + DefaultL2TunnelDescription pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this); + if (pseudowire == null) { + return Response.serverError().status(Response.Status.BAD_REQUEST).build(); + } + + log.info("Creating pseudowire {} from rest api!", pseudowire.l2Tunnel().tunnelId()); + + L2TunnelHandler.Result res = srService.addPseudowire(pseudowire); + switch (res) { + case ADDITION_ERROR: + log.error("Pseudowire {} could not be added, error in configuration," + + " please check logs for more details!", + pseudowire.l2Tunnel().tunnelId()); + return Response.serverError().status(Response.Status.INTERNAL_SERVER_ERROR).build(); + + case SUCCESS: + log.info("Pseudowire {} succesfully deployed!", pseudowire.l2Tunnel().tunnelId()); + return Response.ok().build(); + default: + return Response.ok().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 = (ObjectNode) mapper.readTree(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.info("Deleting pseudowire {} from rest api!", pseudowireId); + + L2TunnelHandler.Result res = srService.removePseudowire(pseudowireId); + switch (res) { + case REMOVAL_ERROR: + log.error("Pseudowire {} could not be removed, error in configuration," + + " please check logs for more details!", + pseudowireId); + + return Response.noContent().build(); + case SUCCESS: + log.info("Pseudowire {} was removed succesfully!", pseudowireId); + return Response.noContent().build(); + 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 new file mode 100644 index 0000000000..4aa1a71930 --- /dev/null +++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java @@ -0,0 +1,31 @@ +/* + * 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 Web application. + */ +public class SegmentRoutingWebApplication extends AbstractWebApplication { + @Override + public Set> getClasses() { + return getClasses(PseudowireWebResource.class); + } +} 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 index 7a368f5e38..476bcd8d4b 100644 --- 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 @@ -26,7 +26,6 @@ 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; @@ -37,7 +36,7 @@ import java.util.List; /** * Query, create and remove segment routing tunnels. */ -@Path("tunnel") +// @Path("tunnel") public class TunnelWebResource extends AbstractWebResource { private static final TunnelCodec TUNNEL_CODEC = new TunnelCodec(); 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 index 101d40ebcc..ff9555ea12 100644 --- 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 @@ -15,6 +15,6 @@ */ /** - * Set of resources implementing the segment routing application REST API. + * 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 new file mode 100644 index 0000000000..feddd1858f --- /dev/null +++ b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireCreate.json @@ -0,0 +1,68 @@ +{ + "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": "", + "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 new file mode 100644 index 0000000000..4dd5c04c53 --- /dev/null +++ b/apps/segmentrouting/web/src/main/resources/definitions/PseudowireDelete.json @@ -0,0 +1,14 @@ +{ + "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/webapp/WEB-INF/web.xml b/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml index 5aac978df8..73154e3393 100644 --- a/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml +++ b/apps/segmentrouting/web/src/main/webapp/WEB-INF/web.xml @@ -14,21 +14,38 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - - Segment Routing REST API v1.0 + Segment Routing Server REST API v1.0 + + + + Secured + /* + + + admin + + + + + admin + + + + BASIC + karaf + JAX-RS Service org.glassfish.jersey.servlet.ServletContainer - jersey.config.server.provider.classnames - - org.onosproject.segmentrouting.web.TunnelWebResource, - org.onosproject.segmentrouting.web.PolicyWebResource - + javax.ws.rs.Application + org.onosproject.segmentrouting.web.SegmentRoutingWebApplication 1