mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-05 12:16:13 +02:00
[ONOS-7262] Cfm improvements to allow RMeps and Mds and Mas to be added and deleted
Change-Id: Ibffb13d046bfb29dbe88de7b558c95fbf9db046d
This commit is contained in:
parent
d062f362ac
commit
96b896d043
@ -20,6 +20,12 @@ import org.apache.karaf.shell.commands.Command;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
|
||||
@ -45,29 +51,7 @@ public class CfmMdListMdCommand extends AbstractShellCommand {
|
||||
CfmMdService service = get(CfmMdService.class);
|
||||
|
||||
if (name != null) {
|
||||
String[] nameParts = name.split("[()]");
|
||||
if (nameParts.length != 2) {
|
||||
throw new IllegalArgumentException("Invalid name format. " +
|
||||
"Must be in the format of <identifier(name-type)>");
|
||||
}
|
||||
|
||||
MdId mdId = null;
|
||||
MdId.MdNameType nameTypeEnum = MdId.MdNameType.valueOf(nameParts[1]);
|
||||
switch (nameTypeEnum) {
|
||||
case DOMAINNAME:
|
||||
mdId = MdIdDomainName.asMdId(nameParts[0]);
|
||||
break;
|
||||
case MACANDUINT:
|
||||
mdId = MdIdMacUint.asMdId(nameParts[0]);
|
||||
break;
|
||||
case NONE:
|
||||
mdId = MdIdNone.asMdId();
|
||||
break;
|
||||
case CHARACTERSTRING:
|
||||
default:
|
||||
mdId = MdIdCharStr.asMdId(nameParts[0]);
|
||||
}
|
||||
|
||||
MdId mdId = parseMdName(name);
|
||||
print("Maintenance Domain:");
|
||||
Optional<MaintenanceDomain> md = service.getMaintenanceDomain(mdId);
|
||||
print(printMd(md));
|
||||
@ -131,4 +115,59 @@ public class CfmMdListMdCommand extends AbstractShellCommand {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static MdId parseMdName(String mdStr) {
|
||||
String[] nameParts = mdStr.split("[()]");
|
||||
if (nameParts.length != 2) {
|
||||
throw new IllegalArgumentException("Invalid name format. " +
|
||||
"Must be in the format of <identifier(name-type)>");
|
||||
}
|
||||
|
||||
MdId mdId = null;
|
||||
MdId.MdNameType nameTypeEnum = MdId.MdNameType.valueOf(nameParts[1]);
|
||||
switch (nameTypeEnum) {
|
||||
case DOMAINNAME:
|
||||
mdId = MdIdDomainName.asMdId(nameParts[0]);
|
||||
break;
|
||||
case MACANDUINT:
|
||||
mdId = MdIdMacUint.asMdId(nameParts[0]);
|
||||
break;
|
||||
case NONE:
|
||||
mdId = MdIdNone.asMdId();
|
||||
break;
|
||||
case CHARACTERSTRING:
|
||||
default:
|
||||
mdId = MdIdCharStr.asMdId(nameParts[0]);
|
||||
}
|
||||
return mdId;
|
||||
}
|
||||
|
||||
public static MaIdShort parseMaName(String maStr) {
|
||||
String[] nameParts = maStr.split("[()]");
|
||||
if (nameParts.length != 2) {
|
||||
throw new IllegalArgumentException("Invalid name format. " +
|
||||
"Must be in the format of <identifier(name-type)>");
|
||||
}
|
||||
|
||||
MaIdShort maId = null;
|
||||
MaIdShort.MaIdType nameTypeEnum = MaIdShort.MaIdType.valueOf(nameParts[1]);
|
||||
switch (nameTypeEnum) {
|
||||
case ICCY1731:
|
||||
maId = MaIdIccY1731.asMaId(nameParts[0]);
|
||||
break;
|
||||
case PRIMARYVID:
|
||||
maId = MaIdPrimaryVid.asMaId(nameParts[0]);
|
||||
break;
|
||||
case RFC2685VPNID:
|
||||
maId = MaIdRfc2685VpnId.asMaIdHex(nameParts[0]);
|
||||
break;
|
||||
case TWOOCTET:
|
||||
maId = MaId2Octet.asMaId(nameParts[0]);
|
||||
case CHARACTERSTRING:
|
||||
default:
|
||||
maId = MaIdCharStr.asMaId(nameParts[0]);
|
||||
}
|
||||
return maId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2018-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.cfm.cli;
|
||||
|
||||
import org.apache.karaf.shell.commands.Argument;
|
||||
import org.apache.karaf.shell.commands.Command;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static org.onosproject.cfm.cli.CfmMdListMdCommand.parseMaName;
|
||||
import static org.onosproject.cfm.cli.CfmMdListMdCommand.parseMdName;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* Lists a particular Maintenance Domain.
|
||||
*/
|
||||
@Command(scope = "onos", name = "cfm-mep-list",
|
||||
description = "Lists a filtered set of MEPs or all if no parameters specified.")
|
||||
public class CfmMepListCommand extends AbstractShellCommand {
|
||||
private final Logger log = getLogger(getClass());
|
||||
@Argument(index = 0, name = "md",
|
||||
description = "Maintenance Domain name and type (in brackets) - will use all MDs if not specified",
|
||||
required = false, multiValued = false)
|
||||
String mdStr = null;
|
||||
@Argument(index = 1, name = "ma",
|
||||
description = "Maintenance Association name and type (in brackets) - requires MD",
|
||||
required = false, multiValued = false)
|
||||
String maStr = null;
|
||||
@Argument(index = 2, name = "mep",
|
||||
description = "MEP identifier - requires MD and MA",
|
||||
required = false, multiValued = false)
|
||||
String mepStr = null;
|
||||
|
||||
@Override
|
||||
protected void execute() {
|
||||
CfmMepService mepService = get(CfmMepService.class);
|
||||
CfmMdService mdService = get(CfmMdService.class);
|
||||
|
||||
if (mdStr != null && !mdStr.isEmpty()) {
|
||||
|
||||
|
||||
MdId mdId = parseMdName(mdStr);
|
||||
print(printMdId(mdId));
|
||||
|
||||
if (maStr != null && !maStr.isEmpty()) {
|
||||
MaIdShort maId = parseMaName(maStr);
|
||||
print(printMaId(maId));
|
||||
|
||||
if (mepStr != null && !mepStr.isEmpty()) {
|
||||
MepId mepId = MepId.valueOf(Short.parseShort(mepStr));
|
||||
try {
|
||||
MepEntry mep = mepService.getMep(mdId, maId, mepId);
|
||||
if (mep != null) {
|
||||
print(printMepEntry(mep));
|
||||
}
|
||||
} catch (CfmConfigException e) {
|
||||
log.error("Error retrieving Mep details {}",
|
||||
new MepKeyId(mdId, maId, mepId), e);
|
||||
}
|
||||
|
||||
//MD, MA and MEP given
|
||||
} else {
|
||||
//MD and MA given but no MEP given
|
||||
try {
|
||||
mepService.getAllMeps(mdId, maId).forEach(mep -> {
|
||||
print(printMepEntry(mep));
|
||||
});
|
||||
} catch (CfmConfigException e) {
|
||||
log.error("Error retrieving Meps for {}/{}",
|
||||
mdId.mdName(), maId.maName(), e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//MD given but no MA given
|
||||
mdService.getAllMaintenanceAssociation(mdId).forEach(ma -> {
|
||||
print(printMaId(ma.maId()));
|
||||
try {
|
||||
mepService.getAllMeps(mdId, ma.maId()).forEach(mep -> {
|
||||
print(printMepEntry(mep));
|
||||
});
|
||||
} catch (CfmConfigException e) {
|
||||
log.error("Error retrieving Meps for {}/{}",
|
||||
mdId.mdName(), ma.maId().maName(), e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
} else {
|
||||
mdService.getAllMaintenanceDomain().forEach(md -> {
|
||||
print(printMdId(md.mdId()));
|
||||
|
||||
mdService.getAllMaintenanceAssociation(md.mdId()).forEach(ma -> {
|
||||
print(printMaId(ma.maId()));
|
||||
try {
|
||||
mepService.getAllMeps(md.mdId(), ma.maId()).forEach(mep -> {
|
||||
print(printMepEntry(mep));
|
||||
});
|
||||
} catch (CfmConfigException e) {
|
||||
log.error("Error retrieving Meps for {}/{}",
|
||||
md.mdId().mdName(), ma.maId().maName(), e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the whole MEP Entry (config and status).
|
||||
* @param mep The MEPEntry to print
|
||||
* @return A string with MepEntry details
|
||||
*/
|
||||
public static String printMepEntry(MepEntry mep) {
|
||||
StringBuffer sb = new StringBuffer("MEP: ");
|
||||
sb.append(mep.mepId());
|
||||
sb.append(" Device:" + mep.deviceId());
|
||||
sb.append(", Port: " + mep.port());
|
||||
sb.append(", Vlan: " + mep.primaryVid());
|
||||
sb.append(", AdminSt: " + mep.administrativeState());
|
||||
sb.append(", CciEnabled: " + mep.cciEnabled());
|
||||
sb.append(", Priority: " + mep.ccmLtmPriority());
|
||||
sb.append("\n"); //The following are state
|
||||
sb.append(", Total CCMs: " + mep.totalCcmsTransmitted());
|
||||
sb.append(", MAC: " + mep.macAddress());
|
||||
sb.append(", Fault: " + mep.fngState());
|
||||
|
||||
mep.activeRemoteMepList().forEach(rmep -> {
|
||||
sb.append("\n\tRmep: " + rmep.remoteMepId());
|
||||
sb.append(", Mac: " + rmep.macAddress());
|
||||
sb.append(", State: " + rmep.state());
|
||||
sb.append(", Failed Time: " + rmep.failedOrOkTime());
|
||||
|
||||
});
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String printMdId(MdId mdId) {
|
||||
StringBuffer sb = new StringBuffer("MD: ");
|
||||
sb.append(mdId.mdName());
|
||||
sb.append("(" + mdId.nameType() + ")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String printMaId(MaIdShort maId) {
|
||||
StringBuffer sb = new StringBuffer("MA: ");
|
||||
sb.append(maId.maName());
|
||||
sb.append("(" + maId.nameType() + ")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2018-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.cfm.cli;
|
||||
|
||||
import org.apache.karaf.shell.commands.Argument;
|
||||
import org.apache.karaf.shell.commands.Command;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* Lists all the MEPs on a particular device.
|
||||
*/
|
||||
@Command(scope = "onos", name = "cfm-mep-device-list",
|
||||
description = "Lists a set of MEPs filtered by device.")
|
||||
public class CfmMepListDeviceCommand extends AbstractShellCommand {
|
||||
private final Logger log = getLogger(getClass());
|
||||
@Argument(index = 0, name = "device",
|
||||
description = "Device Id",
|
||||
required = true, multiValued = false)
|
||||
String deviceStr = null;
|
||||
|
||||
@Override
|
||||
protected void execute() {
|
||||
CfmMepService mepService = get(CfmMepService.class);
|
||||
if (deviceStr != null) {
|
||||
DeviceId deviceId = DeviceId.deviceId(deviceStr);
|
||||
try {
|
||||
mepService.getAllMepsByDevice(deviceId).forEach(mep -> {
|
||||
print(printMep(mep));
|
||||
});
|
||||
} catch (CfmConfigException e) {
|
||||
log.error("Error retrieving Meps for Device {}",
|
||||
deviceId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print only the config part of the MEP.
|
||||
* @param mep The MEP to print
|
||||
* @return A string with MD name, MA name and Mep details
|
||||
*/
|
||||
public static String printMep(Mep mep) {
|
||||
StringBuffer sb = new StringBuffer("MEP: ");
|
||||
sb.append(mep.mdId().mdName() + "/");
|
||||
sb.append(mep.maId().maName() + "/");
|
||||
sb.append(mep.mepId());
|
||||
sb.append(" Device:" + mep.deviceId());
|
||||
sb.append(", Port: " + mep.port());
|
||||
sb.append(", Vlan: " + mep.primaryVid());
|
||||
sb.append(", AdminSt: " + mep.administrativeState());
|
||||
sb.append(", CciEnabled: " + mep.cciEnabled());
|
||||
sb.append(", Priority: " + mep.ccmLtmPriority());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2018-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.cfm.cli.completer;
|
||||
|
||||
import org.apache.karaf.shell.console.Completer;
|
||||
import org.apache.karaf.shell.console.completer.StringsCompleter;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
|
||||
import org.onosproject.net.Device;
|
||||
import org.onosproject.net.device.DeviceService;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* CLI completer for Devices that support Meps.
|
||||
*/
|
||||
public class CfmDeviceIdCompleter implements Completer {
|
||||
@Override
|
||||
public int complete(String buffer, int cursor, List<String> candidates) {
|
||||
// Delegate string completer
|
||||
StringsCompleter delegate = new StringsCompleter();
|
||||
|
||||
// Fetch our service and feed it's offerings to the string completer
|
||||
DeviceService service = AbstractShellCommand.get(DeviceService.class);
|
||||
Iterator<Device> it = service.getDevices().iterator();
|
||||
SortedSet<String> strings = delegate.getStrings();
|
||||
while (it.hasNext()) {
|
||||
Device device = it.next();
|
||||
if (device.is(CfmMepProgrammable.class)) {
|
||||
strings.add(device.id().toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Now let the completer do the work for figuring out what to offer.
|
||||
return delegate.complete(buffer, cursor, candidates);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2018-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.cfm.cli.completer;
|
||||
|
||||
import org.onosproject.cli.AbstractChoicesCompleter;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.onosproject.cli.AbstractShellCommand.get;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* CLI completer for Mep Id creation.
|
||||
*/
|
||||
public class CfmMepIdCompleter extends AbstractChoicesCompleter {
|
||||
private final Logger log = getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public List<String> choices() {
|
||||
List<String> choices = new ArrayList<>();
|
||||
|
||||
CfmMdService mdService = get(CfmMdService.class);
|
||||
CfmMepService mepService = get(CfmMepService.class);
|
||||
|
||||
mdService.getAllMaintenanceDomain().forEach(md -> {
|
||||
choices.add(new StringBuilder(md.mdId().mdName())
|
||||
.append("(")
|
||||
.append(md.mdId().nameType())
|
||||
.append(")").toString());
|
||||
|
||||
md.maintenanceAssociationList().forEach(ma -> {
|
||||
choices.add(new StringBuilder(md.mdId().mdName())
|
||||
.append("(")
|
||||
.append(md.mdId().nameType())
|
||||
.append(") ")
|
||||
.append(ma.maId().maName())
|
||||
.append("(")
|
||||
.append(ma.maId().nameType())
|
||||
.append(")").toString());
|
||||
|
||||
try {
|
||||
mepService.getAllMeps(md.mdId(), ma.maId()).forEach(mep ->
|
||||
choices.add(new StringBuilder(md.mdId().mdName())
|
||||
.append("(")
|
||||
.append(md.mdId().nameType())
|
||||
.append(") ")
|
||||
.append(ma.maId().maName())
|
||||
.append("(")
|
||||
.append(ma.maId().nameType())
|
||||
.append(") ")
|
||||
.append(mep.mepId()).toString())
|
||||
);
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("Unable to retrieve mep details", e);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return choices;
|
||||
}
|
||||
|
||||
}
|
||||
@ -32,6 +32,7 @@ public class CfmWebApplication extends AbstractWebApplication {
|
||||
MdWebResource.class,
|
||||
MaWebResource.class,
|
||||
MepWebResource.class,
|
||||
DeviceMepWebResource.class,
|
||||
DmWebResource.class,
|
||||
LmWebResource.class);
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.cfm.rest;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.rest.AbstractWebResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Layer 2 CFM Maintenance Association Endpoint (MEP) by Device web resource.
|
||||
*/
|
||||
@Path("device")
|
||||
public class DeviceMepWebResource extends AbstractWebResource {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* Get all MEPs by Device Id. The device should support Meps
|
||||
*
|
||||
* @param deviceId The id of a device.
|
||||
* @return 200 OK with a list of MEPS or 500 on error
|
||||
*/
|
||||
@GET
|
||||
@Path("{device_id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response getAllMepsForDevice(@PathParam("device_id") String deviceId) {
|
||||
DeviceId deviceIdObj = DeviceId.deviceId(deviceId);
|
||||
log.debug("GET all Meps called for Device {}", deviceIdObj);
|
||||
try {
|
||||
Collection<Mep> mepCollection = get(CfmMepService.class)
|
||||
.getAllMepsByDevice(deviceIdObj);
|
||||
ArrayNode an = mapper().createArrayNode();
|
||||
an.add(codec(Mep.class).encode(mepCollection, this));
|
||||
return ok(mapper().createObjectNode().set("meps", an)).build();
|
||||
} catch (CfmConfigException e) {
|
||||
log.error("Get all Meps on device {} failed because of exception",
|
||||
deviceIdObj, e);
|
||||
return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,6 +82,7 @@ public class MdWebResource extends AbstractWebResource {
|
||||
log.debug("GET called for MD {}", mdName);
|
||||
try {
|
||||
MaintenanceDomain md = get(CfmMdService.class)
|
||||
//FIXME Handle other types of name constructs e.g. DomainName
|
||||
.getMaintenanceDomain(MdIdCharStr.asMdId(mdName))
|
||||
.orElseThrow(() -> new IllegalArgumentException(
|
||||
"MD " + mdName + " not Found"));
|
||||
|
||||
@ -18,6 +18,7 @@ package org.onosproject.cfm.rest;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
@ -145,7 +146,7 @@ public class MepWebResource extends AbstractWebResource {
|
||||
MdId mdId = MdIdCharStr.asMdId(mdName);
|
||||
MaIdShort maId = MaIdCharStr.asMaId(maName);
|
||||
boolean deleted = get(CfmMepService.class)
|
||||
.deleteMep(mdId, maId, MepId.valueOf(mepIdShort));
|
||||
.deleteMep(mdId, maId, MepId.valueOf(mepIdShort), Optional.empty());
|
||||
if (!deleted) {
|
||||
return Response.notModified(mdName + "/" + maName + "/" +
|
||||
mepIdShort + " did not exist").build();
|
||||
@ -187,8 +188,8 @@ public class MepWebResource extends AbstractWebResource {
|
||||
|
||||
Mep mep = ((MepCodec) mepCodec).decode((ObjectNode) cfg, this, mdName, maName);
|
||||
|
||||
Boolean issuccess = get(CfmMepService.class).createMep(mdId, maId, mep);
|
||||
if (!issuccess) {
|
||||
Boolean didNotExist = get(CfmMepService.class).createMep(mdId, maId, mep);
|
||||
if (!didNotExist) {
|
||||
return Response.notModified(mdName + "/" + ma.maId() + "/" + mep.mepId() +
|
||||
" already exists").build();
|
||||
}
|
||||
|
||||
@ -124,10 +124,13 @@ public class MaintenanceAssociationCodec extends JsonCodec<MaintenanceAssociatio
|
||||
builder = builder.addToComponentList(component);
|
||||
}
|
||||
|
||||
List<MepId> remoteMeps = (new RMepCodec()).decode(
|
||||
(ArrayNode) nullIsIllegal(maNode.get(RMEP_LIST), "rmep-list is required"), context);
|
||||
for (MepId remoteMep:remoteMeps) {
|
||||
builder = builder.addToRemoteMepIdList(remoteMep);
|
||||
JsonNode rmepListJson = maNode.get(RMEP_LIST);
|
||||
if (rmepListJson != null) {
|
||||
List<MepId> remoteMeps = (new RMepCodec()).decode(
|
||||
(ArrayNode) rmepListJson, context);
|
||||
for (MepId remoteMep:remoteMeps) {
|
||||
builder = builder.addToRemoteMepIdList(remoteMep);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
|
||||
@ -57,6 +57,18 @@
|
||||
<ref component-id="maNameCompleter"/>
|
||||
</completers>
|
||||
</command>
|
||||
<command>
|
||||
<action class="org.onosproject.cfm.cli.CfmMepListCommand"/>
|
||||
<completers>
|
||||
<ref component-id="mepIdCompleter"/>
|
||||
</completers>
|
||||
</command>
|
||||
<command>
|
||||
<action class="org.onosproject.cfm.cli.CfmMepListDeviceCommand"/>
|
||||
<completers>
|
||||
<ref component-id="mepDeviceIdCompleter"/>
|
||||
</completers>
|
||||
</command>
|
||||
</command-bundle>
|
||||
|
||||
<bean id="placeholderCompleter" class="org.onosproject.cli.PlaceholderCompleter"/>
|
||||
@ -68,6 +80,8 @@
|
||||
<bean id="maCcmIntervalCompleter" class="org.onosproject.cfm.cli.completer.CfmMaCcmIntervalCompleter"/>
|
||||
<bean id="compTagTypeCompleter" class="org.onosproject.cfm.cli.completer.CfmCompTagTypeCompleter"/>
|
||||
<bean id="compMhfCompleter" class="org.onosproject.cfm.cli.completer.CfmCompMhfCompleter"/>
|
||||
<bean id="mepIdCompleter" class="org.onosproject.cfm.cli.completer.CfmMepIdCompleter"/>
|
||||
<bean id="mepDeviceIdCompleter" class="org.onosproject.cfm.cli.completer.CfmDeviceIdCompleter"/>
|
||||
|
||||
</blueprint>
|
||||
|
||||
|
||||
@ -133,7 +133,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": [{"rmep": 10}, {"rmep": 20}]
|
||||
"example": [{"rmep": 10}, {"rmep": 20}],
|
||||
"description": "An optional set of Mep IDs that might be on equipment not managed by ONOS"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,7 +185,7 @@ public class MepWebResourceTest extends CfmResourceTest {
|
||||
@Test
|
||||
public void testDeleteMepValid() throws CfmConfigException {
|
||||
|
||||
expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 1)))
|
||||
expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 1), Optional.empty()))
|
||||
.andReturn(true).anyTimes();
|
||||
replay(mepService);
|
||||
|
||||
@ -199,7 +199,7 @@ public class MepWebResourceTest extends CfmResourceTest {
|
||||
@Test
|
||||
public void testDeleteMepNotFound() throws CfmConfigException {
|
||||
|
||||
expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 2)))
|
||||
expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 2), Optional.empty()))
|
||||
.andReturn(false).anyTimes();
|
||||
replay(mepService);
|
||||
|
||||
|
||||
@ -15,7 +15,8 @@ TEST_DEPS = [
|
||||
'//core/api:onos-api-tests',
|
||||
'//drivers/netconf:onos-drivers-netconf-tests',
|
||||
'//utils/osgi:onlab-osgi-tests',
|
||||
'//incubator/net:onos-incubator-net'
|
||||
'//incubator/net:onos-incubator-net',
|
||||
'//incubator/net:onos-incubator-net-tests'
|
||||
]
|
||||
|
||||
APPS = [
|
||||
|
||||
@ -16,12 +16,17 @@
|
||||
package org.onosproject.drivers.microsemi;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.drivers.microsemi.yang.utils.MaNameUtil.getApiMaIdFromYangMaName;
|
||||
import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getApiMdIdFromYangMdName;
|
||||
import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getYangMdNameFromApiMdId;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onlab.packet.VlanId;
|
||||
import org.onlab.util.HexString;
|
||||
@ -47,14 +52,12 @@ import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepEn
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||
@ -62,7 +65,6 @@ import org.onosproject.netconf.DatastoreId;
|
||||
import org.onosproject.netconf.NetconfController;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
import org.onosproject.netconf.NetconfSession;
|
||||
import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.DomainName;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
|
||||
@ -83,11 +85,6 @@ import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenanc
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.ContinuityCheck;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultContinuityCheck;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.InterfaceEnum;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultMacAddressAndUint;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameDomainName;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameNone;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.remotemepstatetype.RemoteMepStateTypeEnum;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId;
|
||||
@ -97,8 +94,6 @@ import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.TargetAddress;
|
||||
import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
|
||||
import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MacAddressAndUintStr;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MdLevelType;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
|
||||
@ -128,46 +123,34 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
public boolean createMep(MdId mdName, MaIdShort maName, Mep mep)
|
||||
throws CfmConfigException {
|
||||
NetconfController controller = checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfSession session = controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession();
|
||||
NetconfSession session = checkNotNull(controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession());
|
||||
MseaCfmNetconfService mseaCfmService =
|
||||
checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
CfmMepService cfmMepService =
|
||||
checkNotNull(handler().get(CfmMepService.class));
|
||||
|
||||
MaintenanceAssociationEndPoint yangMep = buildYangMepFromApiMep(mep);
|
||||
|
||||
CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
|
||||
MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdName).get();
|
||||
MaintenanceAssociation ma = cfmMdService.getMaintenanceAssociation(mdName, maName).get();
|
||||
MseaCfmOpParam mseaCfmOpParam = getMaYangObject(cfmMdService, mdName, maName);
|
||||
|
||||
if (!ma.remoteMepIdList().contains(mep.mepId())) {
|
||||
throw new CfmConfigException("Mep Id " + mep.mepId() +
|
||||
" is not present in the remote Mep list for MA " + ma.maId() +
|
||||
". This is required for EA1000.");
|
||||
} else if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) {
|
||||
throw new CfmConfigException("Numeric id of MD " + mdName + " must"
|
||||
+ " be between 1 and 64 inclusive for EA1000");
|
||||
} else if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) {
|
||||
throw new CfmConfigException("Numeric id of MA " + maName + " must"
|
||||
+ " be between 1 and 64 inclusive for EA1000");
|
||||
}
|
||||
mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
|
||||
.maintenanceAssociation().get(0).addToMaintenanceAssociationEndPoint(yangMep);
|
||||
//Add this mepId to the list of remoteMeps on the device
|
||||
mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
|
||||
.maintenanceAssociation().get(0).addToRemoteMeps(MepIdType.of(mep.mepId().value()));
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
|
||||
.MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
|
||||
yangMa.addToMaintenanceAssociationEndPoint(yangMep);
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
|
||||
.mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
|
||||
yangMd.addToMaintenanceAssociation(yangMa);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(yangMd);
|
||||
|
||||
MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
|
||||
mseaCfmOpParam.mefCfm(mefCfm);
|
||||
//Add all of the existing meps on this MD/MA to the remote meps list
|
||||
cfmMepService.getAllMeps(mdName, maName).forEach(m -> {
|
||||
mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
|
||||
.maintenanceAssociation().get(0).addToRemoteMeps(MepIdType.of(m.mepId().value()));
|
||||
});
|
||||
try {
|
||||
mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
|
||||
log.info("Created MEP {} on device {}", mdName + "/" + maName +
|
||||
"/" + mep.mepId(), handler().data().deviceId());
|
||||
|
||||
return true;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to create MEP {}/{}/{} on device {}",
|
||||
@ -176,11 +159,6 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MepEntry> getAllMeps(MdId mdName, MaIdShort maName) throws CfmConfigException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId)
|
||||
throws CfmConfigException {
|
||||
@ -189,31 +167,20 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
throw new CfmConfigException("Device is not ready - connecting or "
|
||||
+ "disconnected for MEP " + mdName + "/" + maName + "/" + mepId);
|
||||
}
|
||||
NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
|
||||
NetconfSession session = checkNotNull(controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession());
|
||||
MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
|
||||
try {
|
||||
MseaCfm mseacfm =
|
||||
mseaCfmService.getMepFull(mdName, maName, mepId, session);
|
||||
if (mseacfm != null && mseacfm.mefCfm() != null &&
|
||||
mseacfm.mefCfm().maintenanceDomain() != null) {
|
||||
for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
|
||||
mseacfm.mefcfm.MaintenanceDomain replyMd :
|
||||
mseacfm.mefCfm().maintenanceDomain()) {
|
||||
for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
|
||||
mseacfm.mefcfm.maintenancedomain.
|
||||
MaintenanceAssociation replyMa :
|
||||
replyMd.maintenanceAssociation()) {
|
||||
for (MaintenanceAssociationEndPoint replyMep :
|
||||
replyMa.maintenanceAssociationEndPoint()) {
|
||||
return buildApiMepEntryFromYangMep(
|
||||
replyMep, handler().data().deviceId(), mdName, maName);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collection<MepEntry> mepEntries = getMepEntriesFromYangResponse(mseacfm);
|
||||
if (mepEntries == null || mepEntries.size() != 1) {
|
||||
log.warn("Mep " + mepId + " not found on device " + handler().data().deviceId());
|
||||
return null;
|
||||
} else {
|
||||
return mepEntries.stream().findFirst().get();
|
||||
}
|
||||
log.warn("Mep " + mepId + " not found on device " + handler().data().deviceId());
|
||||
return null;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to get MEP {}/{}/{} on device {}",
|
||||
mdName, maName, mepId, handler().data().deviceId());
|
||||
@ -221,12 +188,37 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<MepEntry> getMepEntriesFromYangResponse(MseaCfm mseacfm)
|
||||
throws CfmConfigException {
|
||||
|
||||
Collection<MepEntry> mepEntries = new ArrayList<>();
|
||||
if (mseacfm == null || mseacfm.mefCfm() == null || mseacfm.mefCfm().maintenanceDomain() == null) {
|
||||
return mepEntries;
|
||||
}
|
||||
|
||||
for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
|
||||
mseacfm.mefcfm.MaintenanceDomain replyMd:mseacfm.mefCfm().maintenanceDomain()) {
|
||||
for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.
|
||||
mseacfm.mefcfm.maintenancedomain.
|
||||
MaintenanceAssociation replyMa:replyMd.maintenanceAssociation()) {
|
||||
for (MaintenanceAssociationEndPoint replyMep:replyMa.maintenanceAssociationEndPoint()) {
|
||||
mepEntries.add(buildApiMepEntryFromYangMep(
|
||||
replyMep, handler().data().deviceId(), replyMd, replyMa));
|
||||
}
|
||||
}
|
||||
}
|
||||
return mepEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
|
||||
public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
|
||||
|
||||
NetconfController controller = checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
|
||||
NetconfSession session = checkNotNull(controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession());
|
||||
MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
|
||||
|
||||
MaintenanceAssociationEndPoint mep =
|
||||
new DefaultMaintenanceAssociationEndPoint();
|
||||
@ -234,12 +226,34 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
|
||||
.MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
|
||||
yangMa.maNameAndTypeCombo(MaNameUtil.getYangMaNameFromApiMaId(maName));
|
||||
Short maNumericId = null;
|
||||
try {
|
||||
maNumericId =
|
||||
mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId();
|
||||
yangMa.id(maNumericId);
|
||||
} catch (NoSuchElementException | IllegalArgumentException e) {
|
||||
//The MA and/or MD have probably been deleted
|
||||
// try to get numeric id values from oldMd
|
||||
log.debug("Could not get MD/MA details from MD service during deletion of MEP {}." +
|
||||
"Continuing with values from event", new MepKeyId(mdName, maName, mepId));
|
||||
yangMa.id(getMaNumericId(oldMd.get(), maName));
|
||||
}
|
||||
|
||||
yangMa.addToMaintenanceAssociationEndPoint(mep);
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
|
||||
new DefaultMaintenanceDomain();
|
||||
yangMd.mdNameAndTypeCombo(getYangMdNameFromApiMdId(mdName));
|
||||
Short mdNumericId = null;
|
||||
try {
|
||||
mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId();
|
||||
yangMd.id(mdNumericId);
|
||||
} catch (NoSuchElementException | IllegalArgumentException e) {
|
||||
//The MD has probably been deleted
|
||||
// try to get numeric id values from oldMd
|
||||
log.debug("Could not get MD details from MD service during deletion of MEP {}." +
|
||||
"Continuing with values from event", new MepKeyId(mdName, maName, mepId));
|
||||
yangMd.id(oldMd.get().mdNumericId());
|
||||
}
|
||||
yangMd.addToMaintenanceAssociation(yangMa);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
@ -254,13 +268,280 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
"/" + mepId, handler().data().deviceId());
|
||||
return true;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to delete MEP {}/{}/{} on device {}",
|
||||
mdName, maName, mepId, handler().data().deviceId());
|
||||
log.error("Unable to delete MEP {} ({}) on device {}",
|
||||
mdName + "/" + maName + "/" + mepId,
|
||||
mdNumericId + "/" + maNumericId, handler().data().deviceId(), e);
|
||||
throw new CfmConfigException("Unable to delete MEP :" + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createMdOnDevice(MdId mdId) throws CfmConfigException {
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfSession session = checkNotNull(controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession());
|
||||
|
||||
CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
|
||||
MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdId).get();
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
|
||||
.mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
|
||||
|
||||
if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) {
|
||||
throw new CfmConfigException("Numeric id of MD " + mdId + " must"
|
||||
+ " be between 1 and 64 inclusive for EA1000");
|
||||
}
|
||||
|
||||
for (MaintenanceAssociation ma:md.maintenanceAssociationList()) {
|
||||
if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) {
|
||||
throw new CfmConfigException("Numeric id of MA " + mdId + " must"
|
||||
+ " be between 1 and 64 inclusive for EA1000");
|
||||
}
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
|
||||
.MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
|
||||
yangMd.addToMaintenanceAssociation(yangMa);
|
||||
}
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(yangMd);
|
||||
|
||||
MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
|
||||
mseaCfmOpParam.mefCfm(mefCfm);
|
||||
|
||||
MseaCfmNetconfService mseaCfmService =
|
||||
checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
|
||||
try {
|
||||
boolean created = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
|
||||
log.info("Created MD {} on device {}", mdId.mdName(),
|
||||
handler().data().deviceId());
|
||||
return created;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to create MD {} on device {}",
|
||||
mdId.mdName(), handler().data().deviceId());
|
||||
throw new CfmConfigException("Unable to create MD :" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException {
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfSession session = checkNotNull(controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession());
|
||||
|
||||
CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
|
||||
MseaCfmOpParam mseaCfmOpParam = getMaYangObject(mdService, mdId, maId);
|
||||
MseaCfmNetconfService mseaCfmService =
|
||||
checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
|
||||
try {
|
||||
boolean created = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
|
||||
log.info("Created MA {} on device {}", mdId.mdName() + "/" + maId.maName(),
|
||||
handler().data().deviceId());
|
||||
return created;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to create MA {} on device {}",
|
||||
mdId.mdName() + "/" + maId.maName(), handler().data().deviceId());
|
||||
throw new CfmConfigException("Unable to create MA :" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static MseaCfmOpParam getMaYangObject(CfmMdService cfmMdService,
|
||||
MdId mdName, MaIdShort maName) throws CfmConfigException {
|
||||
MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdName).get();
|
||||
MaintenanceAssociation ma = cfmMdService.getMaintenanceAssociation(mdName, maName).get();
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
|
||||
.MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
|
||||
.mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
|
||||
yangMd.addToMaintenanceAssociation(yangMa);
|
||||
|
||||
if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) {
|
||||
throw new CfmConfigException("Numeric id of MD " + mdName + " must"
|
||||
+ " be between 1 and 64 inclusive for EA1000");
|
||||
} else if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) {
|
||||
throw new CfmConfigException("Numeric id of MA " + maName + " must"
|
||||
+ " be between 1 and 64 inclusive for EA1000");
|
||||
}
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(yangMd);
|
||||
|
||||
MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
|
||||
mseaCfmOpParam.mefCfm(mefCfm);
|
||||
|
||||
return mseaCfmOpParam;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd)
|
||||
throws CfmConfigException {
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfSession session = controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession();
|
||||
|
||||
//First check if this MD is known to ONOS if it is does it have MAs and
|
||||
// do they have any Meps known to ONOS. If there are Meps throw an exception -
|
||||
// the Meps should have been deleted first
|
||||
//If there are none known to ONOS we do not check for Meps on the actual device
|
||||
// - there might might be some orphaned ones down there - we want to delete these
|
||||
//FIXME: When CfmMepService is extended to be persistent come back and enable check
|
||||
CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
|
||||
MseaCfmNetconfService mseaCfmService =
|
||||
checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
|
||||
MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(mdId);
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
|
||||
new DefaultMaintenanceDomain();
|
||||
Short mdNumericId = null;
|
||||
try {
|
||||
mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
|
||||
yangMd.id(mdNumericId);
|
||||
} catch (NoSuchElementException e) {
|
||||
yangMd.id(oldMd.get().mdNumericId());
|
||||
}
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(yangMd);
|
||||
|
||||
MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
|
||||
mseaCfmOpParam.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
boolean deleted = mseaCfmService.deleteMseaMd(mseaCfmOpParam, session, DatastoreId.RUNNING);
|
||||
log.info("Deleted MD {} on device {}", mdName,
|
||||
handler().data().deviceId());
|
||||
return deleted;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to delete MD {} ({}) on device {}",
|
||||
mdName, mdNumericId, handler().data().deviceId());
|
||||
throw new CfmConfigException("Unable to delete MD :" + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMaOnDevice(MdId mdId, MaIdShort maId, Optional<MaintenanceDomain> oldMd)
|
||||
throws CfmConfigException {
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfSession session = controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession();
|
||||
|
||||
CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
|
||||
|
||||
MseaCfmNetconfService mseaCfmService =
|
||||
checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
|
||||
.MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
|
||||
Short maNumericId = null;
|
||||
try {
|
||||
maNumericId =
|
||||
mdService.getMaintenanceAssociation(mdId, maId).get().maNumericId();
|
||||
yangMa.id(maNumericId);
|
||||
} catch (NoSuchElementException e) {
|
||||
yangMa.id(getMaNumericId(oldMd.get(), maId));
|
||||
}
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
|
||||
new DefaultMaintenanceDomain();
|
||||
Short mdNumericId = null;
|
||||
try {
|
||||
mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
|
||||
yangMd.id(mdNumericId);
|
||||
} catch (NoSuchElementException e) {
|
||||
yangMd.id(oldMd.get().mdNumericId());
|
||||
}
|
||||
yangMd.addToMaintenanceAssociation(yangMa);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(yangMd);
|
||||
|
||||
MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
|
||||
mseaCfmOpParam.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
boolean deleted = mseaCfmService.deleteMseaMa(mseaCfmOpParam, session, DatastoreId.RUNNING);
|
||||
log.info("Deleted MA {} ({})on device {}", mdId.mdName() + "/" + maId.maName(),
|
||||
mdNumericId + "/" + maNumericId, handler().data().deviceId());
|
||||
return deleted;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to delete MA {} ({}) on device {}",
|
||||
mdId.mdName() + "/" + maId.maName(),
|
||||
mdNumericId + "/" + maNumericId, handler().data().deviceId());
|
||||
throw new CfmConfigException("Unable to delete MA :" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
|
||||
return crDelMaRemoteMep(mdId, maId, remoteMep, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
|
||||
return crDelMaRemoteMep(mdId, maId, remoteMep, false);
|
||||
}
|
||||
|
||||
private boolean crDelMaRemoteMep(MdId mdId, MaIdShort maId, MepId remoteMep,
|
||||
boolean isCreate) throws CfmConfigException {
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfSession session = controller.getDevicesMap()
|
||||
.get(handler().data().deviceId()).getSession();
|
||||
|
||||
CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
|
||||
|
||||
Short mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
|
||||
Short maNumericId =
|
||||
mdService.getMaintenanceAssociation(mdId, maId).get().maNumericId();
|
||||
|
||||
MseaCfmNetconfService mseaCfmService =
|
||||
checkNotNull(handler().get(MseaCfmNetconfService.class));
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
|
||||
.MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
|
||||
yangMa.id(maNumericId);
|
||||
yangMa.addToRemoteMeps(MepIdType.of(remoteMep.value()));
|
||||
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
|
||||
new DefaultMaintenanceDomain();
|
||||
yangMd.id(mdNumericId);
|
||||
yangMd.addToMaintenanceAssociation(yangMa);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(yangMd);
|
||||
|
||||
MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
|
||||
mseaCfmOpParam.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
boolean result = false;
|
||||
if (isCreate) {
|
||||
result = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
|
||||
} else {
|
||||
result = mseaCfmService.deleteMseaMaRMep(mseaCfmOpParam, session, DatastoreId.RUNNING);
|
||||
}
|
||||
log.info("{} Remote MEP {} in MA {} on device {}", isCreate ? "Created" : "Deleted",
|
||||
remoteMep, mdId.mdName() + "/" + maId.maName(), handler().data().deviceId());
|
||||
return result;
|
||||
} catch (NetconfException e) {
|
||||
log.error("Unable to {} RemoteMep {} in MA {} on device {}",
|
||||
isCreate ? "create" : "delete", remoteMep, mdId.mdName() + "/" + maId.maName(),
|
||||
handler().data().deviceId());
|
||||
throw new CfmConfigException("Unable to " + (isCreate ? "create" : "delete")
|
||||
+ " Remote Mep:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
MepLbCreate lbCreate) throws CfmConfigException {
|
||||
@ -361,7 +642,7 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
private org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
|
||||
private static org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
|
||||
.MaintenanceDomain buildYangMdFromApiMd(MaintenanceDomain md)
|
||||
throws CfmConfigException {
|
||||
MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(md.mdId());
|
||||
@ -375,44 +656,7 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
return mdYang;
|
||||
}
|
||||
|
||||
protected static MdNameAndTypeCombo getYangMdNameFromApiMdId(MdId mdId)
|
||||
throws CfmConfigException {
|
||||
MdNameAndTypeCombo mdName;
|
||||
if (mdId instanceof MdIdDomainName) {
|
||||
boolean isIpAddr = false;
|
||||
try {
|
||||
if (IpAddress.valueOf(mdId.mdName()) != null) {
|
||||
isIpAddr = true;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
//continue
|
||||
}
|
||||
if (isIpAddr) {
|
||||
mdName = new DefaultNameDomainName();
|
||||
((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion.of(
|
||||
org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.
|
||||
IpAddress.fromString(mdId.mdName())));
|
||||
} else {
|
||||
mdName = new DefaultNameDomainName();
|
||||
((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion
|
||||
.of(DomainName.fromString(mdId.mdName())));
|
||||
}
|
||||
} else if (mdId instanceof MdIdMacUint) {
|
||||
mdName = new DefaultMacAddressAndUint();
|
||||
((DefaultMacAddressAndUint) mdName).nameMacAddressAndUint(MacAddressAndUintStr.fromString(mdId.mdName()));
|
||||
} else if (mdId instanceof MdIdNone) {
|
||||
mdName = new DefaultNameNone();
|
||||
} else if (mdId instanceof MdIdCharStr) {
|
||||
mdName = new DefaultNameCharacterString();
|
||||
((DefaultNameCharacterString) mdName).name(Identifier45.fromString(mdId.mdName()));
|
||||
} else {
|
||||
throw new CfmConfigException("Unexpected error creating MD " +
|
||||
mdId.getClass().getSimpleName());
|
||||
}
|
||||
return mdName;
|
||||
}
|
||||
|
||||
private org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
|
||||
private static org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
|
||||
.maintenancedomain.MaintenanceAssociation buildYangMaFromApiMa(
|
||||
MaintenanceAssociation apiMa) throws CfmConfigException {
|
||||
|
||||
@ -422,12 +666,6 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
.MaintenanceAssociation yamgMa = new DefaultMaintenanceAssociation();
|
||||
yamgMa.maNameAndTypeCombo(maName);
|
||||
|
||||
if (apiMa.remoteMepIdList() == null || apiMa.remoteMepIdList().size() < REMOTEMEPLIST_MIN_COUNT
|
||||
|| apiMa.remoteMepIdList().size() > REMOTEMEPLIST_MAX_COUNT) {
|
||||
throw new CfmConfigException("EA1000 requires between " +
|
||||
REMOTEMEPLIST_MIN_COUNT + " and " + REMOTEMEPLIST_MAX_COUNT +
|
||||
" remote meps in an MA");
|
||||
}
|
||||
for (MepId rmep:apiMa.remoteMepIdList()) {
|
||||
yamgMa.addToRemoteMeps(MepIdType.of(rmep.id()));
|
||||
}
|
||||
@ -486,7 +724,7 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
return yamgMa;
|
||||
}
|
||||
|
||||
private MaintenanceAssociationEndPoint buildYangMepFromApiMep(Mep mep)
|
||||
private static MaintenanceAssociationEndPoint buildYangMepFromApiMep(Mep mep)
|
||||
throws CfmConfigException {
|
||||
MaintenanceAssociationEndPoint mepBuilder =
|
||||
new DefaultMaintenanceAssociationEndPoint();
|
||||
@ -515,14 +753,19 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
|
||||
private MepEntry buildApiMepEntryFromYangMep(
|
||||
MaintenanceAssociationEndPoint yangMep, DeviceId deviceId,
|
||||
MdId mdName, MaIdShort maName) throws CfmConfigException {
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.
|
||||
mseacfm.mefcfm.MaintenanceDomain replyMd,
|
||||
org.onosproject.yang.gen.v1.mseacfm.rev20160229.
|
||||
mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation replyMa)
|
||||
throws CfmConfigException {
|
||||
MepId mepId = MepId.valueOf((short) yangMep.mepIdentifier().uint16());
|
||||
MepEntry.MepEntryBuilder builder = DefaultMepEntry.builder(mepId,
|
||||
deviceId,
|
||||
(yangMep.yangAutoPrefixInterface() == InterfaceEnum.ETH0) ?
|
||||
PortNumber.portNumber(0) : PortNumber.portNumber(1),
|
||||
MepDirection.DOWN_MEP, //Always down for EA1000
|
||||
mdName, maName);
|
||||
getApiMdIdFromYangMdName(replyMd.mdNameAndTypeCombo()),
|
||||
getApiMaIdFromYangMaName(replyMa.maNameAndTypeCombo()));
|
||||
|
||||
if (yangMep.loopback() != null) {
|
||||
MepLbEntryBuilder lbEntryBuilder = DefaultMepLbEntry.builder();
|
||||
@ -614,4 +857,10 @@ public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour
|
||||
}
|
||||
return rmepBuilder.build();
|
||||
}
|
||||
|
||||
private static short getMaNumericId(MaintenanceDomain md, MaIdShort maId) {
|
||||
return md.maintenanceAssociationList().stream()
|
||||
.filter(ma -> maId.equals(ma.maId()))
|
||||
.findFirst().get().maNumericId();
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ package org.onosproject.drivers.microsemi.yang;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
|
||||
import org.onosproject.netconf.DatastoreId;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
@ -29,6 +30,8 @@ import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Extension of mseaCfmService to include NETCONF sessions.
|
||||
*
|
||||
@ -65,6 +68,19 @@ public interface MseaCfmNetconfService {
|
||||
MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId,
|
||||
NetconfSession session) throws NetconfException;
|
||||
|
||||
|
||||
/**
|
||||
* Returns set of all MepIds from one Md or Ma or all.
|
||||
*
|
||||
* @param mdIdOptional An MdId to filter by, or empty to select all
|
||||
* @param maIdOptional An MaId to filter by, or empty to select all
|
||||
* @param session An active NETCONF session
|
||||
* @param targetDs one of running, candidate or startup
|
||||
* @return mseaCfm
|
||||
* @throws NetconfException if the session has any error
|
||||
*/
|
||||
MseaCfm getMepIds(Optional<MdId> mdIdOptional, Optional<MaIdShort> maIdOptional,
|
||||
NetconfSession session, DatastoreId targetDs) throws NetconfException;
|
||||
/**
|
||||
* Returns attributes of DM.
|
||||
*
|
||||
@ -102,10 +118,52 @@ public interface MseaCfmNetconfService {
|
||||
* @param targetDs one of running, candidate or startup
|
||||
* @return Boolean to indicate success or failure
|
||||
* @throws NetconfException if the session has any error
|
||||
* @throws CfmConfigException if the Cfm config has any error
|
||||
*/
|
||||
boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException;
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException;
|
||||
|
||||
/**
|
||||
* Deletes named Ma of mseaCfm.
|
||||
* Expects to see a list of Mas
|
||||
*
|
||||
* @param mseaCfm value of mseaCfm
|
||||
* @param session An active NETCONF session
|
||||
* @param targetDs one of running, candidate or startup
|
||||
* @return Boolean to indicate success or failure
|
||||
* @throws NetconfException if the session has any error
|
||||
* @throws CfmConfigException if the Cfm config has any error
|
||||
*/
|
||||
boolean deleteMseaMa(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException;
|
||||
|
||||
/**
|
||||
* Deletes a remote Mep from an MA.
|
||||
* Expects one or more RMeps
|
||||
*
|
||||
* @param mseaCfm value of mseaCfm
|
||||
* @param session An active NETCONF session
|
||||
* @param targetDs one of running, candidate or startup
|
||||
* @return Boolean to indicate success or failure
|
||||
* @throws NetconfException if the session has any error
|
||||
* @throws CfmConfigException if the Cfm config has any error
|
||||
*/
|
||||
boolean deleteMseaMaRMep(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException;
|
||||
|
||||
/**
|
||||
* Deletes named Md of mseaCfm.
|
||||
* Expects to see a list of Mds
|
||||
*
|
||||
* @param mseaCfm value of mseaCfm
|
||||
* @param session An active NETCONF session
|
||||
* @param targetDs one of running, candidate or startup
|
||||
* @return Boolean to indicate success or failure
|
||||
* @throws NetconfException if the session has any error
|
||||
* @throws CfmConfigException if the Cfm config has any error
|
||||
*/
|
||||
boolean deleteMseaMd(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException;
|
||||
|
||||
/**
|
||||
* Deletes named delay measurements of mseaCfm.
|
||||
@ -116,9 +174,10 @@ public interface MseaCfmNetconfService {
|
||||
* @param targetDs one of running, candidate or startup
|
||||
* @return Boolean to indicate success or failure
|
||||
* @throws NetconfException if the session has any error
|
||||
* @throws CfmConfigException if the Cfm config has any error
|
||||
*/
|
||||
boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException;
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException;
|
||||
|
||||
/**
|
||||
* Service interface of transmitLoopback.
|
||||
|
||||
@ -25,6 +25,7 @@ import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
|
||||
import org.onosproject.netconf.DatastoreId;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
@ -42,6 +43,7 @@ import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.
|
||||
import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint;
|
||||
import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint;
|
||||
import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
|
||||
import org.onosproject.yang.model.DefaultModelObjectData;
|
||||
import org.onosproject.yang.model.ModelConverter;
|
||||
import org.onosproject.yang.model.ModelObject;
|
||||
@ -54,6 +56,7 @@ import org.onosproject.yang.runtime.DefaultAnnotation;
|
||||
import org.onosproject.yang.runtime.DefaultCompositeStream;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@ -77,6 +80,19 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
@Deprecated
|
||||
protected static final Pattern REGEX_EMPTY_LAST_DEFECT_SENT =
|
||||
Pattern.compile("(<msea-soam-fm:last-defect-sent)[ ]?(/>)", Pattern.DOTALL);
|
||||
public static final String MEF_CFM = "mef-cfm";
|
||||
public static final String MAINTENANCE_DOMAIN = "maintenance-domain";
|
||||
public static final String ID = "id";
|
||||
public static final String MAINTENANCE_ASSOCIATION = "maintenance-association";
|
||||
public static final String TRANSMIT_LOOPBACK = "transmit-loopback";
|
||||
public static final String ABORT_LOOPBACK = "abort-loopback";
|
||||
public static final String MAINTENANCE_ASSOCIATION_END_POINT = "maintenance-association-end-point";
|
||||
public static final String MEP_ID = "mep-id";
|
||||
public static final String DELAY_MEASUREMENTS = "delay-measurements";
|
||||
public static final String DELAY_MEASUREMENT = "delay-measurement";
|
||||
public static final String DM_ID = "dm-id";
|
||||
public static final String MEP_IDENTIFIER = "mep-identifier";
|
||||
public static final String REMOTE_MEPS = "remote-meps";
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
@ -152,6 +168,38 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
return mseaCfm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MseaCfm getMepIds(Optional<MdId> mdIdOptional, Optional<MaIdShort> maIdOptional,
|
||||
NetconfSession session, DatastoreId targetDs) throws NetconfException {
|
||||
|
||||
ModelObjectData.Builder moQueryBldr = DefaultModelObjectData.builder();
|
||||
|
||||
ArrayList annotations = new ArrayList<AnnotatedNodeInfo>();
|
||||
String xmlQueryStr = encodeMoToXmlStr(moQueryBldr.build(), annotations);
|
||||
|
||||
log.debug("Sending <get> for full MEP" +
|
||||
" query on NETCONF session " + session.getSessionId() +
|
||||
":\n" + xmlQueryStr);
|
||||
|
||||
String xmlResult = session.get(xmlQueryStr, null);
|
||||
xmlResult = removeRpcReplyData(xmlResult);
|
||||
xmlResult = removeEmptyActiveDefects(xmlResult);
|
||||
DefaultCompositeStream resultDcs = new DefaultCompositeStream(
|
||||
null, new ByteArrayInputStream(xmlResult.getBytes()));
|
||||
CompositeData compositeData = xSer.decode(resultDcs, yCtx);
|
||||
|
||||
ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
|
||||
|
||||
MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
|
||||
for (ModelObject mo:mod.modelObjects()) {
|
||||
if (mo instanceof DefaultMefCfm) {
|
||||
mseaCfm.mefCfm((DefaultMefCfm) mo);
|
||||
}
|
||||
}
|
||||
|
||||
return mseaCfm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MseaCfm getSoamDm(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
SoamId dmId, DmEntryParts parts, NetconfSession session)
|
||||
@ -190,7 +238,7 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
|
||||
@Override
|
||||
public boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException {
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException {
|
||||
|
||||
ModelObjectData mseCfmDmList = DefaultModelObjectData.builder()
|
||||
.addModelObject((ModelObject) mseaCfm).build();
|
||||
@ -198,7 +246,13 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
|
||||
if (mseaCfm != null && mseaCfm.mefCfm() != null) {
|
||||
for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
|
||||
if (md.id() == 0) {
|
||||
throw new CfmConfigException("An MD numeric ID must be given");
|
||||
}
|
||||
for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
|
||||
if (ma.id() == 0) {
|
||||
throw new CfmConfigException("An MA numeric ID must be given");
|
||||
}
|
||||
for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
|
||||
AugmentedMseaCfmMaintenanceAssociationEndPoint mepAugment =
|
||||
mep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
|
||||
@ -206,16 +260,16 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
for (DelayMeasurement dms:mepAugment.delayMeasurements().delayMeasurement()) {
|
||||
ResourceId.Builder ridBuilder = ResourceId.builder()
|
||||
.addBranchPointSchema("/", null)
|
||||
.addBranchPointSchema("mef-cfm", MSEA_CFM_NS)
|
||||
.addBranchPointSchema("maintenance-domain", MSEA_CFM_NS)
|
||||
.addKeyLeaf("id", MSEA_CFM_NS, md.id())
|
||||
.addBranchPointSchema("maintenance-association", MSEA_CFM_NS)
|
||||
.addKeyLeaf("id", MSEA_CFM_NS, ma.id())
|
||||
.addBranchPointSchema("maintenance-association-end-point", MSEA_CFM_NS)
|
||||
.addKeyLeaf("mep-id", MSEA_CFM_NS, mep.mepIdentifier())
|
||||
.addBranchPointSchema("delay-measurements", MSEA_CFM_PM_NS)
|
||||
.addBranchPointSchema("delay-measurement", MSEA_CFM_PM_NS)
|
||||
.addKeyLeaf("dm-id", MSEA_CFM_PM_NS, mep.mepIdentifier());
|
||||
.addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
|
||||
.addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, md.id())
|
||||
.addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, ma.id())
|
||||
.addBranchPointSchema(MAINTENANCE_ASSOCIATION_END_POINT, MSEA_CFM_NS)
|
||||
.addKeyLeaf(MEP_ID, MSEA_CFM_NS, mep.mepIdentifier())
|
||||
.addBranchPointSchema(DELAY_MEASUREMENTS, MSEA_CFM_PM_NS)
|
||||
.addBranchPointSchema(DELAY_MEASUREMENT, MSEA_CFM_PM_NS)
|
||||
.addKeyLeaf(DM_ID, MSEA_CFM_PM_NS, mep.mepIdentifier());
|
||||
AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(ridBuilder.build())
|
||||
.addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
|
||||
@ -233,7 +287,7 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
|
||||
@Override
|
||||
public boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException {
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException {
|
||||
|
||||
ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
|
||||
.addModelObject((ModelObject) mseaCfm.mefCfm()).build();
|
||||
@ -241,15 +295,100 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
|
||||
if (mseaCfm.mefCfm() != null) {
|
||||
for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
|
||||
if (md.id() == 0) {
|
||||
throw new CfmConfigException("An MD numeric ID must be given");
|
||||
}
|
||||
for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
|
||||
if (ma.id() == 0) {
|
||||
throw new CfmConfigException("An MA numeric ID must be given");
|
||||
}
|
||||
for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
|
||||
ResourceId.Builder ridBuilder = ResourceId.builder()
|
||||
.addBranchPointSchema("/", null)
|
||||
.addBranchPointSchema("mef-cfm", MSEA_CFM_NS)
|
||||
.addBranchPointSchema("maintenance-domain", MSEA_CFM_NS)
|
||||
.addBranchPointSchema("maintenance-association", MSEA_CFM_NS)
|
||||
.addBranchPointSchema("maintenance-association-end-point", MSEA_CFM_NS)
|
||||
.addKeyLeaf("mep-identifier", MSEA_CFM_NS, mep.mepIdentifier().uint16());
|
||||
.addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
|
||||
.addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, md.id())
|
||||
.addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, ma.id())
|
||||
.addBranchPointSchema(MAINTENANCE_ASSOCIATION_END_POINT, MSEA_CFM_NS)
|
||||
.addKeyLeaf(MEP_IDENTIFIER, MSEA_CFM_NS, mep.mepIdentifier().uint16());
|
||||
AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(ridBuilder.build())
|
||||
.addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
|
||||
.build();
|
||||
anis.add(ani);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return setNetconfObject(mseCfmMepList, session, targetDs, anis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMseaMa(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException {
|
||||
|
||||
ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
|
||||
.addModelObject((ModelObject) mseaCfm.mefCfm()).build();
|
||||
|
||||
ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
|
||||
if (mseaCfm != null && mseaCfm.mefCfm() != null) {
|
||||
for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
|
||||
if (md.id() == 0) {
|
||||
throw new CfmConfigException("An MD numeric ID must be given");
|
||||
}
|
||||
for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
|
||||
if (ma.id() == 0) {
|
||||
throw new CfmConfigException("An MA numeric ID must be given");
|
||||
}
|
||||
ResourceId.Builder ridBuilder = ResourceId.builder()
|
||||
.addBranchPointSchema("/", null)
|
||||
.addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
|
||||
.addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, md.id())
|
||||
.addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, ma.id());
|
||||
|
||||
AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(ridBuilder.build())
|
||||
.addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
|
||||
.build();
|
||||
anis.add(ani);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return setNetconfObject(mseCfmMepList, session, targetDs, anis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMseaMaRMep(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException {
|
||||
|
||||
ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
|
||||
.addModelObject((ModelObject) mseaCfm.mefCfm()).build();
|
||||
|
||||
ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
|
||||
if (mseaCfm != null && mseaCfm.mefCfm() != null) {
|
||||
for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
|
||||
if (md.id() == 0) {
|
||||
throw new CfmConfigException("An MD numeric ID must be given");
|
||||
}
|
||||
for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
|
||||
if (ma.id() == 0) {
|
||||
throw new CfmConfigException("An MA numeric ID must be given");
|
||||
}
|
||||
for (MepIdType rmep:ma.remoteMeps()) {
|
||||
ResourceId.Builder ridBuilder = ResourceId.builder()
|
||||
.addBranchPointSchema("/", null)
|
||||
.addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
|
||||
.addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, md.id())
|
||||
.addBranchPointSchema(MAINTENANCE_ASSOCIATION, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, ma.id())
|
||||
.addLeafListBranchPoint(REMOTE_MEPS, MSEA_CFM_NS,
|
||||
Integer.valueOf(rmep.uint16()));
|
||||
AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(ridBuilder.build())
|
||||
.addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
|
||||
@ -264,6 +403,35 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean deleteMseaMd(MseaCfmOpParam mseaCfm, NetconfSession session,
|
||||
DatastoreId targetDs) throws NetconfException, CfmConfigException {
|
||||
|
||||
ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
|
||||
.addModelObject((ModelObject) mseaCfm.mefCfm()).build();
|
||||
|
||||
ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
|
||||
if (mseaCfm != null && mseaCfm.mefCfm() != null) {
|
||||
for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
|
||||
if (md.id() == 0) {
|
||||
throw new CfmConfigException("An MD numeric ID must be given");
|
||||
}
|
||||
ResourceId.Builder ridBuilder = ResourceId.builder()
|
||||
.addBranchPointSchema("/", null)
|
||||
.addBranchPointSchema(MEF_CFM, MSEA_CFM_NS)
|
||||
.addBranchPointSchema(MAINTENANCE_DOMAIN, MSEA_CFM_NS)
|
||||
.addKeyLeaf(ID, MSEA_CFM_NS, md.id());
|
||||
AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(ridBuilder.build())
|
||||
.addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
|
||||
.build();
|
||||
anis.add(ani);
|
||||
}
|
||||
}
|
||||
|
||||
return setNetconfObject(mseCfmMepList, session, targetDs, anis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call RPCs on the device through NETCONF.
|
||||
*/
|
||||
@ -275,7 +443,7 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
.addModelObject((ModelObject) inputVar).build();
|
||||
|
||||
customRpcNetconf(transLoopbackMo,
|
||||
"transmit-loopback", session);
|
||||
TRANSMIT_LOOPBACK, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -284,7 +452,7 @@ public class MseaCfmManager extends AbstractYangServiceImpl
|
||||
ModelObjectData abortLoopbackMo = DefaultModelObjectData.builder()
|
||||
.addModelObject((ModelObject) inputVar).build();
|
||||
|
||||
customRpcNetconf(abortLoopbackMo, "abort-loopback", session);
|
||||
customRpcNetconf(abortLoopbackMo, ABORT_LOOPBACK, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -30,11 +30,14 @@ import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenanc
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameRfc2685VpnId;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameUint16;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameY1731Icc;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.NameCharacterString;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.nameprimaryvid.NamePrimaryVidUnion;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
|
||||
|
||||
/**
|
||||
* This is a workaround for Checkstyle issue.
|
||||
* Utility for translating between Maintenance Association names in the CFM API model and the device YANG.
|
||||
*
|
||||
* This has to be in a separate file as a workaround for Checkstyle issue.
|
||||
* https://github.com/checkstyle/checkstyle/issues/3850
|
||||
* There are two types of DefaultNameCharacterString - one for MA and another for MD
|
||||
* Putting both together in a file means that the full path has to be given which
|
||||
@ -46,6 +49,12 @@ public final class MaNameUtil {
|
||||
//Hidden
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert CFM API MA identifier to the YANG model MA identifier.
|
||||
* @param maId Maintenance Association ID in CFM API
|
||||
* @return Maintenance Association ID in YANG API
|
||||
* @throws CfmConfigException If there's a problem with the name
|
||||
*/
|
||||
public static MaNameAndTypeCombo getYangMaNameFromApiMaId(MaIdShort maId)
|
||||
throws CfmConfigException {
|
||||
MaNameAndTypeCombo maName;
|
||||
@ -70,4 +79,52 @@ public final class MaNameUtil {
|
||||
}
|
||||
return maName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert YANG API MA identifier to the CFM API MA identifier.
|
||||
* @param nameAndTypeCombo Maintenance Association ID in YANG API
|
||||
* @return Maintenance Association ID in CFM API
|
||||
*/
|
||||
public static MaIdShort getApiMaIdFromYangMaName(MaNameAndTypeCombo nameAndTypeCombo) {
|
||||
MaIdShort maId;
|
||||
if (nameAndTypeCombo instanceof DefaultNameCharacterString) {
|
||||
maId = MaIdCharStr.asMaId(
|
||||
((DefaultNameCharacterString) nameAndTypeCombo).name().string());
|
||||
} else if (nameAndTypeCombo instanceof DefaultNamePrimaryVid) {
|
||||
if (((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().enumeration() != null) {
|
||||
maId = MaIdPrimaryVid.asMaId(
|
||||
((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().enumeration().name());
|
||||
} else if (((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().vlanIdType() != null) {
|
||||
maId = MaIdPrimaryVid.asMaId(
|
||||
((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().vlanIdType().uint16());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected primaryVid for " +
|
||||
"MaNameAndTypeCombo: " + nameAndTypeCombo.toString());
|
||||
}
|
||||
} else if (nameAndTypeCombo instanceof DefaultNameUint16) {
|
||||
maId = MaId2Octet.asMaId(((DefaultNameUint16) nameAndTypeCombo).nameUint16());
|
||||
|
||||
} else if (nameAndTypeCombo instanceof DefaultNameRfc2685VpnId) {
|
||||
maId = MaIdRfc2685VpnId.asMaIdHex(
|
||||
HexString.toHexString(
|
||||
((DefaultNameRfc2685VpnId) nameAndTypeCombo).nameRfc2685VpnId()));
|
||||
} else if (nameAndTypeCombo instanceof DefaultNameY1731Icc) {
|
||||
maId = MaIdIccY1731.asMaId(((DefaultNameY1731Icc) nameAndTypeCombo).nameY1731Icc().string());
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected type for " +
|
||||
"MaNameAndTypeCombo: " + nameAndTypeCombo.toString());
|
||||
}
|
||||
|
||||
return maId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the YANG generic type of MaNameAndTypeCombo specifically to char string.
|
||||
* @param maName a YANG generic MaNameAndTypeCombo
|
||||
* @return a YANG specific MaNameAndTypeCombo for Char string
|
||||
*/
|
||||
public static NameCharacterString cast(MaNameAndTypeCombo maName) {
|
||||
return (NameCharacterString) maName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.drivers.microsemi.yang.utils;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.DomainName;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultMacAddressAndUint;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameDomainName;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameNone;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.MacAddressAndUint;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
|
||||
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MacAddressAndUintStr;
|
||||
|
||||
/**
|
||||
* Utility for translating between Maintenance Domain names in the CFM API model and the device YANG.
|
||||
*
|
||||
* This has to be in a separate file as a workaround for Checkstyle issue.
|
||||
* https://github.com/checkstyle/checkstyle/issues/3850
|
||||
* There are two types of DefaultNameCharacterString - one for MA and another for MD
|
||||
* Putting both together in a file means that the full path has to be given which
|
||||
* will then fail checkstyle
|
||||
*/
|
||||
public final class MdNameUtil {
|
||||
|
||||
private MdNameUtil() {
|
||||
//Hidden
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert CFM API MD identifier to the YANG model MD identifier.
|
||||
* @param mdId Maintenance Domain ID in CFM API
|
||||
* @return Maintenance Domain ID in YANG API
|
||||
* @throws CfmConfigException If there's a problem with the name
|
||||
*/
|
||||
public static MdNameAndTypeCombo getYangMdNameFromApiMdId(MdId mdId)
|
||||
throws CfmConfigException {
|
||||
MdNameAndTypeCombo mdName;
|
||||
if (mdId instanceof MdIdDomainName) {
|
||||
boolean isIpAddr = false;
|
||||
try {
|
||||
if (IpAddress.valueOf(mdId.mdName()) != null) {
|
||||
isIpAddr = true;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
//continue
|
||||
}
|
||||
if (isIpAddr) {
|
||||
mdName = new DefaultNameDomainName();
|
||||
((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion.of(
|
||||
org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.
|
||||
IpAddress.fromString(mdId.mdName())));
|
||||
} else {
|
||||
mdName = new DefaultNameDomainName();
|
||||
((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion
|
||||
.of(DomainName.fromString(mdId.mdName())));
|
||||
}
|
||||
} else if (mdId instanceof MdIdMacUint) {
|
||||
mdName = new DefaultMacAddressAndUint();
|
||||
((DefaultMacAddressAndUint) mdName).nameMacAddressAndUint(MacAddressAndUintStr.fromString(mdId.mdName()));
|
||||
} else if (mdId instanceof MdIdNone) {
|
||||
mdName = new DefaultNameNone();
|
||||
} else if (mdId instanceof MdIdCharStr) {
|
||||
mdName = new DefaultNameCharacterString();
|
||||
((DefaultNameCharacterString) mdName).name(Identifier45.fromString(mdId.mdName()));
|
||||
} else {
|
||||
throw new CfmConfigException("Unexpected error creating MD " +
|
||||
mdId.getClass().getSimpleName());
|
||||
}
|
||||
return mdName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert YANG API MD identifier to the CFM API MD identifier.
|
||||
* @param nameAndTypeCombo Maintenance Domain ID in YANG API
|
||||
* @return Maintenance Domain ID in CFM API
|
||||
*/
|
||||
public static MdId getApiMdIdFromYangMdName(MdNameAndTypeCombo nameAndTypeCombo) {
|
||||
MdId mdId;
|
||||
if (nameAndTypeCombo instanceof DefaultNameDomainName) {
|
||||
NameDomainNameUnion domainName =
|
||||
((DefaultNameDomainName) nameAndTypeCombo).nameDomainName();
|
||||
if (domainName.ipAddress() != null) {
|
||||
mdId = MdIdDomainName.asMdId(domainName.ipAddress().toString());
|
||||
} else if (domainName.domainName() != null) {
|
||||
mdId = MdIdDomainName.asMdId(domainName.domainName().string());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected domainName for " +
|
||||
"MdNameAndTypeCombo: " + nameAndTypeCombo.toString());
|
||||
}
|
||||
} else if (nameAndTypeCombo instanceof DefaultNameCharacterString) {
|
||||
mdId = MdIdCharStr.asMdId(
|
||||
((NameCharacterString) nameAndTypeCombo).name().string());
|
||||
|
||||
} else if (nameAndTypeCombo instanceof DefaultMacAddressAndUint) {
|
||||
mdId = MdIdMacUint.asMdId(
|
||||
((MacAddressAndUint) nameAndTypeCombo).nameMacAddressAndUint().string());
|
||||
|
||||
} else if (nameAndTypeCombo instanceof DefaultNameNone) {
|
||||
mdId = MdIdNone.asMdId();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected type for " +
|
||||
"MdNameAndTypeCombo: " + nameAndTypeCombo.toString());
|
||||
}
|
||||
|
||||
return mdId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the YANG generic type of MdNameAndTypeCombo specifically to char string.
|
||||
* @param maName a YANG generic MdNameAndTypeCombo
|
||||
* @return a YANG specific MdNameAndTypeCombo for Char string
|
||||
*/
|
||||
public static NameCharacterString cast(MdNameAndTypeCombo maName) {
|
||||
return (NameCharacterString) maName;
|
||||
}
|
||||
}
|
||||
@ -20,11 +20,13 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getYangMdNameFromApiMdId;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil;
|
||||
import org.onosproject.drivers.microsemi.yang.utils.MdNameUtil;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbCreate;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
|
||||
@ -38,21 +40,24 @@ import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Test of the CFM implementation on EA1000 through the incubator/net/l2monitoring interface.
|
||||
*/
|
||||
public class EA1000CfmMepProgrammableTest {
|
||||
EA1000CfmMepProgrammable cfmProgrammable;
|
||||
public static final MdId MD_ID_1 = MdIdCharStr.asMdId("md-1");
|
||||
public static final MaIdShort MA_ID_11 = MaIdCharStr.asMaId("ma-1-1");
|
||||
public static final MepId MEP_111 = MepId.valueOf((short) 1);
|
||||
public static final MepId MEP_112 = MepId.valueOf((short) 2);
|
||||
|
||||
private CfmMepProgrammable cfmProgrammable;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
cfmProgrammable = new EA1000CfmMepProgrammable();
|
||||
@ -67,12 +72,6 @@ public class EA1000CfmMepProgrammableTest {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testGetAllMeps() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMep() throws CfmConfigException {
|
||||
MepEntry mepEntry = cfmProgrammable.getMep(MD_ID_1, MA_ID_11, MEP_111);
|
||||
@ -143,7 +142,107 @@ public class EA1000CfmMepProgrammableTest {
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteMep() throws CfmConfigException {
|
||||
assertTrue(cfmProgrammable.deleteMep(MD_ID_1, MA_ID_11, MEP_111));
|
||||
assertTrue(cfmProgrammable.deleteMep(MD_ID_1, MA_ID_11, MEP_111, Optional.empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the MD md-1 on the device.
|
||||
* This will retrieve the MD from the MockCfmMdService and will create it
|
||||
* and its MA on the device
|
||||
* Depends on sampleXmlRegexCreateMseaCfmMa
|
||||
*/
|
||||
@Test
|
||||
public void testCreateMaintenanceDomainOnDevice() throws CfmConfigException {
|
||||
boolean success =
|
||||
cfmProgrammable.createMdOnDevice(MdIdCharStr.asMdId("md-1"));
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the MD md-2 on the device.
|
||||
* This will retrieve the MD from the MockCfmMdService and will create it on
|
||||
* the device. This MD has no MA
|
||||
* Depends on sampleXmlRegexCreateMseaCfmMa
|
||||
*/
|
||||
@Test
|
||||
public void testCreateMaintenanceDomainOnDevice2() throws CfmConfigException {
|
||||
boolean success =
|
||||
cfmProgrammable.createMdOnDevice(MdIdCharStr.asMdId("md-2"));
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the MD md-1 on the device.
|
||||
* This will retrieve the MD from the MockCfmMdService and will delete it on
|
||||
* the device.
|
||||
* Depends on sampleXmlRegexCreateMseaCfmMa
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteMaintenanceDomainOnDevice() throws CfmConfigException {
|
||||
boolean success =
|
||||
cfmProgrammable.deleteMdOnDevice(MdIdCharStr.asMdId("md-1"), Optional.empty());
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the MA ma-1-1 on the device.
|
||||
* This will retrieve the MA from the MockCfmMdService and will create it
|
||||
* on the device under md-1
|
||||
* Depends on sampleXmlRegexCreateMseaCfmMa
|
||||
*/
|
||||
@Test
|
||||
public void testCreateMaintenanceAssociationOnDevice() throws CfmConfigException {
|
||||
boolean success =
|
||||
cfmProgrammable.createMaOnDevice(
|
||||
MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"));
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the MD md-1 on the device.
|
||||
* This will retrieve the MD from the MockCfmMdService and will delete it on
|
||||
* the device.
|
||||
* Depends on sampleXmlRegexCreateMseaCfmMa
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteMaintenanceAssociationOnDevice() throws CfmConfigException {
|
||||
boolean success =
|
||||
cfmProgrammable.deleteMaOnDevice(
|
||||
MdIdCharStr.asMdId("md-1"),
|
||||
MaIdCharStr.asMaId("ma-1-1"),
|
||||
Optional.empty());
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Remote Mep 10001 in ma-1-1 on the device.
|
||||
* This will retrieve the MA from the MockCfmMdService and will create the
|
||||
* new remote mep under it on the device
|
||||
* Depends on sampleXmlRegexCreateMseaCfmMa
|
||||
*/
|
||||
@Test
|
||||
public void testCreateRemoteMepOnDevice() throws CfmConfigException {
|
||||
boolean success =
|
||||
cfmProgrammable.createMaRemoteMepOnDevice(
|
||||
MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"),
|
||||
MepId.valueOf((short) 1001));
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the Remote Mep 1002 in ma-1-1 on the device.
|
||||
* This will retrieve the MA from the MockCfmMdService and will delete the
|
||||
* existing remote mep under it on the device
|
||||
* Depends on sampleXmlRegexCreateMseaCfmMa
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteRemoteMepOnDevice() throws CfmConfigException {
|
||||
boolean success =
|
||||
cfmProgrammable.deleteMaRemoteMepOnDevice(
|
||||
MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"),
|
||||
MepId.valueOf((short) 1001));
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,25 +266,21 @@ public class EA1000CfmMepProgrammableTest {
|
||||
cfmProgrammable.abortLoopback(MD_ID_1, MA_ID_11, MEP_111);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testTransmitLinktrace() {
|
||||
// fail("Not yet implemented");
|
||||
// }
|
||||
@Ignore
|
||||
@Test
|
||||
public void testTransmitLinktrace() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetYangMdNameFromApiMdId() throws CfmConfigException {
|
||||
MdNameAndTypeCombo name = EA1000CfmMepProgrammable
|
||||
.getYangMdNameFromApiMdId(MdIdCharStr.asMdId("md-1"));
|
||||
MdNameAndTypeCombo name = getYangMdNameFromApiMdId(MdIdCharStr.asMdId("md-1"));
|
||||
|
||||
assertEquals(org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
|
||||
.maintenancedomain.mdnameandtypecombo
|
||||
.DefaultNameCharacterString.class, name.getClass());
|
||||
|
||||
//There's a problem with checkstyle for typecast on really long paths
|
||||
// assertEquals("md-1", ((org.onosproject.yang.gen.v1.http.www.microsemi.com
|
||||
// .microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.mefcfm
|
||||
// .maintenancedomain.mdnameandtypecombo
|
||||
// .DefaultNameCharacterString) name).name().string());
|
||||
assertEquals("md-1", MdNameUtil.cast(name).name().string());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -196,11 +291,6 @@ public class EA1000CfmMepProgrammableTest {
|
||||
.maintenancedomain.maintenanceassociation.manameandtypecombo
|
||||
.DefaultNameCharacterString.class, name.getClass());
|
||||
|
||||
//There's a problem with checkstyle for typecast on really long paths
|
||||
// assertEquals("ma-1-1", ((org.onosproject.yang.gen.v1.http.www.microsemi.com
|
||||
// .microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.mefcfm
|
||||
// .maintenancedomain.maintenanceassociation.manameandtypecombo
|
||||
// .DefaultNameCharacterString) name).name().string());
|
||||
assertEquals("ma-1-1", MaNameUtil.cast(name).name().string());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import java.util.Map;
|
||||
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.drivers.microsemi.yang.MockCfmMdService;
|
||||
import org.onosproject.drivers.microsemi.yang.MockCfmMepService;
|
||||
import org.onosproject.drivers.microsemi.yang.MockMseaCfmManager;
|
||||
import org.onosproject.drivers.microsemi.yang.MockMseaSaFilteringManager;
|
||||
import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
|
||||
@ -31,6 +32,7 @@ import org.onosproject.drivers.netconf.MockCoreService;
|
||||
import org.onosproject.drivers.netconf.MockNetconfController;
|
||||
import org.onosproject.drivers.netconf.MockNetconfDevice;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.driver.Behaviour;
|
||||
import org.onosproject.net.driver.DefaultDriver;
|
||||
@ -59,6 +61,7 @@ public class MockEa1000DriverHandler implements DriverHandler {
|
||||
private MockMseaUniEvcServiceManager mseaUniEvcService;
|
||||
private MockMseaCfmManager mseaCfmService;
|
||||
private MockCfmMdService mockMdService;
|
||||
private MockCfmMepService mockMepService;
|
||||
private CoreService coreService;
|
||||
|
||||
public MockEa1000DriverHandler() throws NetconfException {
|
||||
@ -92,6 +95,9 @@ public class MockEa1000DriverHandler implements DriverHandler {
|
||||
mockMdService = new MockCfmMdService();
|
||||
mockMdService.activate();
|
||||
|
||||
mockMepService = new MockCfmMepService();
|
||||
mockMepService.activate();
|
||||
|
||||
coreService = new MockCoreService();
|
||||
coreService.registerApplication(MICROSEMI_DRIVERS);
|
||||
}
|
||||
@ -131,6 +137,10 @@ public class MockEa1000DriverHandler implements DriverHandler {
|
||||
|
||||
} else if (serviceClass.equals(CfmMdService.class)) {
|
||||
return (T) mockMdService;
|
||||
|
||||
} else if (serviceClass.equals(CfmMepService.class)) {
|
||||
return (T) mockMepService;
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.onosproject.drivers.microsemi.yang;
|
||||
|
||||
import org.onlab.packet.VlanId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
|
||||
@ -22,6 +24,7 @@ import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMdManager;
|
||||
import static org.easymock.EasyMock.*;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
@ -29,6 +32,9 @@ import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Supports testing of services that reply on the CfmMdService.
|
||||
*/
|
||||
public class MockCfmMdService extends CfmMdManager {
|
||||
|
||||
@Override
|
||||
@ -40,6 +46,11 @@ public class MockCfmMdService extends CfmMdManager {
|
||||
.builder(MaIdCharStr.asMaId("ma-1-1"), 6)
|
||||
.maNumericId((short) 1)
|
||||
.ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_3MS)
|
||||
.addToRemoteMepIdList(MepId.valueOf((short) 10))
|
||||
.addToRemoteMepIdList(MepId.valueOf((short) 20))
|
||||
.addToComponentList(
|
||||
DefaultComponent.builder(1)
|
||||
.addToVidList(VlanId.vlanId((short) 101)).build())
|
||||
.build();
|
||||
|
||||
MdId md1Name = MdIdCharStr.asMdId("md-1");
|
||||
@ -50,14 +61,25 @@ public class MockCfmMdService extends CfmMdManager {
|
||||
.addToMaList(ma)
|
||||
.build();
|
||||
|
||||
MdId md2Name = MdIdCharStr.asMdId("md-2");
|
||||
MaintenanceDomain md2 = DefaultMaintenanceDomain
|
||||
.builder(md1Name)
|
||||
.mdNumericId((short) 2)
|
||||
.mdLevel(MaintenanceDomain.MdLevel.LEVEL2)
|
||||
.build();
|
||||
|
||||
expect(store.createUpdateMaintenanceDomain(md1))
|
||||
.andReturn(true);
|
||||
expect(store.createUpdateMaintenanceDomain(md2))
|
||||
.andReturn(true);
|
||||
expect(store.getMaintenanceDomain(md1Name))
|
||||
.andReturn(Optional.of(md1)).anyTimes();
|
||||
expect(store.getMaintenanceDomain(md2Name))
|
||||
.andReturn(Optional.of(md2)).anyTimes();
|
||||
replay(store);
|
||||
|
||||
} catch (CfmConfigException e) {
|
||||
throw new IllegalArgumentException("Error creating Md md-1 for test");
|
||||
throw new IllegalArgumentException("Error creating MDs for test", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.drivers.microsemi.yang;
|
||||
|
||||
import org.onlab.junit.TestUtils;
|
||||
import org.onlab.packet.ChassisId;
|
||||
import org.onosproject.common.event.impl.TestEventDispatcher;
|
||||
import org.onosproject.core.CoreServiceAdapter;
|
||||
import org.onosproject.core.IdGenerator;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMdManager;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMepManager;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.impl.TestCfmMepProgrammable;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.impl.TestDeviceDiscoveryBehavior;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
|
||||
import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable;
|
||||
import org.onosproject.incubator.net.l2monitoring.soam.impl.TestSoamDmProgrammable;
|
||||
import org.onosproject.net.AnnotationKeys;
|
||||
import org.onosproject.net.DefaultAnnotations;
|
||||
import org.onosproject.net.DefaultDevice;
|
||||
import org.onosproject.net.Device;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.device.DeviceDescriptionDiscovery;
|
||||
import org.onosproject.net.device.DeviceService;
|
||||
import org.onosproject.net.driver.Behaviour;
|
||||
import org.onosproject.net.driver.DefaultDriver;
|
||||
import org.onosproject.net.driver.Driver;
|
||||
import org.onosproject.net.driver.DriverService;
|
||||
import org.onosproject.net.provider.ProviderId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.onosproject.net.NetTestTools.injectEventDispatcher;
|
||||
|
||||
/**
|
||||
* Supports testing of services that reply on the CfmMepService.
|
||||
*/
|
||||
public class MockCfmMepService extends CfmMepManager {
|
||||
private static final String TEST_MFR = "testMfr";
|
||||
private static final String TEST_HW_VERSION = "testHwVersion";
|
||||
private static final String TEST_SW_VERSION = "testSwVersion";
|
||||
private static final String TEST_SN = "testSn";
|
||||
private static final String TEST_DRIVER = "testDriver";
|
||||
protected static final DeviceId DEVICE_ID1 = DeviceId.deviceId("netconf:1.2.3.4:830");
|
||||
|
||||
|
||||
private final DriverService driverService = createMock(DriverService.class);
|
||||
|
||||
private Device device1;
|
||||
private Driver testDriver;
|
||||
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
mepStore = createMock(MepStore.class);
|
||||
cfmMdService = new MockCfmMdService();
|
||||
deviceService = createMock(DeviceService.class);
|
||||
((CfmMdManager) cfmMdService).activate();
|
||||
|
||||
device1 = new DefaultDevice(
|
||||
ProviderId.NONE, DEVICE_ID1, Device.Type.SWITCH,
|
||||
TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION, TEST_SN,
|
||||
new ChassisId(1),
|
||||
DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, TEST_DRIVER).build());
|
||||
|
||||
Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours = new HashMap<>();
|
||||
behaviours.put(DeviceDescriptionDiscovery.class, TestDeviceDiscoveryBehavior.class);
|
||||
behaviours.put(CfmMepProgrammable.class, TestCfmMepProgrammable.class);
|
||||
behaviours.put(SoamDmProgrammable.class, TestSoamDmProgrammable.class);
|
||||
|
||||
TestUtils.setField(this, "coreService", new TestCoreService());
|
||||
TestUtils.setField(this, "deviceService", deviceService);
|
||||
injectEventDispatcher(this, new TestEventDispatcher());
|
||||
|
||||
testDriver = new DefaultDriver(
|
||||
TEST_DRIVER, new ArrayList<Driver>(),
|
||||
TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION,
|
||||
behaviours, new HashMap<>());
|
||||
|
||||
try {
|
||||
Mep mep1 = DefaultMep.builder(
|
||||
MepId.valueOf((short) 10),
|
||||
DEVICE_ID1,
|
||||
PortNumber.P0,
|
||||
Mep.MepDirection.UP_MEP,
|
||||
MdIdCharStr.asMdId("md-1"),
|
||||
MaIdCharStr.asMaId("ma-1-1"))
|
||||
.build();
|
||||
|
||||
expect(mepStore.getMep(new MepKeyId(mep1))).andReturn(Optional.of(mep1)).anyTimes();
|
||||
} catch (CfmConfigException e) {
|
||||
throw new IllegalArgumentException("Error creating MEPs for test", e);
|
||||
}
|
||||
}
|
||||
|
||||
private class TestCoreService extends CoreServiceAdapter {
|
||||
|
||||
@Override
|
||||
public IdGenerator getIdGenerator(String topic) {
|
||||
return new IdGenerator() {
|
||||
private AtomicLong counter = new AtomicLong(0);
|
||||
|
||||
@Override
|
||||
public long getNewId() {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -478,11 +478,12 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter {
|
||||
+ "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
|
||||
+ "(<mef-cfm).*"
|
||||
+ "(<maintenance-domain>)\\R?"
|
||||
+ "(<id/>)?\\R?"
|
||||
+ "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
|
||||
+ "(<id>[0-9]{1,5}</id>)?\\R?"
|
||||
+ "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
|
||||
+ "(<maintenance-association>)\\R?"
|
||||
+ "(<id/>)?\\R?"
|
||||
+ "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
|
||||
+ "(<id>[0-9]{1,5}</id>)?\\R?"
|
||||
+ "((<name>[a-zA-Z0-9\\-:\\.]{1,48}</name>)|"
|
||||
+ "(<name-primary-vid>[0-9]{1,4}</name-primary-vid>))?\\R?"
|
||||
+ "(<maintenance-association-end-point nc:operation=\"delete\">)\\R?"
|
||||
+ "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
|
||||
+ "(</maintenance-association-end-point>)\\R?"
|
||||
@ -492,6 +493,85 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter {
|
||||
+ "(</config>)\\R?"
|
||||
+ "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
|
||||
|
||||
//For testGetConfigMseaCfmEssentials
|
||||
private Pattern sampleXmlRegexCreateMseaCfmMa =
|
||||
Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
|
||||
+ "(<target>\\R?<running/>\\R?</target>)\\R?"
|
||||
+ "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
|
||||
+ "(<mef-cfm).*"
|
||||
+ "(<maintenance-domain>)\\R?"
|
||||
+ "(<id>)([0-9]){1,4}(</id>)\\R?"
|
||||
+ "((<md-level>)([0-9]){1}(</md-level>))?\\R?"
|
||||
+ "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
|
||||
+ "((<maintenance-association>)\\R?"
|
||||
+ "(<id>)([0-9]){1,4}(</id>)\\R?"
|
||||
+ "((<ccm-interval>)(3.3ms)(</ccm-interval>))?\\R?"
|
||||
+ "((<remote-meps>)([0-9]){1,4}(</remote-meps>))*\\R?"
|
||||
+ "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
|
||||
+ "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
|
||||
+ "((<component-list>)\\R?"
|
||||
+ "(<vid>)([0-9]){1,4}(</vid>)\\R?"
|
||||
+ "(</component-list>))?\\R?"
|
||||
+ "(</maintenance-association>))*\\R?"
|
||||
+ "(</maintenance-domain>)\\R?"
|
||||
+ "(</mef-cfm>)\\R?"
|
||||
+ "(</config>)\\R?"
|
||||
+ "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
|
||||
|
||||
//For testGetConfigMseaCfmEssentials
|
||||
private Pattern sampleXmlRegexDeleteMseaCfmMa =
|
||||
Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
|
||||
+ "(<target>\\R?<running/>\\R?</target>)\\R?"
|
||||
+ "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
|
||||
+ "(<mef-cfm).*"
|
||||
+ "(<maintenance-domain>)\\R?"
|
||||
+ "((<id/>)|((<id>)([0-9]){1,4}(</id>)))?\\R?"
|
||||
+ "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
|
||||
+ "(<maintenance-association nc:operation=\"delete\">)\\R?"
|
||||
+ "((<id/>)|((<id>)([0-9]){1,4}(</id>)))?\\R?"
|
||||
+ "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
|
||||
+ "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
|
||||
+ "(</maintenance-association>)\\R?"
|
||||
+ "(</maintenance-domain>)\\R?"
|
||||
+ "(</mef-cfm>)\\R?"
|
||||
+ "(</config>)\\R?"
|
||||
+ "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
|
||||
|
||||
//For testDeleteMseaMepRemoteMep
|
||||
private Pattern sampleXmlRegexDeleteMseaCfmRmep =
|
||||
Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
|
||||
+ "(<target>\\R?<running/>\\R?</target>)\\R?"
|
||||
+ "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
|
||||
+ "(<mef-cfm).*"
|
||||
+ "(<maintenance-domain>)\\R?"
|
||||
+ "((<id>)[0-9]{1,4}(</id>))?\\R?"
|
||||
+ "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
|
||||
+ "(<maintenance-association>)\\R?"
|
||||
+ "((<id>)[0-9]{1,4}(</id>))?\\R?"
|
||||
+ "((<remote-meps nc:operation=\"delete\">)([0-9]){1,4}(</remote-meps>))*\\R?"
|
||||
+ "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
|
||||
+ "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
|
||||
+ "(</maintenance-association>)\\R?"
|
||||
+ "(</maintenance-domain>)\\R?"
|
||||
+ "(</mef-cfm>)\\R?"
|
||||
+ "(</config>)\\R?"
|
||||
+ "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
|
||||
|
||||
//For testDeleteMseaMd
|
||||
private Pattern sampleXmlRegexDeleteMseaCfmMd =
|
||||
Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
|
||||
+ "(<target>\\R?<running/>\\R?</target>)\\R?"
|
||||
+ "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
|
||||
+ "(<mef-cfm).*"
|
||||
+ "(<maintenance-domain nc:operation=\"delete\">)\\R?"
|
||||
+ "((<id/>)|(<id>([0-9]){1,4}(</id>)))?\\R?"
|
||||
+ "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|\\R?"
|
||||
+ "((<name-domain-name>)([a-zA-Z0-9\\-\\.]){1,48}(</name-domain-name>)))?\\R?"
|
||||
+ "(</maintenance-domain>)\\R?"
|
||||
+ "(</mef-cfm>)\\R?"
|
||||
+ "(</config>)\\R?"
|
||||
+ "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
|
||||
|
||||
|
||||
private Pattern sampleXmlRegexTransmitLoopback =
|
||||
Pattern.compile("(<\\?xml).*(<rpc).*\\R?"
|
||||
@ -1310,6 +1390,18 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter {
|
||||
} else if (sampleXmlRegexDeleteMseaCfmMep.matcher(request).matches()) {
|
||||
return SAMPLE_REPLY_OK;
|
||||
|
||||
} else if (sampleXmlRegexCreateMseaCfmMa.matcher(request).matches()) {
|
||||
return SAMPLE_REPLY_OK;
|
||||
|
||||
} else if (sampleXmlRegexDeleteMseaCfmMa.matcher(request).matches()) {
|
||||
return SAMPLE_REPLY_OK;
|
||||
|
||||
} else if (sampleXmlRegexDeleteMseaCfmRmep.matcher(request).matches()) {
|
||||
return SAMPLE_REPLY_OK;
|
||||
|
||||
} else if (sampleXmlRegexDeleteMseaCfmMd.matcher(request).matches()) {
|
||||
return SAMPLE_REPLY_OK;
|
||||
|
||||
} else if (sampleXmlRegexGetMseaDelay.matcher(request).matches()) {
|
||||
return SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY;
|
||||
|
||||
|
||||
@ -36,20 +36,31 @@ import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
|
||||
import org.onosproject.netconf.DatastoreId;
|
||||
import org.onosproject.netconf.NetconfDeviceInfo;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
import org.onosproject.netconf.NetconfSession;
|
||||
import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.MacAddress;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.DefaultAbortLoopbackInput;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNamePrimaryVid;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.NamePrimaryVid;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.nameprimaryvid.NamePrimaryVidUnion;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameDomainName;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameDomainName;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.AddressType;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress;
|
||||
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId;
|
||||
@ -194,10 +205,173 @@ public class MseaCfmManagerTest {
|
||||
// mseaCfmService.setMseaCfm(mseaCfmOpParam, session, NcDsType.running);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using mep Id 10.
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteMseaMep() {
|
||||
MaintenanceAssociationEndPoint mep10 = new DefaultMaintenanceAssociationEndPoint();
|
||||
mep10.mepIdentifier(MepIdType.of(10));
|
||||
|
||||
MaintenanceAssociation ma1100 = new DefaultMaintenanceAssociation();
|
||||
NamePrimaryVid pvid1100Name = new DefaultNamePrimaryVid();
|
||||
pvid1100Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1100"));
|
||||
ma1100.maNameAndTypeCombo(pvid1100Name);
|
||||
ma1100.id((short) 1100);
|
||||
ma1100.addToMaintenanceAssociationEndPoint(mep10);
|
||||
|
||||
MaintenanceDomain md = new DefaultMaintenanceDomain();
|
||||
NameCharacterString mdName = new DefaultNameCharacterString();
|
||||
mdName.name(new Identifier45("md-1"));
|
||||
md.mdNameAndTypeCombo(mdName);
|
||||
md.id((short) 1);
|
||||
md.addToMaintenanceAssociation(ma1100);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(md);
|
||||
MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
|
||||
mseaCfm.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
boolean deleted = mseaCfmService.deleteMseaMep(mseaCfm, session, DatastoreId.RUNNING);
|
||||
assertTrue(deleted);
|
||||
} catch (NetconfException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (CfmConfigException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using mep Id 10.
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteMseaMa() {
|
||||
MaintenanceAssociation ma1300 = new DefaultMaintenanceAssociation();
|
||||
NamePrimaryVid pvid1300Name = new DefaultNamePrimaryVid();
|
||||
pvid1300Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1300"));
|
||||
ma1300.id((short) 1300);
|
||||
ma1300.maNameAndTypeCombo(pvid1300Name);
|
||||
|
||||
MaintenanceDomain md = new DefaultMaintenanceDomain();
|
||||
NameCharacterString mdName = new DefaultNameCharacterString();
|
||||
mdName.name(new Identifier45("md-13"));
|
||||
md.mdNameAndTypeCombo(mdName);
|
||||
md.id((short) 13);
|
||||
md.addToMaintenanceAssociation(ma1300);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(md);
|
||||
MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
|
||||
mseaCfm.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
boolean deleted = mseaCfmService.deleteMseaMa(mseaCfm, session, DatastoreId.RUNNING);
|
||||
assertTrue(deleted);
|
||||
} catch (NetconfException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (CfmConfigException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteMseaRemoteMep() {
|
||||
MaintenanceAssociation ma1100 = new DefaultMaintenanceAssociation();
|
||||
NamePrimaryVid pvid1100Name = new DefaultNamePrimaryVid();
|
||||
pvid1100Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1100"));
|
||||
ma1100.maNameAndTypeCombo(pvid1100Name);
|
||||
ma1100.id((short) 1100);
|
||||
ma1100.addToRemoteMeps(MepIdType.of(100));
|
||||
ma1100.addToRemoteMeps(MepIdType.of(101));
|
||||
|
||||
MaintenanceDomain md = new DefaultMaintenanceDomain();
|
||||
NameCharacterString mdName = new DefaultNameCharacterString();
|
||||
mdName.name(new Identifier45("md-1"));
|
||||
md.mdNameAndTypeCombo(mdName);
|
||||
md.id((short) 1);
|
||||
md.addToMaintenanceAssociation(ma1100);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(md);
|
||||
MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
|
||||
mseaCfm.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
boolean deleted = mseaCfmService.deleteMseaMaRMep(mseaCfm, session, DatastoreId.RUNNING);
|
||||
assertTrue(deleted);
|
||||
} catch (NetconfException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (CfmConfigException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using mep Id 10.
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteMseaMdById() {
|
||||
|
||||
MaintenanceDomain md = new DefaultMaintenanceDomain();
|
||||
NameDomainName mdName = new DefaultNameDomainName();
|
||||
mdName.nameDomainName(NameDomainNameUnion.fromString("www.opennetworking.org"));
|
||||
md.mdNameAndTypeCombo(mdName);
|
||||
md.id((short) 10);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(md);
|
||||
MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
|
||||
mseaCfm.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
boolean deleted = mseaCfmService.deleteMseaMd(mseaCfm, session, DatastoreId.RUNNING);
|
||||
assertTrue(deleted);
|
||||
} catch (NetconfException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (CfmConfigException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using mep Id 10.
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteMseaMdByName() {
|
||||
|
||||
MaintenanceDomain md = new DefaultMaintenanceDomain();
|
||||
NameDomainName mdName = new DefaultNameDomainName();
|
||||
mdName.nameDomainName(NameDomainNameUnion.fromString("www.opennetworking.org"));
|
||||
md.mdNameAndTypeCombo(mdName);
|
||||
|
||||
MefCfm mefCfm = new DefaultMefCfm();
|
||||
mefCfm.addToMaintenanceDomain(md);
|
||||
MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
|
||||
mseaCfm.mefCfm(mefCfm);
|
||||
|
||||
try {
|
||||
mseaCfmService.deleteMseaMd(mseaCfm, session, DatastoreId.RUNNING);
|
||||
fail("Should not have succeeded as no numeric id was given");
|
||||
} catch (NetconfException | CfmConfigException e) {
|
||||
assertEquals("An MD numeric ID must be given", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Using Remote remote MEP ID and all arguments.
|
||||
*/
|
||||
@Test
|
||||
public void testTransmitLoopback1() {
|
||||
TransmitLoopbackInput lbTr1 = new DefaultTransmitLoopbackInput();
|
||||
lbTr1.maintenanceDomain(Short.valueOf((short) 1));
|
||||
@ -221,10 +395,10 @@ public class MseaCfmManagerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* Using Remote Mac address in place of remote MEP ID and fewer arguments.
|
||||
*/
|
||||
@Test
|
||||
public void testTransmitLoopback2() {
|
||||
TransmitLoopbackInput lbTr2 = new DefaultTransmitLoopbackInput();
|
||||
|
||||
|
||||
@ -212,6 +212,12 @@ public final class DefaultMaintenanceAssociation implements MaintenanceAssociati
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaBuilder removeFromRemoteMepIdList(MepId remoteMep) {
|
||||
this.remoteMepIdList.remove(remoteMep);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaBuilder ccmInterval(CcmInterval ccmInterval) {
|
||||
this.ccmInterval = ccmInterval;
|
||||
|
||||
@ -113,6 +113,8 @@ public interface MaintenanceAssociation extends NetworkResource {
|
||||
|
||||
MaBuilder addToRemoteMepIdList(MepId remoteMep);
|
||||
|
||||
MaBuilder removeFromRemoteMepIdList(MepId remoteMep);
|
||||
|
||||
MaBuilder addToComponentList(Component component);
|
||||
|
||||
MaBuilder maNumericId(short maNumericId);
|
||||
|
||||
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.identifier;
|
||||
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
|
||||
/**
|
||||
* Immutable class to represent a unique identifier of a Mep.
|
||||
*/
|
||||
public class MepKeyId {
|
||||
private MdId mdId;
|
||||
private MaIdShort maId;
|
||||
private MepId mepId;
|
||||
|
||||
public MepKeyId(MdId mdId, MaIdShort maId, MepId mepId) {
|
||||
this.mdId = mdId;
|
||||
this.maId = maId;
|
||||
this.mepId = mepId;
|
||||
if (mdId == null || maId == null || mepId == null) {
|
||||
throw new IllegalArgumentException("Arguments to MepKeyId constructor cannot be null");
|
||||
}
|
||||
}
|
||||
|
||||
public MepKeyId(Mep mep) {
|
||||
this.mdId = mep.mdId();
|
||||
this.maId = mep.maId();
|
||||
this.mepId = mep.mepId();
|
||||
}
|
||||
|
||||
public MdId mdId() {
|
||||
return mdId;
|
||||
}
|
||||
|
||||
public MaIdShort maId() {
|
||||
return maId;
|
||||
}
|
||||
|
||||
public MepId mepId() {
|
||||
return mepId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MepKeyId mepKeyId = (MepKeyId) o;
|
||||
|
||||
if (mdId != null ? !mdId.equals(mepKeyId.mdId) : mepKeyId.mdId != null) {
|
||||
return false;
|
||||
}
|
||||
if (maId != null ? !maId.equals(mepKeyId.maId) : mepKeyId.maId != null) {
|
||||
return false;
|
||||
}
|
||||
return mepId != null ? mepId.equals(mepKeyId.mepId) : mepKeyId.mepId == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = mdId != null ? mdId.hashCode() : 0;
|
||||
result = 31 * result + (maId != null ? maId.hashCode() : 0);
|
||||
result = 31 * result + (mepId != null ? mepId.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mdId.mdName() + "/" + maId.maName() + "/" + mepId();
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.onosproject.event.ListenerService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
@ -26,7 +27,7 @@ import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
/**
|
||||
* For the management of Maintenance Domains and Maintenance Associations.
|
||||
*/
|
||||
public interface CfmMdService {
|
||||
public interface CfmMdService extends ListenerService<MdEvent, MdListener> {
|
||||
|
||||
/**
|
||||
* Get a list of all of the Maintenance Domains on the system.
|
||||
|
||||
@ -16,12 +16,12 @@
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
|
||||
import org.onosproject.event.AbstractEvent;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
|
||||
/**
|
||||
* Event related to the maintenance of CFM MEPs.
|
||||
*/
|
||||
public class CfmMepEvent extends AbstractEvent<CfmMepEvent.Type, Mep> {
|
||||
public class CfmMepEvent extends AbstractEvent<CfmMepEvent.Type, MepKeyId> {
|
||||
|
||||
/**
|
||||
* Type of Mep events.
|
||||
@ -52,10 +52,9 @@ public class CfmMepEvent extends AbstractEvent<CfmMepEvent.Type, Mep> {
|
||||
* Creates an event of a given type and for the specified Mep and the current time.
|
||||
*
|
||||
* @param type Mep event type
|
||||
* @param mep event Mep subject
|
||||
* @param mepKeyId event Mep subject
|
||||
*/
|
||||
protected CfmMepEvent(Type type, Mep mep) {
|
||||
super(type, mep);
|
||||
// TODO Auto-generated constructor stub
|
||||
public CfmMepEvent(Type type, MepKeyId mepKeyId) {
|
||||
super(type, mepKeyId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,14 +15,95 @@
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.net.driver.HandlerBehaviour;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Behaviour that allows Layer 2 Monitoring as defined in IEEE 802.1Q be implemented by devices.
|
||||
*
|
||||
* Has all of the same methods as
|
||||
* {@link org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService} so reuse that
|
||||
* {@link CfmMepServiceBase} so reuse that
|
||||
*/
|
||||
public interface CfmMepProgrammable extends HandlerBehaviour, CfmMepService {
|
||||
public interface CfmMepProgrammable extends HandlerBehaviour, CfmMepServiceBase {
|
||||
|
||||
|
||||
/**
|
||||
* Allows an MD and children MAs to be created on a device.
|
||||
* A convenience method that allows an MD to be created on a device
|
||||
* This is a preparation mechanism. If this was not called the MD would be created
|
||||
* at the time of provisioning a MEP anyway
|
||||
* @param mdId The ID of the MD to create - the details will be got from the CfmMdService
|
||||
* @return true when created. false if it already existed
|
||||
* @throws CfmConfigException If the MD already exists
|
||||
*/
|
||||
boolean createMdOnDevice(MdId mdId) throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Allows an MA to be created on an existing MD on a device.
|
||||
* A convenience method that allows an MA to be created
|
||||
* This is a preparation mechanism. If this was not called the MA would be created
|
||||
* at the time of provisioning a MEP anyway. Also MAs can be created when they
|
||||
* are contained in an MD using the createMdOnDevice method
|
||||
* @param mdId The identifier of the MD to create the MA in
|
||||
* @param maId The identifier of the MA to create - the details will be retrieved from the CfmMdService
|
||||
* @return true when created. false if it already existed
|
||||
* @throws CfmConfigException If the MD already exists
|
||||
*/
|
||||
boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Allows a MD and its MAs to be deleted from a device.
|
||||
* A convenience method that allows an MD that has been provisioned on a
|
||||
* device to be removed.
|
||||
* All Meps must be removed first unless they are Meps unknown to ONOS.
|
||||
* This is a cleanup mechanism. Deleting Meps in the normal way does not celan
|
||||
* up MDs and MAs
|
||||
* @param mdId The identifier of the MD
|
||||
* @param oldMd The MaintenanceDomain that is being deleted
|
||||
* @return true when deleted. false if it did not exist
|
||||
* @throws CfmConfigException If the MD has any MAs that have MEPs then this will fail
|
||||
*/
|
||||
boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd) throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Allows an MA to be deleted from an MD on a device.
|
||||
* A convenience method that allows an MA that has been provisioned on a
|
||||
* device to be removed.
|
||||
* All Meps must be removed first unless they are Meps unknown to ONOS.
|
||||
* This is a cleanup mechanism. Deleting Meps in the normal way does not celan
|
||||
* up MDs and MAs
|
||||
* @param mdId The identifier of the MD
|
||||
* @param maId The identifier of the MA
|
||||
* @param oldMd The MaintenanceDomain from which the MA is being deleted
|
||||
* @return true when deleted. false if it did not exist
|
||||
* @throws CfmConfigException If the MA has any MEPs then this will fail
|
||||
*/
|
||||
boolean deleteMaOnDevice(MdId mdId, MaIdShort maId,
|
||||
Optional<MaintenanceDomain> oldMd) throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Creates a Remote Mep entry on an MA.
|
||||
* @param mdId The identifier of the MD
|
||||
* @param maId The identifier of the MA
|
||||
* @param remoteMep The remote Mep Id to remove from the MA
|
||||
* @return true when deleted. false if it did not exist
|
||||
* @throws CfmConfigException If the MA does not exist this will fail
|
||||
*/
|
||||
boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Deletes a Remote Mep entry on an MA.
|
||||
* @param mdId The identifier of the MD
|
||||
* @param maId The identifier of the MA
|
||||
* @param remoteMep The remote Mep Id to remove from the MA
|
||||
* @return true when deleted. false if it did not exist
|
||||
* @throws CfmConfigException If the MA does not exist this will fail
|
||||
*/
|
||||
boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException;
|
||||
|
||||
}
|
||||
|
||||
@ -17,13 +17,12 @@ package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.onosproject.event.ListenerService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.net.DeviceId;
|
||||
|
||||
/**
|
||||
* For the management of Maintenance Association Endpoints.
|
||||
@ -31,7 +30,8 @@ import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
* These are dependent on the Maintenance Domain service which maintains the
|
||||
* Maintenance Domain and Maintenance Associations
|
||||
*/
|
||||
public interface CfmMepService {
|
||||
public interface CfmMepService
|
||||
extends ListenerService<CfmMepEvent, CfmMepListener>, CfmMepServiceBase {
|
||||
/**
|
||||
* Retrieve all {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry}(s) belonging to an MA.
|
||||
* @param mdName A Maintenance Domain
|
||||
@ -43,67 +43,13 @@ public interface CfmMepService {
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Retrieve a named {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry} belonging to an MA.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @return A MEP Entry or null if none found
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Delete a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} belonging to an MA.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @return true if the MEP was deleted successfully. false if it was not found
|
||||
* Retrieve all {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep}(s) belonging to an MA.
|
||||
* Note: This just returns the configuration part of the Mep, not the MepEntry
|
||||
* which contains config and state
|
||||
* @param deviceId A device id
|
||||
* @return A collection of MEP Entries
|
||||
* @throws CfmConfigException If there a problem with the MD or MA
|
||||
*/
|
||||
boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId)
|
||||
Collection<Mep> getAllMepsByDevice(DeviceId deviceId)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Create a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} on an MA.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mep A Mep object
|
||||
* @return False if it was created successfully. True if the object already exists.
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
boolean createMep(MdId mdName, MaIdShort maName, Mep mep)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @param lbCreate The Loopback session details
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
MepLbCreate lbCreate) throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Abort a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtEntry Linktrace} session on the named Mep.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @param ltCreate The Linktrace session details
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
MepLtCreate ltCreate) throws CfmConfigException;
|
||||
}
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CfmMepServiceBase {
|
||||
/**
|
||||
* Retrieve a named {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry} belonging to an MA.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @return A MEP Entry or null if none found
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Delete a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} belonging to an MA.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @param oldMd The MaintenanceDomain from which the MEP is being deleted
|
||||
* @return true if the MEP was deleted successfully. false if it was not found
|
||||
* @throws CfmConfigException If there a problem with the MD or MA
|
||||
*/
|
||||
boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId, Optional<MaintenanceDomain> oldMd)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Create a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} on an MA.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mep A Mep object
|
||||
* @return True if it was created successfully. False if the object already exists.
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
boolean createMep(MdId mdName, MaIdShort maName, Mep mep)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @param lbCreate The Loopback session details
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
MepLbCreate lbCreate) throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Abort a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
|
||||
throws CfmConfigException;
|
||||
|
||||
/**
|
||||
* Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtEntry Linktrace} session on the named Mep.
|
||||
* @param mdName A Maintenance Domain
|
||||
* @param maName A Maintetance Association in the MD
|
||||
* @param mepId A Mep Id
|
||||
* @param ltCreate The Linktrace session details
|
||||
* @throws CfmConfigException If there a problem with the MD, MA or MEP
|
||||
*/
|
||||
void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
MepLtCreate ltCreate) throws CfmConfigException;
|
||||
}
|
||||
@ -15,24 +15,78 @@
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.onlab.util.Tools;
|
||||
import org.onosproject.event.AbstractEvent;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Event related to the maintenance of CFM MDs.
|
||||
*/
|
||||
public class MdEvent extends AbstractEvent<MdEvent.Type, MdId> {
|
||||
|
||||
private MaIdShort maId;
|
||||
private MaintenanceDomain oldMd;
|
||||
/**
|
||||
* MD Event types supported.
|
||||
*/
|
||||
public enum Type {
|
||||
MD_ADDED,
|
||||
MD_REMOVED,
|
||||
MD_UPDATED
|
||||
MD_UPDATED,
|
||||
MA_ADDED,
|
||||
MA_REMOVED
|
||||
}
|
||||
|
||||
public MdEvent(Type type, MdId mdId) {
|
||||
super(type, mdId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that allows the MD to be held in the event.
|
||||
* This is useful if the MD had been deleted - it will be the only way of
|
||||
* retrieving some of its attributes
|
||||
* @param type The type of the event
|
||||
* @param mdId The ID of the MD
|
||||
* @param md The whole MD
|
||||
* @throws CfmConfigException if there's a problem copying MD
|
||||
*/
|
||||
public MdEvent(Type type, MdId mdId, MaintenanceDomain md) throws CfmConfigException {
|
||||
super(type, mdId);
|
||||
this.oldMd = DefaultMaintenanceDomain.builder(md).build();
|
||||
}
|
||||
|
||||
public MdEvent(Type type, MdId mdId, MaintenanceDomain md, MaIdShort maId)
|
||||
throws CfmConfigException {
|
||||
super(type, mdId);
|
||||
this.maId = maId;
|
||||
this.oldMd = DefaultMaintenanceDomain.builder(md).build();
|
||||
}
|
||||
|
||||
public Optional<MaIdShort> maId() {
|
||||
return maId == null ? Optional.empty() : Optional.of(maId);
|
||||
}
|
||||
|
||||
public Optional<MaintenanceDomain> md() {
|
||||
return oldMd == null ? Optional.empty() : Optional.of(oldMd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
MoreObjects.ToStringHelper helper = toStringHelper(this)
|
||||
.add("time", Tools.defaultOffsetDataTime(time()))
|
||||
.add("type", type())
|
||||
.add("subject", subject());
|
||||
if (maId != null) {
|
||||
helper = helper.add("subject2", maId);
|
||||
}
|
||||
return helper.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2018-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.store.Store;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep Maintenance Association Endpoint's} storage interface.
|
||||
* Note: because the Mep is immutable if anything needs to be
|
||||
* changed in it, then it must be replaced in the store.
|
||||
*/
|
||||
public interface MepStore extends Store<CfmMepEvent, MepStoreDelegate> {
|
||||
/**
|
||||
* Get a list of all of the Meps on the system.
|
||||
* @return A collection Meps from the Mep Store.
|
||||
*/
|
||||
Collection<Mep> getAllMeps();
|
||||
|
||||
/**
|
||||
* Get all Meps by MD.
|
||||
* @param mdName An identifier for the Maintenance Domain
|
||||
* @return MEPs from the MEP Store. Empty if not found.
|
||||
*/
|
||||
Collection<Mep> getMepsByMd(MdId mdName);
|
||||
|
||||
/**
|
||||
* Get all Meps by MD, MA.
|
||||
* @param mdName An identifier for the Maintenance Domain
|
||||
* @param maName An identifier for the Maintenance Association
|
||||
* @return MEPs from the MEP Store. Empty if not found.
|
||||
*/
|
||||
Collection<Mep> getMepsByMdMa(MdId mdName, MaIdShort maName);
|
||||
|
||||
/**
|
||||
* Get all Meps by DeviceId.
|
||||
* @param deviceId An identifier for the Device
|
||||
* @return MEPs from the MEP Store. Empty if not found.
|
||||
*/
|
||||
Collection<Mep> getMepsByDeviceId(DeviceId deviceId);
|
||||
|
||||
/**
|
||||
* Get a specific Mep by its Mep key id.
|
||||
* @param mepKeyId An unique identifier for the MEP
|
||||
* @return A MEP from the MEP Store. Empty if not found.
|
||||
*/
|
||||
Optional<Mep> getMep(MepKeyId mepKeyId);
|
||||
|
||||
/**
|
||||
* Delete a specific Mep by its identifier.
|
||||
* @param mepKeyId An unique identifier for the MEP
|
||||
* @return True if the Mep was found and deleted
|
||||
*/
|
||||
boolean deleteMep(MepKeyId mepKeyId);
|
||||
|
||||
/**
|
||||
* Create or replace a Mep.
|
||||
* @param mepKeyId An unique identifier for the MEP
|
||||
* @param mep The new MEP
|
||||
* @return true if an Mep of this name already existed
|
||||
*/
|
||||
boolean createUpdateMep(MepKeyId mepKeyId, Mep mep);
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2018-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.service;
|
||||
|
||||
import org.onosproject.store.StoreDelegate;
|
||||
|
||||
/**
|
||||
* Delegate for MEP Store.
|
||||
*/
|
||||
public interface MepStoreDelegate extends StoreDelegate<CfmMepEvent> {
|
||||
}
|
||||
@ -65,10 +65,8 @@ public class CfmMdManager extends AbstractListenerManager<MdEvent, MdListener>
|
||||
@Activate
|
||||
public void activate() {
|
||||
appId = coreService.registerApplication(APP_ID);
|
||||
|
||||
eventDispatcher.addSink(MdEvent.class, listenerRegistry);
|
||||
store.setDelegate(delegate);
|
||||
|
||||
log.info("CFM Service Started");
|
||||
}
|
||||
|
||||
@ -163,9 +161,8 @@ public class CfmMdManager extends AbstractListenerManager<MdEvent, MdListener>
|
||||
private class InternalStoreDelegate implements MdStoreDelegate {
|
||||
@Override
|
||||
public void notify(MdEvent event) {
|
||||
log.debug("New MD event: {}", event.subject());
|
||||
log.debug("New MD event: {}", event);
|
||||
eventDispatcher.post(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -15,10 +15,21 @@
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.impl;
|
||||
|
||||
import static org.onlab.util.Tools.groupedThreads;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.felix.scr.annotations.Activate;
|
||||
import org.apache.felix.scr.annotations.Component;
|
||||
@ -29,6 +40,8 @@ import org.apache.felix.scr.annotations.Service;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.core.IdGenerator;
|
||||
import org.onosproject.event.AbstractListenerManager;
|
||||
import org.onosproject.event.Event;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
|
||||
@ -36,12 +49,17 @@ import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepEvent;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepListener;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MdEvent;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MdListener;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStoreDelegate;
|
||||
import org.onosproject.mastership.MastershipService;
|
||||
import org.onosproject.net.Device;
|
||||
import org.onosproject.net.DeviceId;
|
||||
@ -61,7 +79,8 @@ public class CfmMepManager
|
||||
|
||||
private final Logger log = getLogger(getClass());
|
||||
|
||||
private final DeviceListener deviceListener = new InternalDeviceListener();
|
||||
private InternalDeviceListener deviceListener = null;
|
||||
private InternalMdListener mdListener = null;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected DeviceService deviceService;
|
||||
@ -78,22 +97,39 @@ public class CfmMepManager
|
||||
private static final int DEFAULT_POLL_FREQUENCY = 30;
|
||||
private int fallbackMepPollFrequency = DEFAULT_POLL_FREQUENCY;
|
||||
|
||||
private InternalEventHandler eventHandler = new InternalEventHandler();
|
||||
private static final Object THREAD_SCHED_LOCK = new Object();
|
||||
private static int numOfEventsQueued = 0;
|
||||
private static int numOfEventsExecuted = 0;
|
||||
private static int numOfHandlerExecution = 0;
|
||||
private static int numOfHandlerScheduled = 0;
|
||||
|
||||
private ScheduledExecutorService executorService = Executors
|
||||
.newScheduledThreadPool(1,
|
||||
groupedThreads("CfmMepManager", "event-%d", log));
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static ScheduledFuture<?> eventHandlerFuture = null;
|
||||
@SuppressWarnings("rawtypes")
|
||||
private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
|
||||
private IdGenerator idGenerator;
|
||||
|
||||
//FIXME Get rid of this hack - we will use this in memory to emulate
|
||||
// a store for the short term.
|
||||
//Note: This is not distributed and will not work in a clustered system
|
||||
//TODO Create a MepStore for this
|
||||
private Collection<Mep> mepCollection;
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected MepStore mepStore;
|
||||
|
||||
protected final MepStoreDelegate delegate = new InternalStoreDelegate();
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
//FIXME Get rid of this local list
|
||||
mepCollection = new ArrayList<>();
|
||||
mepStore.setDelegate(delegate);
|
||||
|
||||
eventDispatcher.addSink(CfmMepEvent.class, listenerRegistry);
|
||||
deviceListener = new InternalDeviceListener();
|
||||
deviceService.addListener(deviceListener);
|
||||
mdListener = new InternalMdListener();
|
||||
cfmMdService.addListener(mdListener);
|
||||
eventDispatcher.addSink(CfmMepEvent.class, listenerRegistry);
|
||||
idGenerator = coreService.getIdGenerator("mep-ids");
|
||||
log.info("CFM MEP Manager Started");
|
||||
}
|
||||
@ -101,9 +137,12 @@ public class CfmMepManager
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
deviceService.removeListener(deviceListener);
|
||||
cfmMdService.removeListener(mdListener);
|
||||
eventDispatcher.removeSink(CfmMepEvent.class);
|
||||
log.info("CFM MEP Manager Stopped");
|
||||
mepCollection.clear();
|
||||
mepStore.unsetDelegate(delegate);
|
||||
deviceListener = null;
|
||||
mdListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -112,27 +151,28 @@ public class CfmMepManager
|
||||
//Will throw IllegalArgumentException if ma does not exist
|
||||
cfmMdService.getMaintenanceAssociation(mdName, maName);
|
||||
|
||||
Collection<Mep> mepStoreCollection = mepStore.getAllMeps();
|
||||
Collection<MepEntry> mepEntryCollection = new ArrayList<>();
|
||||
|
||||
for (Mep mep:mepCollection) {
|
||||
for (Mep mep : mepStoreCollection) {
|
||||
if (mep.mdId().equals(mdName) && mep.maId().equals(maName)) {
|
||||
DeviceId mepDeviceId = mep.deviceId();
|
||||
if (deviceService.getDevice(mepDeviceId) == null) {
|
||||
log.warn("Device not found/available " + mepDeviceId +
|
||||
" for MEP: " + mdName + "/" + maName + "/" + mep.mepId());
|
||||
" for MEP: " + mdName + "/" + maName + "/" + mep.mepId());
|
||||
continue;
|
||||
} else if (!deviceService.getDevice(mepDeviceId)
|
||||
.is(CfmMepProgrammable.class)) {
|
||||
.is(CfmMepProgrammable.class)) {
|
||||
throw new CfmConfigException("Device " + mepDeviceId +
|
||||
" does not support CfmMepProgrammable behaviour.");
|
||||
}
|
||||
|
||||
log.debug("Retrieving MEP results for Mep {} in MD {}, MA {} "
|
||||
+ "on Device {}", mep.mepId(), mdName, maName, mepDeviceId);
|
||||
+ "on Device {}", mep.mepId(), mdName, maName, mepDeviceId);
|
||||
mepEntryCollection.add(deviceService
|
||||
.getDevice(mepDeviceId)
|
||||
.as(CfmMepProgrammable.class)
|
||||
.getMep(mdName, maName, mep.mepId()));
|
||||
.getDevice(mepDeviceId)
|
||||
.as(CfmMepProgrammable.class)
|
||||
.getMep(mdName, maName, mep.mepId()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,75 +180,116 @@ public class CfmMepManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
|
||||
//Will throw IllegalArgumentException if ma does not exist
|
||||
cfmMdService.getMaintenanceAssociation(mdName, maName);
|
||||
|
||||
for (Mep mep : mepCollection) {
|
||||
if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
|
||||
&& mep.mepId().equals(mepId)) {
|
||||
|
||||
DeviceId mepDeviceId = mep.deviceId();
|
||||
if (deviceService.getDevice(mepDeviceId) == null) {
|
||||
throw new CfmConfigException("Device not found " + mepDeviceId);
|
||||
} else if (!deviceService.getDevice(mepDeviceId).is(CfmMepProgrammable.class)) {
|
||||
throw new CfmConfigException("Device " + mepDeviceId +
|
||||
" does not support CfmMepProgrammable behaviour.");
|
||||
}
|
||||
|
||||
log.debug("Retrieving MEP reults for Mep {} in MD {}, MA {} on Device {}",
|
||||
mep.mepId(), mdName, maName, mepDeviceId);
|
||||
|
||||
return deviceService.getDevice(mepDeviceId)
|
||||
.as(CfmMepProgrammable.class).getMep(mdName, maName, mepId);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public Collection<Mep> getAllMepsByDevice(DeviceId deviceId) throws CfmConfigException {
|
||||
return mepStore.getMepsByDeviceId(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
|
||||
public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
|
||||
MepKeyId key = new MepKeyId(mdName, maName, mepId);
|
||||
|
||||
//Will throw IllegalArgumentException if ma does not exist
|
||||
cfmMdService.getMaintenanceAssociation(mdName, maName);
|
||||
|
||||
for (Mep mep : mepCollection) {
|
||||
if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
|
||||
&& mep.mepId().equals(mepId)) {
|
||||
Device mepDevice = deviceService.getDevice(mep.deviceId());
|
||||
if (mepDevice == null || !mepDevice.is(CfmMepProgrammable.class)) {
|
||||
throw new CfmConfigException("Unexpeced fault on device drier for "
|
||||
+ mep.deviceId());
|
||||
}
|
||||
boolean deleted = false;
|
||||
try {
|
||||
deleted = mepDevice.as(CfmMepProgrammable.class)
|
||||
.deleteMep(mdName, maName, mepId);
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("MEP could not be deleted on device - perhaps it "
|
||||
+ "does not exist. Continuing");
|
||||
mepCollection.remove(mep);
|
||||
return false;
|
||||
}
|
||||
if (deleted) {
|
||||
mepCollection.remove(mep);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
Optional<Mep> mepOptional = mepStore.getMep(key);
|
||||
if (mepOptional.isPresent()) {
|
||||
Mep mep = mepOptional.get();
|
||||
DeviceId mepDeviceId = mep.deviceId();
|
||||
if (deviceService.getDevice(mepDeviceId) == null) {
|
||||
throw new CfmConfigException("Device not found " + mepDeviceId);
|
||||
} else if (!deviceService.getDevice(mepDeviceId).is(CfmMepProgrammable.class)) {
|
||||
throw new CfmConfigException("Device " + mepDeviceId +
|
||||
" does not support CfmMepProgrammable behaviour.");
|
||||
}
|
||||
|
||||
log.debug("Retrieving MEP reults for Mep {} in MD {}, MA {} on Device {}",
|
||||
mep.mepId(), mdName, maName, mepDeviceId);
|
||||
|
||||
return deviceService.getDevice(mepDeviceId)
|
||||
.as(CfmMepProgrammable.class).getMep(mdName, maName, mepId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
|
||||
MepKeyId key = new MepKeyId(mdName, maName, mepId);
|
||||
|
||||
//Will throw IllegalArgumentException if ma does not exist
|
||||
cfmMdService.getMaintenanceAssociation(mdName, maName);
|
||||
|
||||
//Get the device ID from the MEP
|
||||
Optional<Mep> deletedMep = mepStore.getMep(key);
|
||||
if (!deletedMep.isPresent()) {
|
||||
log.warn("MEP {} not found when deleting Mep", key);
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceId mepDeviceId = deletedMep.get().deviceId();
|
||||
boolean deleted = mepStore.deleteMep(key);
|
||||
|
||||
Device mepDevice = deviceService.getDevice(mepDeviceId);
|
||||
if (mepDevice == null || !mepDevice.is(CfmMepProgrammable.class)) {
|
||||
throw new CfmConfigException("Unexpeced fault on device driver for "
|
||||
+ mepDeviceId);
|
||||
}
|
||||
try {
|
||||
deleted = mepDevice.as(CfmMepProgrammable.class)
|
||||
.deleteMep(mdName, maName, mepId, oldMd);
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("MEP could not be deleted on device - perhaps it "
|
||||
+ "does not exist. Continuing");
|
||||
}
|
||||
|
||||
//Iterate through all other devices and remove as a Remote Mep
|
||||
int mepsOnMdCount = 0;
|
||||
int mepsOnMaCount = 0;
|
||||
for (Mep mep : mepStore.getAllMeps()) {
|
||||
if (mep.deviceId().equals(mepDeviceId) && mdName.equals(mep.mdId())) {
|
||||
mepsOnMdCount++;
|
||||
if (maName.equals(mep.maId())) {
|
||||
mepsOnMaCount++;
|
||||
}
|
||||
}
|
||||
List<DeviceId> alreadyHandledDevices = new ArrayList<>();
|
||||
if (mep.deviceId().equals(mepDeviceId) || !mep.mdId().equals(mdName) ||
|
||||
!mep.maId().equals(maName) ||
|
||||
alreadyHandledDevices.contains(mep.deviceId())) {
|
||||
continue;
|
||||
}
|
||||
deviceService.getDevice(mep.deviceId())
|
||||
.as(CfmMepProgrammable.class)
|
||||
.deleteMaRemoteMepOnDevice(mdName, maName, mepId);
|
||||
alreadyHandledDevices.add(mep.deviceId());
|
||||
log.info("Deleted RMep entry on {} on device {}",
|
||||
mdName.mdName() + "/" + maName.maName(), mep.deviceId());
|
||||
}
|
||||
return false;
|
||||
|
||||
//Also if this is the last MEP in this MA then delete this MA from device
|
||||
//If this is the last MA in this MD on device, then delete the MD from the device
|
||||
if (mepsOnMdCount == 0) {
|
||||
boolean deletedMd = deviceService.getDevice(mepDeviceId)
|
||||
.as(CfmMepProgrammable.class).deleteMdOnDevice(mdName, oldMd);
|
||||
log.info("Deleted MD {} from Device {}", mdName.mdName(), mepDeviceId);
|
||||
} else if (mepsOnMaCount == 0) {
|
||||
boolean deletedMa = deviceService.getDevice(mepDeviceId)
|
||||
.as(CfmMepProgrammable.class).deleteMaOnDevice(mdName, maName, oldMd);
|
||||
log.info("Deleted MA {} from Device {}",
|
||||
mdName.mdName() + "/" + maName.maName(), mepDeviceId);
|
||||
}
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createMep(MdId mdName, MaIdShort maName, Mep newMep) throws CfmConfigException {
|
||||
MepKeyId key = new MepKeyId(mdName, maName, newMep.mepId());
|
||||
log.debug("Creating MEP " + newMep.mepId() + " on MD {}, MA {} on Device {}",
|
||||
mdName, maName, newMep.deviceId().toString());
|
||||
for (Mep mep : mepCollection) {
|
||||
if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
|
||||
&& mep.mepId().equals(newMep.mepId())) {
|
||||
return false;
|
||||
}
|
||||
if (mepStore.getMep(key).isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Will throw IllegalArgumentException if ma does not exist
|
||||
@ -225,7 +306,24 @@ public class CfmMepManager
|
||||
deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class).createMep(mdName, maName, newMep);
|
||||
log.debug("MEP created on {}", mepDeviceId);
|
||||
if (deviceResult) {
|
||||
return mepCollection.add(newMep);
|
||||
boolean alreadyExisted = mepStore.createUpdateMep(key, newMep);
|
||||
|
||||
//Add to other Remote Mep List on other devices
|
||||
for (Mep mep:mepStore.getMepsByMdMa(mdName, maName)) {
|
||||
List<DeviceId> alreadyHandledDevices = new ArrayList<>();
|
||||
if (mep.deviceId().equals(mepDeviceId) ||
|
||||
alreadyHandledDevices.contains(mep.deviceId())) {
|
||||
continue;
|
||||
}
|
||||
boolean created = deviceService.getDevice(mep.deviceId())
|
||||
.as(CfmMepProgrammable.class)
|
||||
.createMaRemoteMepOnDevice(mdName, maName, newMep.mepId());
|
||||
alreadyHandledDevices.add(mep.deviceId());
|
||||
log.info("Created RMep entry on {} on device {}",
|
||||
mdName.mdName() + "/" + maName.maName(), mep.deviceId());
|
||||
}
|
||||
|
||||
return !alreadyExisted;
|
||||
} else {
|
||||
return deviceResult;
|
||||
}
|
||||
@ -233,60 +331,253 @@ public class CfmMepManager
|
||||
|
||||
@Override
|
||||
public void transmitLoopback(MdId mdName, MaIdShort maName,
|
||||
MepId mepId, MepLbCreate lbCreate) throws CfmConfigException {
|
||||
for (Mep mep : mepCollection) {
|
||||
if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
|
||||
&& mep.mepId().equals(mepId)) {
|
||||
log.debug("Transmitting Loopback on MEP {}/{}/{} on Device {}",
|
||||
mdName, maName, mepId, mep.deviceId());
|
||||
deviceService.getDevice(mep.deviceId())
|
||||
.as(CfmMepProgrammable.class)
|
||||
.transmitLoopback(mdName, maName, mepId, lbCreate);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new CfmConfigException("Mep " + mdName + "/" + maName + "/"
|
||||
+ mepId + " not found when calling Transmit Loopback");
|
||||
MepId mepId, MepLbCreate lbCreate) throws CfmConfigException {
|
||||
MepKeyId key = new MepKeyId(mdName, maName, mepId);
|
||||
Mep mep = mepStore.getMep(key)
|
||||
.orElseThrow(() -> new CfmConfigException("Mep " + mdName + "/" + maName + "/"
|
||||
+ mepId + " not found when calling Transmit Loopback"));
|
||||
|
||||
log.debug("Transmitting Loopback on MEP {} on Device {}",
|
||||
key, mep.deviceId());
|
||||
deviceService.getDevice(mep.deviceId())
|
||||
.as(CfmMepProgrammable.class)
|
||||
.transmitLoopback(mdName, maName, mepId, lbCreate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
|
||||
throws CfmConfigException {
|
||||
for (Mep mep : mepCollection) {
|
||||
if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
|
||||
&& mep.mepId().equals(mepId)) {
|
||||
log.debug("Aborting Loopback on MEP {}/{}/{} on Device {}",
|
||||
mdName, maName, mepId, mep.deviceId());
|
||||
deviceService.getDevice(mep.deviceId())
|
||||
.as(CfmMepProgrammable.class)
|
||||
.abortLoopback(mdName, maName, mepId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new CfmConfigException("Mep " + mdName + "/" + maName + "/"
|
||||
+ mepId + " not found when calling Transmit Loopback");
|
||||
|
||||
MepKeyId key = new MepKeyId(mdName, maName, mepId);
|
||||
Mep mep = mepStore.getMep(key)
|
||||
.orElseThrow(() -> new CfmConfigException("Mep " + mdName + "/" + maName + "/"
|
||||
+ mepId + " not found when calling Aborting Loopback"));
|
||||
|
||||
log.debug("Aborting Loopback on MEP {} on Device {}",
|
||||
key, mep.deviceId());
|
||||
deviceService.getDevice(mep.deviceId())
|
||||
.as(CfmMepProgrammable.class)
|
||||
.abortLoopback(mdName, maName, mepId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
MepLtCreate ltCreate) {
|
||||
MepLtCreate ltCreate) {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
private class InternalDeviceListener implements DeviceListener {
|
||||
private class InternalMdListener implements MdListener {
|
||||
@Override
|
||||
public void event(DeviceEvent event) {
|
||||
public boolean isRelevant(MdEvent event) {
|
||||
return event.type().equals(MdEvent.Type.MD_REMOVED) ||
|
||||
event.type().equals(MdEvent.Type.MA_REMOVED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(MdEvent event) {
|
||||
MdId mdName = event.subject();
|
||||
switch (event.type()) {
|
||||
case DEVICE_REMOVED:
|
||||
case DEVICE_AVAILABILITY_CHANGED:
|
||||
DeviceId deviceId = event.subject().id();
|
||||
if (!deviceService.isAvailable(deviceId)) {
|
||||
log.warn("Device {} has been removed or changed", deviceId);
|
||||
}
|
||||
case MA_REMOVED:
|
||||
case MD_REMOVED:
|
||||
log.trace("Event {} receieved from MD Service for {}", event.type(), mdName);
|
||||
scheduleEventHandlerIfNotScheduled(event);
|
||||
break;
|
||||
default:
|
||||
log.warn("Unhandled Event {} received from MD Service", event.type());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalDeviceListener implements DeviceListener {
|
||||
@Override
|
||||
public boolean isRelevant(DeviceEvent event) {
|
||||
return event.type().equals(DeviceEvent.Type.DEVICE_REMOVED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(DeviceEvent event) {
|
||||
DeviceId deviceId = event.subject().id();
|
||||
switch (event.type()) {
|
||||
case DEVICE_ADDED:
|
||||
case PORT_UPDATED:
|
||||
case PORT_ADDED:
|
||||
case DEVICE_UPDATED:
|
||||
case DEVICE_REMOVED:
|
||||
case DEVICE_AVAILABILITY_CHANGED:
|
||||
log.trace("Event {} received from Device Service", event.type());
|
||||
scheduleEventHandlerIfNotScheduled(event);
|
||||
break;
|
||||
default:
|
||||
log.warn("Unhandled Event {} received from Device Service", event.type());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void scheduleEventHandlerIfNotScheduled(Event event) {
|
||||
synchronized (THREAD_SCHED_LOCK) {
|
||||
eventQueue.add(event);
|
||||
numOfEventsQueued++;
|
||||
|
||||
if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
|
||||
//No pending scheduled event handling threads. So start a new one.
|
||||
eventHandlerFuture = executorService
|
||||
.schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
|
||||
numOfHandlerScheduled++;
|
||||
}
|
||||
log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
|
||||
numOfEventsQueued,
|
||||
numOfHandlerScheduled);
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalEventHandler implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
Event event;
|
||||
synchronized (THREAD_SCHED_LOCK) {
|
||||
if (!eventQueue.isEmpty()) {
|
||||
event = eventQueue.poll();
|
||||
numOfEventsExecuted++;
|
||||
} else {
|
||||
numOfHandlerExecution++;
|
||||
log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
|
||||
numOfHandlerExecution, numOfEventsExecuted);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (event.type() == DeviceEvent.Type.DEVICE_REMOVED) {
|
||||
DeviceId deviceId = ((Device) event.subject()).id();
|
||||
log.info("Processing device removal event for unavailable device {}",
|
||||
deviceId);
|
||||
processDeviceRemoved((Device) event.subject());
|
||||
} else if (event.type() == MdEvent.Type.MD_REMOVED) {
|
||||
MdId mdName = (MdId) event.subject();
|
||||
log.info("Processing MD removal event for MD {}",
|
||||
mdName);
|
||||
processMdRemoved(mdName, ((MdEvent) event).md().get());
|
||||
} else if (event.type() == MdEvent.Type.MA_REMOVED) {
|
||||
MdId mdName = (MdId) event.subject();
|
||||
MaIdShort maName = ((MdEvent) event).maId().get();
|
||||
log.info("Processing MA removal event for MA {}",
|
||||
mdName.mdName() + "/" + maName.maName());
|
||||
processMaRemoved(mdName, maName, ((MdEvent) event).md().get());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("CfmMepService event handler "
|
||||
+ "thread thrown an exception: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes a MEP from the internal list of Meps, and updates remote meps list on other Meps.
|
||||
* Note: This does not call the device's CfmMepProgrammable, because there
|
||||
* would be no point as the device has already been removed from ONOS.
|
||||
* The configuration for this MEP may still be present on the actual device, and
|
||||
* any future config would have to be careful to wipe the Mep from the device
|
||||
* before applying a Mep again
|
||||
* @param removedDevice The device that has been removed
|
||||
*/
|
||||
protected void processDeviceRemoved(Device removedDevice) {
|
||||
log.warn("Remove Mep(s) associated with Device: " + removedDevice.id());
|
||||
Collection<Mep> mepListForDevice = mepStore.getMepsByDeviceId(removedDevice.id());
|
||||
|
||||
|
||||
for (Mep mep:mepStore.getAllMeps()) {
|
||||
for (Mep mepForDevice:mepListForDevice) {
|
||||
if (mep.mdId().equals(mepForDevice.mdId()) && mep.maId().equals(mepForDevice.maId())) {
|
||||
Device mepDevice = deviceService.getDevice(mep.deviceId());
|
||||
log.info("Removing Remote Mep {} from MA{} on device {}",
|
||||
mepForDevice.mepId(),
|
||||
mep.mdId().mdName() + "/" + mep.maId().maName(),
|
||||
mepDevice.id());
|
||||
try {
|
||||
mepDevice.as(CfmMepProgrammable.class)
|
||||
.deleteMaRemoteMepOnDevice(mep.mdId(), mep.maId(), mepForDevice.mepId());
|
||||
} catch (CfmConfigException e) {
|
||||
log.error("Error when removing Remote Mep {} from MA {}. Continuing.",
|
||||
mep.mdId().mdName() + "/" + mep.maId().maName(),
|
||||
mepForDevice.mepId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator<Mep> iter = mepListForDevice.iterator(); iter.hasNext();) {
|
||||
mepStore.deleteMep(new MepKeyId(iter.next()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void processMaRemoved(MdId mdId, MaIdShort maId, MaintenanceDomain oldMd) {
|
||||
Set<DeviceId> deviceIdsRemoved = new HashSet<>();
|
||||
|
||||
for (Iterator<Mep> iter = mepStore.getMepsByMdMa(mdId, maId).iterator(); iter.hasNext();) {
|
||||
Mep mepForMdMa = iter.next();
|
||||
DeviceId mepDeviceId = mepForMdMa.deviceId();
|
||||
try {
|
||||
deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class)
|
||||
.deleteMep(mdId, maId, mepForMdMa.mepId(), Optional.of(oldMd));
|
||||
deviceIdsRemoved.add(mepDeviceId);
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("Could not delete MEP {} from Device {}", mepForMdMa.mepId(), mepDeviceId, e);
|
||||
}
|
||||
iter.remove();
|
||||
|
||||
log.info("Removed MEP {} from Device {} because MA {} was deleted",
|
||||
mepForMdMa.mepId(), mepDeviceId, mdId.mdName() + "/" + maId.maName());
|
||||
}
|
||||
|
||||
deviceIdsRemoved.forEach(deviceId -> {
|
||||
try {
|
||||
deviceService.getDevice(deviceId).as(CfmMepProgrammable.class)
|
||||
.deleteMaOnDevice(mdId, maId, Optional.of(oldMd));
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("Could not delete MA {} from Device {}",
|
||||
mdId.mdName() + "/" + maId.maName(), deviceId, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void processMdRemoved(MdId mdId, MaintenanceDomain oldMd) {
|
||||
Set<DeviceId> deviceIdsRemoved = new HashSet<>();
|
||||
for (Iterator<Mep> iter = mepStore.getMepsByMd(mdId).iterator(); iter.hasNext();) {
|
||||
Mep mep = iter.next();
|
||||
DeviceId mepDeviceId = mep.deviceId();
|
||||
try {
|
||||
deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class)
|
||||
.deleteMep(mdId, mep.maId(), mep.mepId(), Optional.of(oldMd));
|
||||
deviceIdsRemoved.add(mepDeviceId);
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("Could not delete MEP {} from Device {}", mep.mepId(), mepDeviceId, e);
|
||||
}
|
||||
iter.remove();
|
||||
log.info("Removed MEP {} from Device {} because MD {} was deleted",
|
||||
mep.mepId(), mepDeviceId, mdId.mdName());
|
||||
}
|
||||
|
||||
deviceIdsRemoved.forEach(deviceId -> {
|
||||
try {
|
||||
deviceService.getDevice(deviceId).as(CfmMepProgrammable.class)
|
||||
.deleteMdOnDevice(mdId, Optional.of(oldMd));
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("Could not delete MD {} from Device {}",
|
||||
mdId.mdName(), deviceId, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class InternalStoreDelegate implements MepStoreDelegate {
|
||||
@Override
|
||||
public void notify(CfmMepEvent event) {
|
||||
log.debug("New Mep event: {}", event);
|
||||
eventDispatcher.post(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import com.google.common.net.InternetDomainName;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.felix.scr.annotations.Activate;
|
||||
import org.apache.felix.scr.annotations.Component;
|
||||
import org.apache.felix.scr.annotations.Deactivate;
|
||||
import org.apache.felix.scr.annotations.Reference;
|
||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||
import org.apache.felix.scr.annotations.Service;
|
||||
@ -42,6 +43,7 @@ import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MdEvent;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStoreDelegate;
|
||||
@ -58,6 +60,8 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Maintenance Domain Store implementation backed by consistent map.
|
||||
@ -75,7 +79,7 @@ public class DistributedMdStore extends AbstractStore<MdEvent, MdStoreDelegate>
|
||||
private ConsistentMap<MdId, MaintenanceDomain> maintenanceDomainConsistentMap;
|
||||
private Map<MdId, MaintenanceDomain> maintenanceDomainMap;
|
||||
|
||||
private final InternalMdListener listener = new InternalMdListener();
|
||||
private MapEventListener<MdId, MaintenanceDomain> mapListener = null;
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
@ -112,8 +116,17 @@ public class DistributedMdStore extends AbstractStore<MdEvent, MdStoreDelegate>
|
||||
.cfm.Component.TagType.class)
|
||||
.build("md")))
|
||||
.build();
|
||||
mapListener = new InternalMdListener();
|
||||
maintenanceDomainConsistentMap.addListener(mapListener);
|
||||
|
||||
maintenanceDomainMap = maintenanceDomainConsistentMap.asJavaMap();
|
||||
log.info("MDStore started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
maintenanceDomainConsistentMap.removeListener(mapListener);
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -141,19 +154,65 @@ public class DistributedMdStore extends AbstractStore<MdEvent, MdStoreDelegate>
|
||||
@Override
|
||||
public void event(MapEvent<MdId, MaintenanceDomain> mapEvent) {
|
||||
final MdEvent.Type type;
|
||||
MaIdShort maId = null;
|
||||
switch (mapEvent.type()) {
|
||||
case INSERT:
|
||||
type = MdEvent.Type.MD_ADDED;
|
||||
break;
|
||||
case UPDATE:
|
||||
type = MdEvent.Type.MD_UPDATED;
|
||||
// Examine the diff to see if it was a removal or addition of an MA caused it
|
||||
if (mapEvent.oldValue().value().maintenanceAssociationList().size() >
|
||||
mapEvent.newValue().value().maintenanceAssociationList().size()) {
|
||||
Set<MaIdShort> newMaIds = mapEvent.newValue().value().maintenanceAssociationList()
|
||||
.stream()
|
||||
.map(MaintenanceAssociation::maId)
|
||||
.collect(Collectors.toSet());
|
||||
Optional<MaintenanceAssociation> removedMa =
|
||||
mapEvent.oldValue().value().maintenanceAssociationList()
|
||||
.stream()
|
||||
.filter(maOld -> !newMaIds.contains(maOld.maId())).findFirst();
|
||||
if (removedMa.isPresent()) {
|
||||
maId = removedMa.get().maId();
|
||||
}
|
||||
type = MdEvent.Type.MA_REMOVED;
|
||||
} else if (mapEvent.oldValue().value().maintenanceAssociationList().size() <
|
||||
mapEvent.newValue().value().maintenanceAssociationList().size()) {
|
||||
Set<MaIdShort> oldMaIds = mapEvent.oldValue().value().maintenanceAssociationList()
|
||||
.stream()
|
||||
.map(MaintenanceAssociation::maId)
|
||||
.collect(Collectors.toSet());
|
||||
Optional<MaintenanceAssociation> addedMa =
|
||||
mapEvent.newValue().value().maintenanceAssociationList()
|
||||
.stream()
|
||||
.filter(maNew -> !oldMaIds.contains(maNew.maId())).findFirst();
|
||||
if (addedMa.isPresent()) {
|
||||
maId = addedMa.get().maId();
|
||||
}
|
||||
type = MdEvent.Type.MA_ADDED;
|
||||
} else {
|
||||
type = MdEvent.Type.MD_UPDATED;
|
||||
}
|
||||
break;
|
||||
case REMOVE:
|
||||
default:
|
||||
type = MdEvent.Type.MD_REMOVED;
|
||||
break;
|
||||
}
|
||||
notifyDelegate(new MdEvent(type, mapEvent.key()));
|
||||
if (mapEvent.oldValue() != null && mapEvent.oldValue().value() != null) {
|
||||
MaintenanceDomain oldMd = mapEvent.oldValue().value();
|
||||
try {
|
||||
if (maId != null) {
|
||||
notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd, maId));
|
||||
} else {
|
||||
notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd));
|
||||
}
|
||||
} catch (CfmConfigException e) {
|
||||
log.warn("Unable to copy MD {}", oldMd);
|
||||
notifyDelegate(new MdEvent(type, mapEvent.key()));
|
||||
}
|
||||
} else {
|
||||
notifyDelegate(new MdEvent(type, mapEvent.key()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.incubator.net.l2monitoring.cfm.impl;
|
||||
|
||||
import org.apache.felix.scr.annotations.Activate;
|
||||
import org.apache.felix.scr.annotations.Component;
|
||||
import org.apache.felix.scr.annotations.Deactivate;
|
||||
import org.apache.felix.scr.annotations.Reference;
|
||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||
import org.apache.felix.scr.annotations.Service;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.VlanId;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepEvent;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStoreDelegate;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.NetworkResource;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.store.AbstractStore;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.ConsistentMap;
|
||||
import org.onosproject.store.service.MapEvent;
|
||||
import org.onosproject.store.service.MapEventListener;
|
||||
import org.onosproject.store.service.Serializer;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* MEP Store implementation backed by consistent map.
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
@Service
|
||||
public class DistributedMepStore extends AbstractStore<CfmMepEvent, MepStoreDelegate>
|
||||
implements MepStore {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected StorageService storageService;
|
||||
|
||||
private ConsistentMap<MepKeyId, Mep> mepConsistentMap;
|
||||
private Map<MepKeyId, Mep> mepMap;
|
||||
|
||||
private MapEventListener<MepKeyId, Mep> mapListener = null;
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
mepConsistentMap = storageService
|
||||
.<MepKeyId, Mep>consistentMapBuilder()
|
||||
.withName("onos-cfm-mep-map")
|
||||
.withSerializer(Serializer.using(new KryoNamespace.Builder()
|
||||
.register(KryoNamespaces.API)
|
||||
.register(DefaultMep.class)
|
||||
.register(MepId.class)
|
||||
.register(MepKeyId.class)
|
||||
.register(NetworkResource.class)
|
||||
.register(DeviceId.class)
|
||||
.register(PortNumber.class)
|
||||
.register(Mep.MepDirection.class)
|
||||
.register(VlanId.class)
|
||||
.register(Mep.Priority.class)
|
||||
.register(Mep.FngAddress.class)
|
||||
.register(Mep.FngAddressType.class)
|
||||
.register(IpAddress.class)
|
||||
.register(Mep.LowestFaultDefect.class)
|
||||
.register(Duration.class)
|
||||
.register(MdIdCharStr.class)
|
||||
.register(MdIdDomainName.class)
|
||||
.register(MdIdMacUint.class)
|
||||
.register(MdIdNone.class)
|
||||
.register(MaIdCharStr.class)
|
||||
.register(MaIdShort.class)
|
||||
.register(MaId2Octet.class)
|
||||
.register(MaIdIccY1731.class)
|
||||
.register(MaIdPrimaryVid.class)
|
||||
.register(MaIdRfc2685VpnId.class)
|
||||
.build("mep")))
|
||||
.build();
|
||||
mapListener = new InternalMepListener();
|
||||
mepConsistentMap.addListener(mapListener);
|
||||
|
||||
mepMap = mepConsistentMap.asJavaMap();
|
||||
log.info("MepStore started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
mepConsistentMap.removeListener(mapListener);
|
||||
log.info("MepStore stopped");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Mep> getAllMeps() {
|
||||
return mepMap.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Mep> getMepsByMd(MdId mdName) {
|
||||
return mepMap.values().stream()
|
||||
.filter(mep -> mep.mdId().equals(mdName))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Mep> getMepsByMdMa(MdId mdName, MaIdShort maName) {
|
||||
return mepMap.values().stream()
|
||||
.filter(mep -> mep.mdId().equals(mdName) && mep.maId().equals(maName))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Mep> getMepsByDeviceId(DeviceId deviceId) {
|
||||
return mepMap.values().stream()
|
||||
.filter(mep -> mep.deviceId().equals(deviceId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Mep> getMep(MepKeyId mepKeyId) {
|
||||
return mepMap.values().stream()
|
||||
.filter(mep -> mep.mdId().equals(mepKeyId.mdId()) &&
|
||||
mep.maId().equals(mepKeyId.maId()) &&
|
||||
mep.mepId().equals(mepKeyId.mepId()))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMep(MepKeyId mepKeyId) {
|
||||
return mepMap.remove(mepKeyId) == null ? false : true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createUpdateMep(MepKeyId mepKeyId, Mep mep) {
|
||||
return mepMap.put(mepKeyId, mep) == null ? false : true;
|
||||
}
|
||||
|
||||
private class InternalMepListener implements MapEventListener<MepKeyId, Mep> {
|
||||
|
||||
@Override
|
||||
public void event(MapEvent<MepKeyId, Mep> mapEvent) {
|
||||
final CfmMepEvent.Type type;
|
||||
|
||||
switch (mapEvent.type()) {
|
||||
case INSERT:
|
||||
type = CfmMepEvent.Type.MEP_ADDED;
|
||||
break;
|
||||
case UPDATE:
|
||||
type = CfmMepEvent.Type.MEP_UPDATED;
|
||||
break;
|
||||
default:
|
||||
case REMOVE:
|
||||
type = CfmMepEvent.Type.MEP_REMOVED;
|
||||
}
|
||||
notifyDelegate(new CfmMepEvent(type, mapEvent.key()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,10 +36,13 @@ import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.onosproject.mastership.MastershipServiceAdapter;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.store.service.TestStorageService;
|
||||
@ -50,6 +53,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
@ -61,6 +65,11 @@ import static org.onosproject.net.NetTestTools.injectEventDispatcher;
|
||||
public class CfmMdManagerTest {
|
||||
private static final NodeId NID_LOCAL = new NodeId("local");
|
||||
private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");
|
||||
private static final MaIdShort MA_ID_1_1 = MaIdCharStr.asMaId("test-ma-1-1");
|
||||
private static final MaIdShort MA_ID_1_2 = MaIdCharStr.asMaId("test-ma-1-2");
|
||||
private static final MdId MD_ID_1 = MdIdCharStr.asMdId("test-md-1");
|
||||
|
||||
private final CfmMepService mepService = createMock(CfmMepService.class);
|
||||
|
||||
private DistributedMdStore mdStore;
|
||||
private CfmMdService service;
|
||||
@ -71,7 +80,7 @@ public class CfmMdManagerTest {
|
||||
mdStore = new DistributedMdStore();
|
||||
|
||||
MaintenanceAssociation maTest11 = DefaultMaintenanceAssociation
|
||||
.builder(MaIdCharStr.asMaId("test-ma-1-1"), 9)
|
||||
.builder(MA_ID_1_1, MD_ID_1.getNameLength())
|
||||
.ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_10MIN)
|
||||
.maNumericId((short) 1)
|
||||
.addToRemoteMepIdList(MepId.valueOf((short) 101))
|
||||
@ -83,7 +92,7 @@ public class CfmMdManagerTest {
|
||||
.build();
|
||||
|
||||
MaintenanceAssociation maTest12 = DefaultMaintenanceAssociation
|
||||
.builder(MaIdCharStr.asMaId("test-ma-1-2"), 9)
|
||||
.builder(MA_ID_1_2, MD_ID_1.getNameLength())
|
||||
.ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_10MIN)
|
||||
.maNumericId((short) 2)
|
||||
.addToRemoteMepIdList(MepId.valueOf((short) 201))
|
||||
@ -95,7 +104,7 @@ public class CfmMdManagerTest {
|
||||
.build();
|
||||
|
||||
MaintenanceDomain mdTest1 = DefaultMaintenanceDomain
|
||||
.builder(MdIdCharStr.asMdId("test-md-1"))
|
||||
.builder(MD_ID_1)
|
||||
.mdLevel(MaintenanceDomain.MdLevel.LEVEL1)
|
||||
.mdNumericId((short) 1)
|
||||
.addToMaList(maTest11)
|
||||
@ -105,6 +114,7 @@ public class CfmMdManagerTest {
|
||||
TestUtils.setField(mdStore, "storageService", new TestStorageService());
|
||||
TestUtils.setField(mdStore, "clusterService", new CfmMdManagerTest.TestClusterService());
|
||||
TestUtils.setField(mdStore, "mastershipService", new CfmMdManagerTest.TestMastershipService());
|
||||
|
||||
mdStore.activate();
|
||||
mdStore.createUpdateMaintenanceDomain(mdTest1);
|
||||
|
||||
@ -113,6 +123,7 @@ public class CfmMdManagerTest {
|
||||
service = manager;
|
||||
TestUtils.setField(manager, "storageService", new TestStorageService());
|
||||
TestUtils.setField(manager, "coreService", new TestCoreService());
|
||||
TestUtils.setField(manager, "mepService", mepService);
|
||||
injectEventDispatcher(manager, new TestEventDispatcher());
|
||||
|
||||
manager.appId = new CfmMdManagerTest.TestApplicationId(0, "CfmMdManagerTest");
|
||||
@ -339,7 +350,6 @@ public class CfmMdManagerTest {
|
||||
MdIdCharStr.asMdId("test-md-1")).size());
|
||||
}
|
||||
|
||||
|
||||
public class TestApplicationId extends DefaultApplicationId {
|
||||
public TestApplicationId(int id, String name) {
|
||||
super(id, name);
|
||||
|
||||
@ -37,10 +37,12 @@ import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
|
||||
import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable;
|
||||
import org.onosproject.incubator.net.l2monitoring.soam.impl.TestSoamDmProgrammable;
|
||||
import org.onosproject.net.AbstractProjectableModel;
|
||||
@ -57,21 +59,30 @@ import org.onosproject.net.driver.DefaultDriver;
|
||||
import org.onosproject.net.driver.Driver;
|
||||
import org.onosproject.net.driver.DriverService;
|
||||
import org.onosproject.net.provider.ProviderId;
|
||||
import org.onosproject.store.service.AsyncDocumentTree;
|
||||
import org.onosproject.store.service.DocumentTreeBuilder;
|
||||
import org.onosproject.store.service.Serializer;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.TestAsyncDocumentTree;
|
||||
import org.onosproject.store.service.TestStorageService;
|
||||
import org.onosproject.store.service.TestTopic;
|
||||
import org.onosproject.store.service.Topic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static junit.framework.TestCase.fail;
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.onosproject.net.NetTestTools.injectEventDispatcher;
|
||||
|
||||
/**
|
||||
@ -91,18 +102,32 @@ public class CfmMepManagerTest {
|
||||
|
||||
private CfmMepService mepService;
|
||||
private CfmMepManager mepManager;
|
||||
private MepStore mepStore;
|
||||
private StorageService storageService;
|
||||
|
||||
protected static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1");
|
||||
protected static final MdId MDNAME2 = MdIdCharStr.asMdId("md-2");
|
||||
protected static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1");
|
||||
protected static final MaIdShort MANAME2 = MaIdCharStr.asMaId("ma-2-2");
|
||||
|
||||
private MaintenanceAssociation ma1;
|
||||
private MaintenanceAssociation ma2;
|
||||
protected static final MepId MEPID1 = MepId.valueOf((short) 10);
|
||||
protected static final MepId MEPID11 = MepId.valueOf((short) 11);
|
||||
protected static final MepId MEPID12 = MepId.valueOf((short) 12);
|
||||
protected static final MepId MEPID2 = MepId.valueOf((short) 20);
|
||||
protected static final MepId MEPID21 = MepId.valueOf((short) 21);
|
||||
protected static final MepId MEPID22 = MepId.valueOf((short) 22);
|
||||
|
||||
protected static final DeviceId DEVICE_ID1 = DeviceId.deviceId("netconf:1.2.3.4:830");
|
||||
protected static final DeviceId DEVICE_ID2 = DeviceId.deviceId("netconf:2.2.3.4:830");
|
||||
|
||||
private Mep mep1;
|
||||
private Mep mep11;
|
||||
private Mep mep12;
|
||||
private Mep mep2;
|
||||
private Mep mep21;
|
||||
private Mep mep22;
|
||||
|
||||
private Device device1;
|
||||
private Device device2;
|
||||
@ -112,12 +137,19 @@ public class CfmMepManagerTest {
|
||||
@Before
|
||||
public void setup() throws CfmConfigException {
|
||||
mepManager = new CfmMepManager();
|
||||
mepStore = new DistributedMepStore();
|
||||
storageService = new MockStorageService();
|
||||
|
||||
ma1 = DefaultMaintenanceAssociation.builder(MANAME1, MDNAME1.getNameLength()).build();
|
||||
ma2 = DefaultMaintenanceAssociation.builder(MANAME2, MDNAME2.getNameLength()).build();
|
||||
|
||||
TestUtils.setField(mepStore, "storageService", storageService);
|
||||
((DistributedMepStore) mepStore).activate();
|
||||
|
||||
TestUtils.setField(mepManager, "coreService", new TestCoreService());
|
||||
TestUtils.setField(mepManager, "deviceService", deviceService);
|
||||
TestUtils.setField(mepManager, "cfmMdService", mdService);
|
||||
TestUtils.setField(mepManager, "mepStore", mepStore);
|
||||
injectEventDispatcher(mepManager, new TestEventDispatcher());
|
||||
|
||||
mepService = mepManager;
|
||||
@ -125,12 +157,27 @@ public class CfmMepManagerTest {
|
||||
|
||||
mep1 = DefaultMep.builder(MEPID1, DEVICE_ID1, PortNumber.P0,
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
|
||||
mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID1), mep1);
|
||||
|
||||
mep11 = DefaultMep.builder(MEPID11, DEVICE_ID1, PortNumber.P0,
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
|
||||
mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID11), mep11);
|
||||
|
||||
mep12 = DefaultMep.builder(MEPID12, DEVICE_ID1, PortNumber.P0,
|
||||
Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build();
|
||||
mepStore.createUpdateMep(new MepKeyId(MDNAME2, MANAME2, MEPID12), mep12);
|
||||
|
||||
mep2 = DefaultMep.builder(MEPID2, DEVICE_ID2, PortNumber.portNumber(2),
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
|
||||
List<Mep> mepList = new ArrayList<>();
|
||||
mepList.add(mep1);
|
||||
mepList.add(mep2);
|
||||
TestUtils.setField(mepManager, "mepCollection", mepList);
|
||||
mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID2), mep2);
|
||||
|
||||
mep21 = DefaultMep.builder(MEPID21, DEVICE_ID2, PortNumber.portNumber(2),
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
|
||||
mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID21), mep21);
|
||||
|
||||
mep22 = DefaultMep.builder(MEPID22, DEVICE_ID2, PortNumber.portNumber(2),
|
||||
Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build();
|
||||
mepStore.createUpdateMep(new MepKeyId(MDNAME2, MANAME2, MEPID22), mep22);
|
||||
|
||||
device1 = new DefaultDevice(
|
||||
ProviderId.NONE, DEVICE_ID1, Device.Type.SWITCH,
|
||||
@ -180,7 +227,7 @@ public class CfmMepManagerTest {
|
||||
|
||||
Collection<MepEntry> mepEntries = mepManager.getAllMeps(MDNAME1, MANAME1);
|
||||
|
||||
assertEquals(2, mepEntries.size());
|
||||
assertEquals(4, mepEntries.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -232,12 +279,13 @@ public class CfmMepManagerTest {
|
||||
replay(mdService);
|
||||
|
||||
expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes();
|
||||
expect(deviceService.getDevice(DEVICE_ID2)).andReturn(device2).anyTimes();
|
||||
replay(deviceService);
|
||||
|
||||
expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes();
|
||||
replay(driverService);
|
||||
|
||||
assertTrue(mepManager.deleteMep(MDNAME1, MANAME1, MEPID1));
|
||||
assertTrue(mepManager.deleteMep(MDNAME1, MANAME1, MEPID1, Optional.empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -248,6 +296,7 @@ public class CfmMepManagerTest {
|
||||
replay(mdService);
|
||||
|
||||
expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes();
|
||||
expect(deviceService.getDevice(DEVICE_ID2)).andReturn(device2).anyTimes();
|
||||
replay(deviceService);
|
||||
|
||||
expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes();
|
||||
@ -257,6 +306,7 @@ public class CfmMepManagerTest {
|
||||
Mep mep3 = DefaultMep.builder(mepId3, DEVICE_ID1, PortNumber.portNumber(1),
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
|
||||
|
||||
//Expecting false - since it was not found
|
||||
assertTrue(mepManager.createMep(MDNAME1, MANAME1, mep3));
|
||||
}
|
||||
|
||||
@ -364,6 +414,56 @@ public class CfmMepManagerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceRemoved() throws CfmConfigException {
|
||||
expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1))
|
||||
.andReturn(Optional.ofNullable(ma1))
|
||||
.anyTimes();
|
||||
expect(mdService.getMaintenanceAssociation(MDNAME2, MANAME2))
|
||||
.andReturn(Optional.ofNullable(ma2))
|
||||
.anyTimes();
|
||||
replay(mdService);
|
||||
|
||||
expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes();
|
||||
expect(deviceService.getDevice(DEVICE_ID2)).andReturn(device2).anyTimes();
|
||||
replay(deviceService);
|
||||
|
||||
expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes();
|
||||
replay(driverService);
|
||||
|
||||
// This is arranged like
|
||||
// device1 device2
|
||||
// / \ / \
|
||||
// md-1 md-2 md-1 md-2
|
||||
// | | | |
|
||||
// ma-1-1 ma-2-2 ma-1-1 ma-2-2
|
||||
// / \ | / \ \
|
||||
// mep1 mep11 mep12 mep2 mep21 mep22
|
||||
assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID1));
|
||||
assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID11));
|
||||
assertNotNull(mepService.getMep(MDNAME2, MANAME2, MEPID12));
|
||||
assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID2));
|
||||
assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID21));
|
||||
assertNotNull(mepService.getMep(MDNAME2, MANAME2, MEPID22));
|
||||
|
||||
//By deleting Device2 we expect Mep2,21,22 to have been deleted but Mep1,11,12 to remain
|
||||
((CfmMepManager) mepService).processDeviceRemoved(device2);
|
||||
|
||||
assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID1));
|
||||
assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID11));
|
||||
assertNotNull(mepService.getMep(MDNAME2, MANAME2, MEPID12));
|
||||
//The device 2 related ones are gone
|
||||
assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID2));
|
||||
assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID21));
|
||||
assertNull(mepService.getMep(MDNAME2, MANAME2, MEPID22));
|
||||
|
||||
//Now delete device1
|
||||
((CfmMepManager) mepService).processDeviceRemoved(device1);
|
||||
assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID1));
|
||||
assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID11));
|
||||
assertNull(mepService.getMep(MDNAME2, MANAME2, MEPID12));
|
||||
}
|
||||
|
||||
private class TestCoreService extends CoreServiceAdapter {
|
||||
|
||||
@Override
|
||||
@ -378,4 +478,27 @@ public class CfmMepManagerTest {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static class MockStorageService extends TestStorageService {
|
||||
@Override
|
||||
public <V> DocumentTreeBuilder<V> documentTreeBuilder() {
|
||||
return new DocumentTreeBuilder<V>() {
|
||||
@Override
|
||||
public AsyncDocumentTree<V> buildDocumentTree() {
|
||||
return build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public AsyncDocumentTree<V> build() {
|
||||
return new TestAsyncDocumentTree<>(name());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Topic<T> getTopic(String name, Serializer serializer) {
|
||||
return new TestTopic<>(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ package org.onosproject.incubator.net.l2monitoring.cfm.impl;
|
||||
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
|
||||
import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
|
||||
@ -30,8 +31,8 @@ import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMepManagerTest.*;
|
||||
|
||||
@ -47,13 +48,16 @@ public class TestCfmMepProgrammable extends AbstractHandlerBehaviour implements
|
||||
|
||||
deviceMepList.add(DefaultMep.builder(MEPID1, DEVICE_ID1, PortNumber.P0,
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
|
||||
deviceMepList.add(DefaultMep.builder(MEPID11, DEVICE_ID1, PortNumber.P0,
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
|
||||
deviceMepList.add(DefaultMep.builder(MEPID12, DEVICE_ID1, PortNumber.P0,
|
||||
Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build());
|
||||
deviceMepList.add(DefaultMep.builder(MEPID2, DEVICE_ID2, PortNumber.portNumber(2),
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MepEntry> getAllMeps(MdId mdName, MaIdShort maName) throws CfmConfigException {
|
||||
return null;
|
||||
deviceMepList.add(DefaultMep.builder(MEPID21, DEVICE_ID2, PortNumber.portNumber(2),
|
||||
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
|
||||
deviceMepList.add(DefaultMep.builder(MEPID22, DEVICE_ID2, PortNumber.portNumber(2),
|
||||
Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -67,7 +71,8 @@ public class TestCfmMepProgrammable extends AbstractHandlerBehaviour implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
|
||||
public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId,
|
||||
Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -76,6 +81,37 @@ public class TestCfmMepProgrammable extends AbstractHandlerBehaviour implements
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMaOnDevice(MdId mdId, MaIdShort maId,
|
||||
Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createMdOnDevice(MdId mdId) throws CfmConfigException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId, MepLbCreate lbCreate)
|
||||
throws CfmConfigException {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user