Implemented the following PW features and fixes:
- PW support for H-AGG topologies. Support for leaf-spine-spine
leaf-spine-spine-leaf pseudowires.
- Renamed pw commands with sr-pw-* pattern and also removed redundant output
from them.
- Enabled bulk addition / removal of pws from the rest api.
- Modified diagnostics tool with the updated command name.
Change-Id: I708db9281d0082b160cbd713910b420ef7df9da3
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
index 240d6e9..ff0f2a6 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -876,6 +876,39 @@
}
}
+ 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
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 65ffb53..1f035d7 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
@@ -556,6 +556,11 @@
}
@Override
+ public Set<L2TunnelDescription> getL2TunnelDescriptions() {
+ return l2TunnelHandler.getL2Descriptions();
+ }
+
+ @Override
public List<L2Tunnel> getL2Tunnels() {
return l2TunnelHandler.getL2Tunnels();
}
@@ -566,43 +571,41 @@
}
@Override
+ public L2TunnelHandler.Result addPseudowiresBulk(List<DefaultL2TunnelDescription> bulkPseudowires) {
+
+ Set<L2TunnelDescription> pseudowires = l2TunnelHandler.getL2Descriptions();
+
+ pseudowires.addAll(bulkPseudowires);
+ Set<L2TunnelDescription> newPseudowires = new HashSet(bulkPseudowires);
+
+ // check global validity for all the new pseudowires, if it fails
+ // do not add any of them
+ boolean res = configurationValidity(pseudowires);
+ if (res) {
+ l2TunnelHandler.deploy(newPseudowires);
+ return L2TunnelHandler.Result.SUCCESS;
+ } else {
+ log.error("Bulk pseudowires {} can not be added, error in global configuration!",
+ newPseudowires);
+ return L2TunnelHandler.Result.ADDITION_ERROR;
+ }
+ }
+
+ @Override
public L2TunnelHandler.Result addPseudowire(L2TunnelDescription l2TunnelDescription) {
- List<L2Tunnel> tunnels = getL2Tunnels();
- List<L2TunnelPolicy> policies = getL2Policies();
-
- // combine polices and tunnels to pseudowires
- List<L2TunnelDescription> 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<L2TunnelDescription> newPseudowires = new HashSet<>(pseudowires);
+ Set<L2TunnelDescription> newPseudowires = l2TunnelHandler.getL2Descriptions();
// 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;
}
-
// 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);
@@ -612,7 +615,6 @@
l2TunnelDescription.l2Tunnel().tunnelId());
return L2TunnelHandler.Result.SUCCESS;
} else {
-
log.error("Pseudowire with {} can not be added!", l2TunnelDescription.l2Tunnel().tunnelId());
return L2TunnelHandler.Result.ADDITION_ERROR;
}
@@ -645,7 +647,6 @@
} 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;
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 759495b..dc3d7b1 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
@@ -23,6 +23,7 @@
import org.onosproject.net.PortNumber;
import org.onosproject.segmentrouting.grouphandler.NextNeighbors;
import org.onosproject.segmentrouting.mcast.McastRole;
+import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.L2Tunnel;
import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
@@ -89,6 +90,13 @@
List<Policy> getPolicies();
/**
+ * Returns the l2 tunnel descriptions.
+ *
+ * @return set of l2 tunnel descriptions.
+ */
+ Set<L2TunnelDescription> getL2TunnelDescriptions();
+
+ /**
* Returns all l2 tunnels of pseudowires.
*
* @return list of l2 tunnels
@@ -103,7 +111,7 @@
List<L2TunnelPolicy> getL2Policies();
/**
- * Removes pseudowire. Used ONLY by the REST api.
+ * Removes pseudowire.
*
* @param pwId The id of the pseudowire.
* @return SUCCESS if operation successful or a descriptive error otherwise.
@@ -111,7 +119,7 @@
L2TunnelHandler.Result removePseudowire(Integer pwId);
/**
- * Adds a Pseudowire to the configuration.
+ * Adds a Pseudowire to the system.
*
* @param tunnel The pseudowire tunnel.
* @return SUCCESS if operation is successful or a descriptive error otherwise.
@@ -119,6 +127,14 @@
L2TunnelHandler.Result addPseudowire(L2TunnelDescription tunnel);
/**
+ * Adss 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.
+ */
+ L2TunnelHandler.Result addPseudowiresBulk(List<DefaultL2TunnelDescription> l2TunnelDescriptions);
+
+ /**
* Creates a policy.
*
* @param policy policy reference to create
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 ab80aff..b69763d 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
@@ -35,7 +35,7 @@
/**
* Command to add a pseuwodire.
*/
-@Command(scope = "onos", name = "pseudowire-add",
+@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 {
@@ -121,10 +121,9 @@
switch (res) {
case ADDITION_ERROR:
- print("Pseudowire could not be added, please check logs for more details!");
+ print("Pseudowire could not be added!");
break;
case SUCCESS:
- print("Pseudowire was added succesfully!");
break;
default:
break;
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
index c48f633..a633a8a 100644
--- 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
@@ -30,7 +30,7 @@
/**
* Command to show the pseudowires.
*/
-@Command(scope = "onos", name = "pseudowires",
+@Command(scope = "onos", name = "sr-pw-list",
description = "Lists all pseudowires")
public class PseudowireListCommand extends AbstractShellCommand {
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 0f027b2..305f0be 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
@@ -29,7 +29,7 @@
/**
* Command to remove a pseudowire.
*/
-@Command(scope = "onos", name = "pseudowire-remove",
+@Command(scope = "onos", name = "sr-pw-remove",
description = "Remove a pseudowire")
public class PseudowireRemoveCommand extends AbstractShellCommand {
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 4b3272d..acaf9f6 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
@@ -175,6 +175,27 @@
// use it in the future.
}
+ @Override
+ public Set<L2TunnelDescription> getL2Descriptions() {
+ List<L2Tunnel> tunnels = getL2Tunnels();
+ List<L2TunnelPolicy> policies = getL2Policies();
+
+ // determine affected pseudowires and update them at once
+ 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());
+ }
+
/**
* Returns all L2 Policies.
*
@@ -188,7 +209,6 @@
.stream()
.map(Versioned::value)
.collect(Collectors.toList()));
-
}
/**
@@ -204,7 +224,6 @@
.stream()
.map(Versioned::value)
.collect(Collectors.toList()));
-
}
@Override
@@ -298,6 +317,16 @@
}
/**
+ * Returns true if path size is valid according to the current logic.
+ *
+ * @param pathSize The size of the path
+ * @return True if path size is valid, false otherwise.
+ */
+ private boolean isValidPathSize(int pathSize) {
+ return ((pathSize >= 1) && (pathSize <= 4));
+ }
+
+ /**
* Adds a single pseudowire.
*
* @param pw The pseudowire
@@ -327,31 +356,27 @@
Link fwdNextHop;
Link revNextHop;
- if (!spinePw) {
- if (path.size() != 2) {
- log.info("Deploying process : Path between two leafs should have size of 2, for pseudowire {}",
- l2TunnelId);
- return INTERNAL_ERROR;
- }
-
- fwdNextHop = path.get(0);
- revNextHop = reverseLink(path.get(1));
- } else {
- if (path.size() != 1) {
- log.info("Deploying process : Path between leaf spine should equal to 1, for pseudowire {}",
- l2TunnelId);
- return INTERNAL_ERROR;
- }
-
- fwdNextHop = path.get(0);
- revNextHop = reverseLink(path.get(0));
+ if (!isValidPathSize(path.size())) {
+ log.error("Deploying process : Path size for pseudowire should be of" +
+ " one of the following sizes = [1, 2, 3, 4], for pseudowire {}",
+ l2TunnelId);
+ return INTERNAL_ERROR;
}
+ // spinePw signifies if we have a leaf-spine pw
+ // thus only one label should be pushed (that of pw)
+ // if size>1 we need to push intermediate labels also.
+ if (path.size() > 1) {
+ spinePw = false;
+ }
+
+ fwdNextHop = path.get(0);
+ revNextHop = reverseLink(path.get(path.size() - 1));
+
pw.l2Tunnel().setPath(path);
pw.l2Tunnel().setTransportVlan(determineTransportVlan(spinePw));
// next hops for next objectives
-
log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
@@ -618,24 +643,23 @@
}
Link fwdNextHop, revNextHop;
- if (!finalNewPwSpine) {
- if (path.size() != 2) {
- log.error("Update process : Error, path between two leafs should have size of 2, for pseudowire {}",
- newPw.l2Tunnel().tunnelId());
- return;
- }
- fwdNextHop = path.get(0);
- revNextHop = reverseLink(path.get(1));
- } else {
- if (path.size() != 1) {
- log.error("Update process : Error, path between leaf spine should equal to 1, for pseudowire {}",
- newPw.l2Tunnel().tunnelId());
- return;
- }
- fwdNextHop = path.get(0);
- revNextHop = reverseLink(path.get(0));
+ if (!isValidPathSize(path.size())) {
+ log.error("Deploying process : Path size for pseudowire should be of one of the following sizes" +
+ " = [1, 2, 3, 4], for pseudowire {}",
+ newPw.l2Tunnel().tunnelId());
+ return;
}
+ // spinePw signifies if we have a leaf-spine pw
+ // thus only one label should be pushed (that of pw)
+ // if size>1 we need to push intermediate labels also.
+ if (path.size() > 1) {
+ newPwSpine = false;
+ }
+
+ fwdNextHop = path.get(0);
+ revNextHop = reverseLink(path.get(path.size() - 1));
+
// set new path and transport vlan.
newPw.l2Tunnel().setPath(path);
newPw.l2Tunnel().setTransportVlan(determineTransportVlan(newPwSpine));
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 5fce137..ad4f50a 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
@@ -25,6 +25,13 @@
void init();
/**
+ * Combines policies and tunnels to create descriptions.
+ *
+ * @return Set of l2 tunnel descriptions.
+ */
+ Set<L2TunnelDescription> getL2Descriptions();
+
+ /**
* Returns a copy of the l2 policies that exist in the store.
*
* @return The l2 policies