Various pseudowire fixes and improvements.
- Co-ordination when creating - removing pseudowires from
different instances with a use of a DistributedLock.
- Fixed REST API To return json with specific error for
the single pw instantiation.
- Fixed REST API to return specific error also for pseudowires
that could not be decoded.
- Minor bug fix to return appropriate error when instantiating
a pw from the command line that could not be decoded.
- Fixed bug when creating spine-leaf-leaf pseudowire where we observed flows in pending state.
- Improved logging.
Change-Id: I60dd0ebf8af63ca74d18cfe4801d01846641fb7b
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 277a1c3..d7d22b4 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
@@ -100,8 +100,9 @@
try {
tun = new DefaultL2Tunnel(parseMode(mode), parseVlan(sDTag), parsePwId(pwId), parsePWLabel(pwLabel));
- } catch (Exception e) {
- print("Exception while parsing L2Tunnel : {}", e);
+ } catch (IllegalArgumentException e) {
+ log.error("Exception while parsing L2Tunnel : \n\t %s", e.getMessage());
+ print("Exception while parsing L2Tunnel : \n\t %s", e.getMessage());
return;
}
@@ -111,13 +112,15 @@
parseVlan(cP1OuterVlan), ConnectPoint.deviceConnectPoint(cP2),
parseVlan(cP2InnerVlan), parseVlan(cP2OuterVlan));
- } catch (Exception e) {
- print("Exception while parsing L2TunnelPolicy : {}", e);
+ } catch (IllegalArgumentException e) {
+ log.error("Exception while parsing L2TunnelPolicy : \n\t %s", e.getMessage());
+ print("Exception while parsing L2TunnelPolicy : \n\t %s", e.getMessage());
return;
}
L2TunnelDescription pw = new DefaultL2TunnelDescription(tun, policy);
L2TunnelHandler.Result res = srService.addPseudowire(pw);
+ log.info("Deploying pseudowire {} via the command line.", pw);
switch (res) {
case WRONG_PARAMETERS:
print("Pseudowire could not be added , error in the parameters : \n\t%s",
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 362ebbb..d0f217d 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
@@ -49,11 +49,13 @@
int pwIntId;
try {
pwIntId = parsePwId(pwId);
- } catch (Exception e) {
- print("Exception while parsing pseudowire id : {}", e);
+ } catch (IllegalArgumentException e) {
+ log.error("Exception while parsing pseudowire id : \n\t %s", e.getMessage());
+ print("Exception while parsing pseudowire id : \n\t %s", e.getMessage());
return;
}
+ log.info("Removing pseudowire {} from the command line.", pwIntId);
L2TunnelHandler.Result res = mngr.removePseudowire(pwIntId);
switch (res) {
case WRONG_PARAMETERS:
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 eb18381..a8b94e0 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
@@ -52,8 +52,10 @@
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.DistributedLock;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageException;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -74,10 +76,11 @@
import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
/**
- * Handles pwaas related events.
+ * Handler for pseudowire management.
*/
public class DefaultL2TunnelHandler implements L2TunnelHandler {
+ private static final String LOCK_NAME = "l2-tunnel-handler-lock";
private static final Logger log = LoggerFactory.getLogger(DefaultL2TunnelHandler.class);
private final SegmentRoutingManager srManager;
@@ -118,6 +121,13 @@
private final DistributedSet<VlanId> vlanStore;
/**
+ * Lock used when creating or removing pseudowires.
+ */
+ private final DistributedLock pwLock;
+
+ private static final long LOCK_TIMEOUT = 2000;
+
+ /**
* Used for determining transport vlans for leaf-spine.
*/
private short transportVlanUpper = 4093, transportVlanLower = 3500;
@@ -188,6 +198,11 @@
.build()))
.build()
.asDistributedSet();
+
+ pwLock = srManager.storageService.lockBuilder()
+ .withName(LOCK_NAME)
+ .build()
+ .asLock(LOCK_TIMEOUT);
}
/**
@@ -281,10 +296,7 @@
private Result manageIntermediateFiltering(L2TunnelDescription pw, boolean leafSpinePw) {
// only leaf-spine-spine should need intermediate rules for now
- if (!leafSpinePw) {
- return Result.SUCCESS;
- }
- if (pw.l2Tunnel().pathUsed().size() != 2) {
+ if (!leafSpinePw || (pw.l2Tunnel().pathUsed().size() != 2)) {
return Result.SUCCESS;
}
@@ -292,7 +304,7 @@
DeviceId intermediateSpineId = pw.l2Tunnel().pathUsed().get(0).dst().deviceId();
L2Tunnel l2Tunnel = pw.l2Tunnel();
- log.info("Installing intermediate filtering rules for spine {} , for pseudowire {}",
+ log.debug("Installing intermediate filtering rules for spine {} , for pseudowire {}",
intermediateSpineId, pw.l2Tunnel().tunnelId());
MacAddress dstMac;
@@ -394,7 +406,7 @@
if (!spinePw) {
- log.info("Untagged transport with internal vlan {} for pseudowire!", UNTAGGED_TRANSPORT_VLAN);
+ log.debug("Untagged transport with internal vlan {} for pseudowire!", UNTAGGED_TRANSPORT_VLAN);
return UNTAGGED_TRANSPORT_VLAN;
} else {
for (short i = transportVlanUpper; i > transportVlanLower; i--) {
@@ -403,12 +415,12 @@
if (!vlanStore.contains(vlanToUse)) {
vlanStore.add(vlanToUse);
- log.info("Transport vlan {} for pseudowire!", vlanToUse);
+ log.debug("Transport vlan {} for pseudowire!", vlanToUse);
return vlanToUse;
}
}
- log.info("No available transport vlan found, pseudowire traffic will be carried untagged " +
+ log.warn("No available transport vlan found, pseudowire traffic will be carried untagged " +
"with internal vlan {}!", UNTAGGED_TRANSPORT_VLAN);
return UNTAGGED_TRANSPORT_VLAN;
}
@@ -455,6 +467,7 @@
*/
private boolean isValidPath(List<Link> path, boolean leafSpinePw) {
+ log.debug("Checking path validity for pseudowire.");
List<DeviceId> devices = getDevicesOnPath(path);
if (devices.size() < 2) {
log.error("Path size for pseudowire should be greater than 1!");
@@ -528,196 +541,202 @@
*/
public Result deployPseudowire(L2TunnelDescription pw) {
- Result result;
- long l2TunnelId;
-
- log.debug("Pseudowire with {} deployment started, check log for any errors in this process!",
- pw.l2Tunnel().tunnelId());
-
- l2TunnelId = pw.l2Tunnel().tunnelId();
- // The tunnel id cannot be 0.
- if (l2TunnelId == 0) {
- log.warn("Tunnel id id must be > 0");
- return Result.WRONG_PARAMETERS
- .appendError("Tunnel id id must be > 0");
- }
-
- result = verifyGlobalValidity(pw);
- if (result != SUCCESS) {
- log.error("Global validity for pseudowire {} is wrong!", l2TunnelId);
- return result;
- }
-
- // leafSpinePw determines if this is a leaf-leaf
- // or leaf-spine pseudowire
- boolean leafSpinePw;
- ConnectPoint cp1 = pw.l2TunnelPolicy().cP1();
- ConnectPoint cp2 = pw.l2TunnelPolicy().cP2();
try {
- // differentiate between leaf-leaf pseudowires and leaf-spine
- if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
- !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
- log.error("Can not deploy pseudowire from spine to spine!");
+ // take the lock
+ pwLock.lock();
+ Result result;
+ long l2TunnelId;
+ log.debug("Pseudowire with {} deployment started, check log for any errors in this process!",
+ pw.l2Tunnel().tunnelId());
+ l2TunnelId = pw.l2Tunnel().tunnelId();
+ // The tunnel id cannot be 0.
+ if (l2TunnelId == 0) {
+ log.warn("Tunnel id id must be > 0 in {}", l2TunnelId);
return Result.WRONG_PARAMETERS
- .appendError("Can not deploy pseudowire from spine to spine!");
- } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
- srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
- leafSpinePw = false;
- } else {
- leafSpinePw = true;
+ .appendError("Tunnel id id must be > 0");
}
- } catch (DeviceConfigNotFoundException e) {
- log.error("Device for pseudowire connection points does not exist in the configuration");
- return Result.INTERNAL_ERROR
- .appendError("Device for pseudowire connection points does not exist in the configuration");
+
+ result = verifyGlobalValidity(pw);
+ if (result != SUCCESS) {
+ log.error("Global validity for pseudowire {} is wrong!", l2TunnelId);
+ return result;
+ }
+
+ // leafSpinePw determines if this is a leaf-leaf
+ // or leaf-spine pseudowire
+ boolean leafSpinePw;
+ ConnectPoint cp1 = pw.l2TunnelPolicy().cP1();
+ ConnectPoint cp2 = pw.l2TunnelPolicy().cP2();
+ try {
+ // differentiate between leaf-leaf pseudowires and leaf-spine
+ if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
+ !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
+ log.error("Can not deploy pseudowire {} from spine to spine!", l2TunnelId);
+ return Result.WRONG_PARAMETERS
+ .appendError("Can not deploy pseudowire from spine to spine!");
+ } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
+ srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
+ leafSpinePw = false;
+ } else {
+ leafSpinePw = true;
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ log.error("Device for pseudowire {} connection points does not exist in the configuration", l2TunnelId);
+ return Result.INTERNAL_ERROR
+ .appendError("Device for pseudowire connection points does not exist in the configuration");
+ }
+
+ // reverse the policy in order for leaf switch to be at CP1
+ // this will help us for re-using SRLinkWeigher for computing valid paths
+ L2TunnelPolicy reversedPolicy = reverseL2TunnelPolicy(pw.l2TunnelPolicy());
+ if (reversedPolicy == null) {
+ log.error("Error in reversing policy, device configuration was not found for pseudowire {}.",
+ l2TunnelId);
+ return INTERNAL_ERROR
+ .appendError("Device configuration not found when reversing the policy.");
+ }
+ pw.setL2TunnelPolicy(reversedPolicy);
+
+ // get path here, need to use the same for fwd and rev direction
+ List<Link> path = getPath(pw.l2TunnelPolicy().cP1(),
+ pw.l2TunnelPolicy().cP2());
+ if (path == null) {
+ log.error("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
+ return PATH_NOT_FOUND.appendError("No path between the connection points for pseudowire!");
+ }
+
+ Link fwdNextHop;
+ Link revNextHop;
+ if (!isValidPath(path, leafSpinePw)) {
+ log.error("Deploying process : Path for pseudowire {} is not valid", l2TunnelId);
+ return INTERNAL_ERROR.appendError("Internal error : path for pseudowire is not valid!");
+ }
+ // oneHope flag is used to determine if we need to
+ // install transit mpls rules
+ boolean oneHop = true;
+ if (path.size() > 1) {
+ oneHop = false;
+ }
+
+ fwdNextHop = path.get(0);
+ revNextHop = reverseLink(path.get(path.size() - 1));
+
+ pw.l2Tunnel().setPath(path);
+ pw.l2Tunnel().setTransportVlan(determineTransportVlan(leafSpinePw));
+
+ // next hops for next objectives
+ log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
+
+ VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
+ pw.l2TunnelPolicy().cP1InnerTag(),
+ pw.l2TunnelPolicy().cP2OuterTag(),
+ pw.l2TunnelPolicy().cP2InnerTag());
+ result = deployPseudoWireInit(pw.l2Tunnel(),
+ pw.l2TunnelPolicy().cP1(),
+ pw.l2TunnelPolicy().cP2(),
+ FWD,
+ fwdNextHop,
+ leafSpinePw,
+ oneHop,
+ egressVlan);
+ if (result != SUCCESS) {
+ log.error("Deploying process : Error in deploying pseudowire {} initiation for CP1", l2TunnelId);
+ return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire initiation for CP1");
+ }
+
+ result = deployPolicy(l2TunnelId,
+ pw.l2TunnelPolicy().cP1(),
+ pw.l2TunnelPolicy().cP1InnerTag(),
+ pw.l2TunnelPolicy().cP1OuterTag(),
+ egressVlan,
+ result.getNextId());
+ if (result != SUCCESS) {
+ log.error("Deploying process : Error in deploying pseudowire {} policy for CP1", l2TunnelId);
+ return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire policy for CP1");
+ }
+
+ PortNumber termPort = pw.l2Tunnel().pathUsed().get(pw.l2Tunnel().pathUsed().size() - 1).dst().port();
+ result = deployPseudoWireTerm(pw.l2Tunnel(),
+ pw.l2TunnelPolicy().cP2(),
+ egressVlan,
+ FWD,
+ leafSpinePw,
+ oneHop,
+ termPort);
+
+ if (result != SUCCESS) {
+ log.error("Deploying process : Error in deploying pseudowire {} termination for CP1", l2TunnelId);
+ return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP1");
+ }
+
+ // We establish the reverse tunnel.
+ log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);
+ egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
+ pw.l2TunnelPolicy().cP2InnerTag(),
+ pw.l2TunnelPolicy().cP1OuterTag(),
+ pw.l2TunnelPolicy().cP1InnerTag());
+
+ result = deployPseudoWireInit(pw.l2Tunnel(),
+ pw.l2TunnelPolicy().cP2(),
+ pw.l2TunnelPolicy().cP1(),
+ REV,
+ revNextHop,
+ leafSpinePw,
+ oneHop,
+ egressVlan);
+ if (result != SUCCESS) {
+ log.error("Deploying process : Error in deploying pseudowire {} initiation for CP2", l2TunnelId);
+ return Result.INTERNAL_ERROR
+ .appendError("Error in deploying pseudowire initiation for CP2");
+ }
+
+ result = deployPolicy(l2TunnelId,
+ pw.l2TunnelPolicy().cP2(),
+ pw.l2TunnelPolicy().cP2InnerTag(),
+ pw.l2TunnelPolicy().cP2OuterTag(),
+ egressVlan,
+ result.getNextId());
+ if (result != SUCCESS) {
+ log.error("Deploying process : Error in deploying policy {} for CP2", l2TunnelId);
+ return Result.INTERNAL_ERROR
+ .appendError("Deploying process : Error in deploying policy for CP2");
+ }
+
+ termPort = pw.l2Tunnel().pathUsed().get(0).src().port();
+ result = deployPseudoWireTerm(pw.l2Tunnel(),
+ pw.l2TunnelPolicy().cP1(),
+ egressVlan,
+ REV,
+ leafSpinePw,
+ oneHop,
+ termPort);
+
+ if (result != SUCCESS) {
+ log.error("Deploying process : Error in deploying pseudowire {} termination for CP2", l2TunnelId);
+ return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP2");
+ }
+
+ result = manageIntermediateFiltering(pw, leafSpinePw);
+ if (result != SUCCESS) {
+ log.error("Deploying process : Error in installing intermediate rules for " +
+ "tagged transport for pseudowire {}", l2TunnelId);
+ return Result.INTERNAL_ERROR.appendError("Error in installing intermediate rules for tagged transport");
+ }
+
+ log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);
+
+ // Populate stores as the final step of the process
+ l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
+ l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());
+
+ return Result.SUCCESS;
+ } catch (StorageException.Timeout e) {
+ log.error("Can not acquire distributed lock for pseudowire {}!", pw.l2Tunnel().tunnelId());
+ return Result.INTERNAL_ERROR.appendError("Can not acquire distributed lock!");
+ } finally {
+ // release the lock
+ pwLock.unlock();
}
-
- // reverse the policy in order for leaf switch to be at CP1
- // this will help us for re-using SRLinkWeigher for computing valid paths
- L2TunnelPolicy reversedPolicy = reverseL2TunnelPolicy(pw.l2TunnelPolicy());
- if (reversedPolicy == null) {
- log.error("Error in reversing policy, device configuration was not found!");
- return INTERNAL_ERROR
- .appendError("Device configuration not found when reversing the policy.");
- }
- pw.setL2TunnelPolicy(reversedPolicy);
-
- // get path here, need to use the same for fwd and rev direction
- List<Link> path = getPath(pw.l2TunnelPolicy().cP1(),
- pw.l2TunnelPolicy().cP2());
- if (path == null) {
- log.error("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
- return PATH_NOT_FOUND.appendError("No path between the connection points for pseudowire!");
- }
-
- Link fwdNextHop;
- Link revNextHop;
- if (!isValidPath(path, leafSpinePw)) {
- log.error("Deploying process : Path for pseudowire {} is not valid",
- l2TunnelId);
- return INTERNAL_ERROR.appendError("Internal error : path for pseudowire is not valid!");
- }
-
- // oneHope flag is used to determine if we need to
- // install transit mpls rules
- boolean oneHop = true;
- if (path.size() > 1) {
- oneHop = false;
- }
-
- fwdNextHop = path.get(0);
- revNextHop = reverseLink(path.get(path.size() - 1));
-
- pw.l2Tunnel().setPath(path);
- pw.l2Tunnel().setTransportVlan(determineTransportVlan(leafSpinePw));
-
- // next hops for next objectives
- log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
-
- VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
- pw.l2TunnelPolicy().cP1InnerTag(),
- pw.l2TunnelPolicy().cP2OuterTag(),
- pw.l2TunnelPolicy().cP2InnerTag());
- // We establish the tunnel.
- // result.nextId will be used in fwd
- result = deployPseudoWireInit(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP1(),
- pw.l2TunnelPolicy().cP2(),
- FWD,
- fwdNextHop,
- leafSpinePw,
- oneHop,
- egressVlan);
- if (result != SUCCESS) {
- log.info("Deploying process : Error in deploying pseudowire initiation for CP1");
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire initiation for CP1");
- }
-
- // We create the policy.
- result = deployPolicy(l2TunnelId,
- pw.l2TunnelPolicy().cP1(),
- pw.l2TunnelPolicy().cP1InnerTag(),
- pw.l2TunnelPolicy().cP1OuterTag(),
- egressVlan,
- result.getNextId());
- if (result != SUCCESS) {
- log.info("Deploying process : Error in deploying pseudowire policy for CP1");
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire policy for CP1");
- }
-
- // We terminate the tunnel
- result = deployPseudoWireTerm(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP2(),
- egressVlan,
- FWD,
- leafSpinePw,
- oneHop);
-
- if (result != SUCCESS) {
- log.info("Deploying process : Error in deploying pseudowire termination for CP1");
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP1");
- }
-
- log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);
-
- egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
- pw.l2TunnelPolicy().cP2InnerTag(),
- pw.l2TunnelPolicy().cP1OuterTag(),
- pw.l2TunnelPolicy().cP1InnerTag());
-
- // We establish the reverse tunnel.
- result = deployPseudoWireInit(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP2(),
- pw.l2TunnelPolicy().cP1(),
- REV,
- revNextHop,
- leafSpinePw,
- oneHop,
- egressVlan);
- if (result != SUCCESS) {
- log.info("Deploying process : Error in deploying pseudowire initiation for CP2");
- return Result.INTERNAL_ERROR
- .appendError("Error in deploying pseudowire initiation for CP2");
- }
-
-
- result = deployPolicy(l2TunnelId,
- pw.l2TunnelPolicy().cP2(),
- pw.l2TunnelPolicy().cP2InnerTag(),
- pw.l2TunnelPolicy().cP2OuterTag(),
- egressVlan,
- result.getNextId());
- if (result != SUCCESS) {
- log.info("Deploying process : Error in deploying policy for CP2");
- return Result.INTERNAL_ERROR
- .appendError("Deploying process : Error in deploying policy for CP2");
- }
-
- result = deployPseudoWireTerm(pw.l2Tunnel(),
- pw.l2TunnelPolicy().cP1(),
- egressVlan,
- REV,
- leafSpinePw,
- oneHop);
-
- if (result != SUCCESS) {
- log.info("Deploying process : Error in deploying pseudowire termination for CP2");
- return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP2");
- }
-
- result = manageIntermediateFiltering(pw, leafSpinePw);
- if (result != SUCCESS) {
- log.info("Deploying process : Error in installing intermediate rules for tagged transport");
- return Result.INTERNAL_ERROR.appendError("Error in installing intermediate rules for tagged transport");
- }
-
- log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);
-
- // Populate stores as the final step of the process
- l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
- l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());
-
- return Result.SUCCESS;
}
@Override
@@ -760,7 +779,7 @@
CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
if (l2TunnelId == 0) {
- log.warn("Removal process : Tunnel id cannot be 0");
+ log.error("Removal process : Tunnel id cannot be 0");
return Result.WRONG_PARAMETERS.appendError("Pseudowire id can not be 0.");
}
@@ -825,10 +844,13 @@
fwdTermNextFuture.thenAcceptAsync(status -> {
if (status == null) {
+ PortNumber termPort = pwToRemove.l2Tunnel().pathUsed()
+ .get(pwToRemove.l2Tunnel().pathUsed().size() - 1).dst().port();
tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
pwToRemove.l2TunnelPolicy().cP2(),
null,
- FWD);
+ FWD,
+ termPort);
}
});
}
@@ -861,10 +883,12 @@
revTermNextFuture.thenAcceptAsync(status -> {
if (status == null) {
+ PortNumber termPort = pwToRemove.l2Tunnel().pathUsed().get(0).src().port();
tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
pwToRemove.l2TunnelPolicy().cP1(),
null,
- REV);
+ REV,
+ termPort);
}
});
}
@@ -883,14 +907,25 @@
*/
public Result tearDownPseudowire(long l2TunnelId) {
- if (checkIfPwExists(l2TunnelId, true) == Result.SUCCESS) {
- return tearDownConnectionPoints(l2TunnelId, true, true, true);
- } else if (checkIfPwExists(l2TunnelId, false) == Result.SUCCESS) {
- return tearDownConnectionPoints(l2TunnelId, true, true, false);
- } else {
- return Result.WRONG_PARAMETERS.appendError("Pseudowire with "
- + l2TunnelId
- + " did not reside in any store!");
+ try {
+ // take the lock
+ pwLock.lock();
+
+ if (checkIfPwExists(l2TunnelId, true) == Result.SUCCESS) {
+ return tearDownConnectionPoints(l2TunnelId, true, true, true);
+ } else if (checkIfPwExists(l2TunnelId, false) == Result.SUCCESS) {
+ return tearDownConnectionPoints(l2TunnelId, true, true, false);
+ } else {
+ return Result.WRONG_PARAMETERS.appendError("Pseudowire with "
+ + l2TunnelId
+ + " did not reside in any store!");
+ }
+ } catch (StorageException.Timeout e) {
+ log.error("Can not acquire distributed lock for pseudowire {}!", l2TunnelId);
+ return Result.INTERNAL_ERROR.appendError("Can not acquire distributed lock!");
+ } finally {
+ // release the lock
+ pwLock.unlock();
}
}
@@ -918,16 +953,17 @@
* @param ingress the ingress point
* @param ingressInner the ingress inner tag
* @param ingressOuter the ingress outer tag
- * @param nextId the next objective id
* @param egressVlan Vlan-id to set, depends on ingress vlan
* combinations. For example, if pw is double tagged
* then this is the value of the outer vlan, if single
* tagged then it is the new value of the single tag.
* Should be None for untagged traffic.
+ * @param nextId the next objective id
* @return the result of the operation
*/
private Result deployPolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner,
VlanId ingressOuter, VlanId egressVlan, int nextId) {
+ log.debug("Starting deploying policy for pseudowire {}.", tunnelId);
List<Objective> objectives = Lists.newArrayList();
// We create the forwarding objective for supporting
@@ -937,8 +973,9 @@
ObjectiveContext context = new DefaultObjectiveContext((objective) ->
log.debug("FwdObj for tunnel {} populated", tunnelId),
(objective, error) ->
- log.warn("Failed to populate fwdrObj " +
- "for tunnel {}", tunnelId, error));
+ log.warn("Failed to populate fwdObj " +
+ "for tunnel {} : {}",
+ tunnelId, error));
objectives.add(fwdBuilder.add(context));
// We create the filtering objective to define the
@@ -955,7 +992,8 @@
// We create and add objective context.
context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for tunnel {} populated", tunnelId),
(objective, error) -> log.warn("Failed to populate filterObj for " +
- "tunnel {}", tunnelId, error));
+ "tunnel {} : {}",
+ tunnelId, error));
objectives.add(filtBuilder.add(context));
for (Objective objective : objectives) {
@@ -984,9 +1022,10 @@
private Result deployPseudoWireInit(L2Tunnel l2Tunnel, ConnectPoint ingress,
ConnectPoint egress, Direction direction,
Link nextHop, boolean spinePw, boolean oneHop, VlanId termVlanId) {
-
+ log.debug("Started deploying init next objectives for pseudowire {} for tunnel {} -> {}.",
+ l2Tunnel.tunnelId(), ingress, egress);
if (nextHop == null) {
- log.warn("No path between ingress and egress cps for tunnel {}", l2Tunnel.tunnelId());
+ log.warn("No path between ingress and egress connection points for tunnel {}", l2Tunnel.tunnelId());
return WRONG_PARAMETERS;
}
@@ -1046,10 +1085,15 @@
* @param egressVlan the expected vlan at egress
* @param direction the direction
* @param spinePw if the pseudowire involves a spine switch
+ * @param inputTermPort the input port at the termination point for the pseudowire, used for installing special
+ * filtering rules at the termination
* @return the result of the operation
*/
private Result deployPseudoWireTerm(L2Tunnel l2Tunnel, ConnectPoint egress,
- VlanId egressVlan, Direction direction, boolean spinePw, boolean oneHop) {
+ VlanId egressVlan, Direction direction,
+ boolean spinePw, boolean oneHop, PortNumber inputTermPort) {
+ log.debug("Started deploying termination objectives for pseudowire {} , direction {}.",
+ l2Tunnel.tunnelId(), direction == FWD ? "forward" : "reverse");
// We create the group relative to the termination.
NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
@@ -1092,7 +1136,7 @@
context = new DefaultObjectiveContext((objective) -> log.debug("FwdObj for tunnel termination {} populated",
l2Tunnel.tunnelId()),
(objective, error) -> log.warn("Failed to populate fwdrObj" +
- " for tunnel termination {}",
+ " for tunnel termination {} : {}",
l2Tunnel.tunnelId(), error));
srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.add(context));
log.debug("Creating new FwdObj for termination NextObj with id={} for tunnel {}",
@@ -1100,16 +1144,6 @@
if (spinePw) {
- // determine the input port at the
- PortNumber inPort;
-
- if (egress.deviceId().
- equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
- inPort = l2Tunnel.pathUsed().get(0).dst().port();
- } else {
- inPort = l2Tunnel.pathUsed().get(0).src().port();
- }
-
MacAddress dstMac;
try {
dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
@@ -1121,10 +1155,10 @@
log.info("Populating filtering objective for pseudowire transport" +
" with vlan = {}, port = {}, mac = {}",
l2Tunnel.transportVlan(),
- inPort,
+ inputTermPort,
dstMac);
FilteringObjective.Builder filteringObjectiveBuilder =
- createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
+ createNormalPipelineFiltObjective(inputTermPort, l2Tunnel.transportVlan(), dstMac);
context = new DefaultObjectiveContext(( objective ) ->
log.debug("Special filtObj for " + "for {} populated",
l2Tunnel.tunnelId()),
@@ -1138,7 +1172,7 @@
srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.add(context));
log.debug("Creating new special FiltObj for termination point with tunnel {} for port {}",
l2Tunnel.tunnelId(),
- inPort);
+ inputTermPort);
}
return SUCCESS;
@@ -1156,7 +1190,7 @@
VlanId vlanId,
MacAddress dstMac) {
- log.info("Creating filtering objective for pseudowire transport with vlan={}, port={}, mac={}",
+ log.debug("Creating filtering objective for pseudowire intermediate transport with vlan={}, port={}, mac={}",
vlanId,
inPort,
dstMac);
@@ -1185,7 +1219,7 @@
*/
private FilteringObjective.Builder createFiltObjective(PortNumber inPort, VlanId innerTag, VlanId outerTag) {
- log.info("Creating filtering objective for vlans {} / {}", outerTag, innerTag);
+ log.debug("Creating connection point filtering objective for vlans {} / {}", outerTag, innerTag);
return DefaultFilteringObjective
.builder()
.withKey(Criteria.matchInPort(inPort))
@@ -1208,6 +1242,8 @@
private ForwardingObjective.Builder createTermFwdObjective(MplsLabel pwLabel, long tunnelId,
PortNumber egressPort, int nextId) {
+ log.debug("Creating forwarding objective for termination for tunnel {} : pwLabel {}, egressPort {}, nextId {}",
+ tunnelId, pwLabel, egressPort, nextId);
TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder trafficTreatment = DefaultTrafficTreatment.builder();
// The flow has to match on the pw label and bos
@@ -1243,6 +1279,7 @@
*/
private ForwardingObjective.Builder createInitFwdObjective(long tunnelId, PortNumber inPort, int nextId) {
+ log.debug("Creating forwarding objective for tunnel {} : Port {} , nextId {}", tunnelId, inPort, nextId);
TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
// The flow has to match on the mpls logical
@@ -1281,6 +1318,9 @@
ConnectPoint dstCp, L2Tunnel l2Tunnel,
DeviceId egressId, boolean leafSpinePw,
boolean oneHop, VlanId termVlanId) {
+ log.debug("Creating {} next objective for pseudowire {}.",
+ pipeline == TERMINATION ? "termination" : "inititation");
+
NextObjective.Builder nextObjBuilder;
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (pipeline == INITIATION) {
@@ -1291,7 +1331,7 @@
// The pw label is the bottom of stack. It has to
// be different -1.
if (l2Tunnel.pwLabel().toInt() == MplsLabel.MAX_MPLS) {
- log.warn("Pw label not configured");
+ log.error("Pw label not configured");
return null;
}
treatmentBuilder.pushMpls();
@@ -1317,7 +1357,7 @@
srLabel = MplsLabel.mplsLabel(srManager.deviceConfiguration().getPWRoutingLabel(egressId));
} catch (DeviceConfigNotFoundException e) {
- log.warn("Sr label for pw traffic not configured");
+ log.error("Sr label for pw traffic not configured");
return null;
}
@@ -1332,7 +1372,7 @@
try {
ingressMac = srManager.deviceConfiguration().getDeviceMac(srcCp.deviceId());
} catch (DeviceConfigNotFoundException e) {
- log.warn("Was not able to find the ingress mac");
+ log.error("Was not able to find the ingress mac");
return null;
}
treatmentBuilder.setEthSrc(ingressMac);
@@ -1340,7 +1380,7 @@
try {
neighborMac = srManager.deviceConfiguration().getDeviceMac(dstCp.deviceId());
} catch (DeviceConfigNotFoundException e) {
- log.warn("Was not able to find the neighbor mac");
+ log.error("Was not able to find the neighbor mac");
return null;
}
treatmentBuilder.setEthDst(neighborMac);
@@ -1348,7 +1388,7 @@
// if true we need to pop the vlan because
// we instantiate a leaf to leaf pseudowire
if (!leafSpinePw) {
- log.info("We should carry this traffic UNTAGGED!");
+ log.debug("We should carry traffic UNTAGGED for pseudowire {}", l2Tunnel.tunnelId());
treatmentBuilder.popVlan();
}
@@ -1385,6 +1425,8 @@
* current SRLinkWeigher
*/
private L2TunnelPolicy reverseL2TunnelPolicy(L2TunnelPolicy policy) {
+
+ log.debug("Reversing policy for pseudowire.");
try {
// if cp1 is a leaf, just return
if (srManager.deviceConfiguration().isEdgeDevice(policy.cP1().deviceId())) {
@@ -1469,7 +1511,7 @@
String key = generateKey(tunnelId, direction);
if (!l2InitiationNextObjStore.containsKey(key)) {
- log.warn("Abort delete of policy for tunnel {}: next does not exist in the store", tunnelId);
+ log.error("Abort delete of policy for tunnel {}: next does not exist in the store", tunnelId);
if (future != null) {
future.complete(null);
}
@@ -1491,7 +1533,7 @@
@Override
public void onError(Objective objective, ObjectiveError error) {
- log.warn("Failed to remove previous fwdObj for policy {}: {}", tunnelId, error);
+ log.error("Failed to remove previous fwdObj for policy {}: {}", tunnelId, error);
if (future != null) {
future.complete(error);
}
@@ -1531,10 +1573,11 @@
*/
private void tearDownPseudoWireInit(long l2TunnelId, ConnectPoint ingress,
CompletableFuture<ObjectiveError> future, Direction direction) {
-
+ log.debug("Starting tearing dowing initation of pseudowire {} for direction {}.",
+ l2TunnelId, direction == FWD ? "forward" : "reverse");
String key = generateKey(l2TunnelId, direction);
if (!l2InitiationNextObjStore.containsKey(key)) {
- log.info("Abort delete of {} for {}: next does not exist in the store", INITIATION, key);
+ log.error("Abort delete of {} for {}: next does not exist in the store", INITIATION, key);
if (future != null) {
future.complete(null);
}
@@ -1581,11 +1624,13 @@
private void tearDownPseudoWireTerm(L2Tunnel l2Tunnel,
ConnectPoint egress,
CompletableFuture<ObjectiveError> future,
- Direction direction) {
-
+ Direction direction,
+ PortNumber inPort) {
+ log.debug("Starting tearing down termination for pseudowire {} direction {}.",
+ l2Tunnel.tunnelId(), direction == FWD ? "forward" : "reverse");
String key = generateKey(l2Tunnel.tunnelId(), direction);
if (!l2TerminationNextObjStore.containsKey(key)) {
- log.info("Abort delete of {} for {}: next does not exist in the store", TERMINATION, key);
+ log.error("Abort delete of {} for {}: next does not exist in the store", TERMINATION, key);
if (future != null) {
future.complete(null);
}
@@ -1640,21 +1685,11 @@
// spine-spine pws
if (!l2Tunnel.transportVlan().equals(UNTAGGED_TRANSPORT_VLAN)) {
- // determine the input port at the
- PortNumber inPort;
-
- if (egress.deviceId().
- equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
- inPort = l2Tunnel.pathUsed().get(0).dst().port();
- } else {
- inPort = l2Tunnel.pathUsed().get(0).src().port();
- }
-
MacAddress dstMac;
try {
dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
} catch (Exception e) {
- log.info("Device not found in configuration, no programming of MAC address");
+ log.error("Device not found in configuration, no programming of MAC address");
dstMac = null;
}
@@ -1667,9 +1702,11 @@
createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
context = new DefaultObjectiveContext(( objective ) ->
log.debug("Special filtObj for " + "for {} removed",
- l2Tunnel.tunnelId()), ( objective, error ) ->
- log.warn("Failed to populate " + "special filtObj " +
- "rule for {}: {}", l2Tunnel.tunnelId(), error));
+ l2Tunnel.tunnelId()),
+ ( objective, error ) ->
+ log.warn("Failed to populate " + "special filtObj " +
+ "rule for {}: {}",
+ l2Tunnel.tunnelId(), error));
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
filteringObjectiveBuilder.withMeta(treatment.build());
srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.remove(context));
@@ -1692,5 +1729,4 @@
private String generateKey(long tunnelId, Direction direction) {
return String.format("%s-%s", tunnelId, direction);
}
-
}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
index f4a71ab..1475198 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/pwaas/PwaasUtil.java
@@ -32,6 +32,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static com.google.common.base.Preconditions.checkArgument;
+
/**
* Utility class with static methods that help
* parse pseudowire related information and also
@@ -63,12 +65,7 @@
} 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;
- }
+ return VlanId.vlanId(vlan);
}
}
@@ -78,11 +75,8 @@
* @return the L2Mode if input is correct
*/
public static L2Mode parseMode(String mode) {
-
- if (!mode.equals("RAW") && !mode.equals("TAGGED")) {
- return null;
- }
-
+ checkArgument(mode.equals("RAW") || mode.equals("TAGGED"),
+ "Invalid pseudowire mode of operation, should be TAGGED or RAW.");
return L2Mode.valueOf(mode);
}
@@ -93,13 +87,7 @@
* @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;
- }
+ return MplsLabel.mplsLabel(label);
}
/**
@@ -109,14 +97,9 @@
* @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;
- }
+ return Integer.parseInt(id);
}
-
/**
* Helper method to verify if the tunnel is whether or not
* supported.
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
index 00d20a7..8abfa71 100644
--- 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
@@ -15,6 +15,7 @@
*/
package org.onosproject.segmentrouting.web;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.tuple.Pair;
@@ -27,9 +28,11 @@
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.L2Mode;
+import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
import java.util.List;
import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
@@ -69,13 +72,11 @@
result.put(CP1_INNER_TAG, pseudowire.l2TunnelPolicy().cP1InnerTag().toString());
result.put(CP1_OUTER_TAG, pseudowire.l2TunnelPolicy().cP1OuterTag().toString());
-
-
result.put(CP2_INNER_TAG, pseudowire.l2TunnelPolicy().cP2InnerTag().toString());
result.put(CP2_OUTER_TAG, pseudowire.l2TunnelPolicy().cP2OuterTag().toString());
+ result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
result.put(MODE, pseudowire.l2Tunnel().pwMode() == L2Mode.RAW ? "RAW" : "TAGGED");
- result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
result.put(PW_LABEL, pseudowire.l2Tunnel().pwLabel().toString());
return result;
@@ -101,25 +102,77 @@
}
/**
- * Returns a JSON containing the failed pseudowires and the reason that its one failed.
+ * Encoded in an Object Node the undecoed pseudowire and the specificError it failed.
+ *
+ * @param failedPW The failed pseudowire in json format
+ * @param specificError The specificError it failed
+ * @param context Our context
+ * @return A node containing the information we provided
+ */
+ public ObjectNode encodeError(JsonNode failedPW, String specificError,
+ CodecContext context) {
+ ObjectNode result = context.mapper().createObjectNode();
+
+ result.set(FAILED_PW, failedPW);
+ result.put(REASON, specificError);
+
+ return result;
+ }
+
+ /**
+ * Returns a JSON containing the failed pseudowires and the reason that they failed.
*
* @param failedPws Pairs of pws and reasons.
+ * @param undecodedPws Pairs of pws that we could not decode with reason being illegal arguments.
* @param context The context
* @return ObjectNode representing the json to return
*/
public ObjectNode encodeFailedPseudowires(
List<Pair<DefaultL2TunnelDescription, String>> failedPws,
+ List<Pair<JsonNode, String>> undecodedPws,
CodecContext context) {
ArrayNode failedNodes = context.mapper().createArrayNode();
failedPws.stream()
.forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
+ undecodedPws.stream()
+ .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
final ObjectNode toReturn = context.mapper().createObjectNode();
toReturn.set(FAILED_PWS, failedNodes);
return toReturn;
}
/**
+ *
+ * @param json The json containing the pseudowires.
+ * @param context The context
+ * @return A pair of lists.
+ * First list contains pseudowires that we were not able to decode
+ * along with the reason we could not decode them.
+ * Second list contains successfully decoded pseudowires which we are
+ * going to instantiate.
+ */
+ public Pair<List<Pair<JsonNode, String>>, List<L2TunnelDescription>> decodePws(ArrayNode json,
+ CodecContext context) {
+
+ List<L2TunnelDescription> decodedPws = new ArrayList<>();
+ List<Pair<JsonNode, String>> notDecodedPws = new ArrayList<>();
+ for (JsonNode node : json) {
+ DefaultL2TunnelDescription l2Description;
+ try {
+ l2Description = decode((ObjectNode) node, context);
+ decodedPws.add(l2Description);
+ } catch (IllegalArgumentException e) {
+ // the reason why we could not decode this pseudowire is encoded in the
+ // exception, we need to store it now
+ notDecodedPws.add(Pair.of(node, e.getMessage()));
+ }
+ }
+
+ return Pair.of(notDecodedPws, decodedPws);
+ }
+
+ /**
* Decodes a json containg a single field with the pseudowire id.
*
* @param json Json to decode.
@@ -127,8 +180,10 @@
*/
public static Integer decodeId(ObjectNode json) {
- Integer id = parsePwId(json.path(PW_ID).asText());
- if (id == null) {
+ Integer id;
+ try {
+ id = parsePwId(json.path(PW_ID).asText());
+ } catch (IllegalArgumentException e) {
log.error("Pseudowire id is not an integer!");
return null;
}
@@ -139,66 +194,25 @@
@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;
- }
+ cP1 = ConnectPoint.deviceConnectPoint(json.path(CP1).asText());
+ cP2 = ConnectPoint.deviceConnectPoint(json.path(CP2).asText());
- 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;
- }
+ VlanId cP1InnerVlan, cP1OuterVlan, cP2InnerVlan, cP2OuterVlan, sdTag;
+ cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText());
+ cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText());
+ cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText());
+ cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText());
+ sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText());
L2Mode mode = parseMode(json.path(MODE).asText());
- 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,
+ DefaultL2Tunnel l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel);
+ DefaultL2TunnelPolicy l2Policy = new DefaultL2TunnelPolicy(id, cP1, cP1InnerVlan, cP1OuterVlan,
cP2, cP2InnerVlan, cP2OuterVlan);
-
return new DefaultL2TunnelDescription(l2Tunnel, l2Policy);
}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireWebResource.java
index 854697b..4867c90 100644
--- 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
@@ -24,6 +24,7 @@
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.segmentrouting.SegmentRoutingService;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
+import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.L2Tunnel;
import org.onosproject.segmentrouting.pwaas.L2TunnelHandler;
@@ -111,28 +112,36 @@
ObjectMapper mapper = new ObjectMapper();
ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
+ List<Pair<DefaultL2TunnelDescription, String>> failed = new ArrayList<>();
+ List<Pair<JsonNode, String>> undecoded = new ArrayList<>();
- DefaultL2TunnelDescription pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
- if (pseudowire == null) {
- return Response.serverError().status(Response.Status.BAD_REQUEST).build();
+ DefaultL2TunnelDescription pseudowire;
+ try {
+ pseudowire = PSEUDOWIRE_CODEC.decode(pseudowireJson, this);
+
+ // pseudowire decoded, try to instantiate it, if we fail add it to failed list
+ long tunId = pseudowire.l2Tunnel().tunnelId();
+ log.debug("Creating pseudowire {} from rest api!", tunId);
+
+ L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
+ if (res != L2TunnelHandler.Result.SUCCESS) {
+ log.error("Could not create pseudowire {} : {}", pseudowire.l2Tunnel().tunnelId(),
+ res.getSpecificError());
+ failed.add(Pair.of(pseudowire, res.getSpecificError()));
+ }
+ } catch (IllegalArgumentException e) {
+ log.debug("Pseudowire could not be decoded : {}", e.getMessage());
+ undecoded.add(Pair.of(pseudowireJson, e.getMessage()));
}
- long tunId = pseudowire.l2Tunnel().tunnelId();
- log.debug("Creating pseudowire {} from rest api!", tunId);
-
- L2TunnelHandler.Result res = srService.addPseudowire(pseudowire);
- switch (res) {
- case WRONG_PARAMETERS:
- case CONFIGURATION_ERROR:
- case PATH_NOT_FOUND:
- case INTERNAL_ERROR:
- log.error("Pseudowire {} could not be added : {}", tunId, res.getSpecificError());
- 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();
+ if ((failed.size() == 0) && (undecoded.size() == 0)) {
+ // pseudowire instantiated correctly
+ return Response.ok().build();
+ } else {
+ // failed to decode or instantiate pseudowire, return the reason
+ PseudowireCodec pwCodec = new PseudowireCodec();
+ ObjectNode result = pwCodec.encodeFailedPseudowires(failed, undecoded, this);
+ return Response.serverError().entity(result).build();
}
}
@@ -152,33 +161,36 @@
ObjectMapper mapper = new ObjectMapper();
ObjectNode pseudowireJson = readTreeFromStream(mapper, input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
- List<DefaultL2TunnelDescription> pseudowires;
+ Pair<List<Pair<JsonNode, String>>, List<L2TunnelDescription>> pseudowires;
try {
ArrayNode pseudowiresArray = nullIsIllegal((ArrayNode) pseudowireJson.get(PWS), PWS_KEY_ERROR);
- pseudowires = PSEUDOWIRE_CODEC.decode(pseudowiresArray, this);
+ // get two lists, first one contains pseudowires that we were unable to decode
+ // that have faulty arguments, second one contains pseudowires that we decoded
+ // succesfully
+ pseudowires = PSEUDOWIRE_CODEC.decodePws(pseudowiresArray, this);
} catch (ItemNotFoundException e) {
return Response.serverError().status(Response.Status.BAD_REQUEST).build();
}
log.debug("Creating pseudowires {} from rest api!", pseudowires);
List<Pair<DefaultL2TunnelDescription, String>> failed = new ArrayList<>();
-
- for (DefaultL2TunnelDescription pw : pseudowires) {
+ for (L2TunnelDescription pw : pseudowires.getRight()) {
L2TunnelHandler.Result res = srService.addPseudowire(pw);
- if (!(res == L2TunnelHandler.Result.SUCCESS)) {
- log.trace("Could not create pseudowire {} : {}", pw.l2Tunnel().tunnelId(), res.getSpecificError());
- failed.add(Pair.of(pw, res.getSpecificError()));
+ if (res != L2TunnelHandler.Result.SUCCESS) {
+ log.error("Could not create pseudowire {} : {}", pw.l2Tunnel().tunnelId(), res.getSpecificError());
+ failed.add(Pair.of((DefaultL2TunnelDescription) pw, res.getSpecificError()));
}
}
+ List<Pair<JsonNode, String>> undecodedPws = pseudowires.getLeft();
- if (failed.size() == 0) {
- // all pseudowires were instantiated
+ if ((failed.size() == 0) && (undecodedPws.size() == 0)) {
+ // all pseudowires were decoded and instantiated succesfully
return Response.ok().build();
} else {
PseudowireCodec pwCodec = new PseudowireCodec();
// some failed, need to report them to user
- ObjectNode result = pwCodec.encodeFailedPseudowires(failed, this);
+ ObjectNode result = pwCodec.encodeFailedPseudowires(failed, undecodedPws, this);
return Response.serverError().entity(result).build();
}
}