diff options
Diffstat (limited to 'framework/src/onos/apps/sdnip')
9 files changed, 446 insertions, 89 deletions
diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java index eaabed33..2eb5d0f3 100644 --- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java @@ -15,24 +15,25 @@ */ package org.onosproject.sdnip; -import org.onosproject.core.ApplicationId; -import org.onosproject.net.intent.Intent; -import org.onosproject.net.intent.IntentService; -import org.onosproject.net.intent.IntentState; -import org.onosproject.net.intent.Key; -import org.onosproject.routing.IntentSynchronizationService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static org.onlab.util.Tools.groupedThreads; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; -import static java.util.concurrent.Executors.newSingleThreadExecutor; -import static org.onlab.util.Tools.groupedThreads; +import org.onosproject.core.ApplicationId; +import org.onosproject.net.intent.Intent; +import org.onosproject.net.intent.IntentService; +import org.onosproject.net.intent.IntentState; +import org.onosproject.net.intent.Key; +import org.onosproject.routing.IntentSynchronizationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Synchronizes intents between the in-memory intent store and the @@ -49,9 +50,9 @@ public class IntentSynchronizer implements IntentSynchronizationService { private final Map<Key, Intent> intents; // - // State to deal with SDN-IP Leader election and pushing Intents + // State to deal with the Leader election and pushing Intents // - private final ExecutorService bgpIntentsSynchronizerExecutor; + private final ExecutorService intentsSynchronizerExecutor; private volatile boolean isElectedLeader = false; private volatile boolean isActivatedLeader = false; @@ -61,9 +62,9 @@ public class IntentSynchronizer implements IntentSynchronizationService { * @param appId the Application ID * @param intentService the intent service */ - IntentSynchronizer(ApplicationId appId, IntentService intentService) { + public IntentSynchronizer(ApplicationId appId, IntentService intentService) { this(appId, intentService, - newSingleThreadExecutor(groupedThreads("onos/sdnip", "sync"))); + newSingleThreadExecutor(groupedThreads("onos/" + appId, "sync"))); } /** @@ -73,14 +74,14 @@ public class IntentSynchronizer implements IntentSynchronizationService { * @param intentService the intent service * @param executorService executor service for synchronization thread */ - IntentSynchronizer(ApplicationId appId, IntentService intentService, + public IntentSynchronizer(ApplicationId appId, IntentService intentService, ExecutorService executorService) { this.appId = appId; this.intentService = intentService; intents = new ConcurrentHashMap<>(); - bgpIntentsSynchronizerExecutor = executorService; + intentsSynchronizerExecutor = executorService; } /** @@ -96,56 +97,31 @@ public class IntentSynchronizer implements IntentSynchronizationService { public void stop() { synchronized (this) { // Stop the thread(s) - bgpIntentsSynchronizerExecutor.shutdownNow(); + intentsSynchronizerExecutor.shutdownNow(); + log.info("Intents Synchronizer Executor shutdown completed"); - // - // Withdraw all SDN-IP intents - // - if (!isElectedLeader) { - return; // Nothing to do: not the leader anymore - } + } + } - // - // NOTE: We don't withdraw the intents during shutdown, because - // it creates flux in the data plane during switchover. - // - - /* - // - // Build a batch operation to withdraw all intents from this - // application. - // - log.debug("SDN-IP Intent Synchronizer shutdown: " + - "withdrawing all intents..."); - IntentOperations.Builder builder = IntentOperations.builder(appId); - for (Intent intent : intentService.getIntents()) { - // Skip the intents from other applications - if (!intent.appId().equals(appId)) { - continue; - } + /** + * Withdraws all intents. + */ + public void removeIntents() { + if (!isElectedLeader) { + // only leader will withdraw intents + return; + } - // Skip the intents that are already withdrawn - IntentState intentState = - intentService.getIntentState(intent.id()); - if ((intentState == null) || - intentState.equals(IntentState.WITHDRAWING) || - intentState.equals(IntentState.WITHDRAWN)) { - continue; - } + log.debug("Intent Synchronizer shutdown: withdrawing all intents..."); - log.trace("SDN-IP Intent Synchronizer withdrawing intent: {}", - intent); - builder.addWithdrawOperation(intent.id()); - } - IntentOperations intentOperations = builder.build(); - intentService.execute(intentOperations); - leaderChanged(false); - - peerIntents.clear(); - routeIntents.clear(); - log.debug("SDN-IP Intent Synchronizer shutdown completed"); - */ + for (Entry<Key, Intent> entry : intents.entrySet()) { + intentService.withdraw(entry.getValue()); + log.debug("Intent Synchronizer withdrawing intent: {}", + entry.getValue()); } + + intents.clear(); + log.info("Tried to clean all intents"); } @Override @@ -153,7 +129,7 @@ public class IntentSynchronizer implements IntentSynchronizationService { synchronized (this) { intents.put(intent.key(), intent); if (isElectedLeader && isActivatedLeader) { - log.trace("SDN-IP Submitting intent: {}", intent); + log.trace("Submitting intent: {}", intent); intentService.submit(intent); } } @@ -164,19 +140,19 @@ public class IntentSynchronizer implements IntentSynchronizationService { synchronized (this) { intents.remove(intent.key(), intent); if (isElectedLeader && isActivatedLeader) { - log.trace("SDN-IP Withdrawing intent: {}", intent); + log.trace("Withdrawing intent: {}", intent); intentService.withdraw(intent); } } } /** - * Signals the synchronizer that the SDN-IP leadership has changed. + * Signals the synchronizer that the leadership has changed. * * @param isLeader true if this instance is now the leader, otherwise false */ public void leaderChanged(boolean isLeader) { - log.debug("SDN-IP Leader changed: {}", isLeader); + log.debug("Leader changed: {}", isLeader); if (!isLeader) { this.isElectedLeader = false; @@ -187,7 +163,7 @@ public class IntentSynchronizer implements IntentSynchronizationService { this.isElectedLeader = true; // Run the synchronization method off-thread - bgpIntentsSynchronizerExecutor.execute(this::synchronizeIntents); + intentsSynchronizerExecutor.execute(this::synchronizeIntents); } private void synchronizeIntents() { @@ -225,17 +201,17 @@ public class IntentSynchronizer implements IntentSynchronizationService { } } - log.debug("SDN-IP Intent Synchronizer: submitting {}, withdrawing {}", + log.debug("Intent Synchronizer: submitting {}, withdrawing {}", intentsToAdd.size(), intentsToRemove.size()); // Withdraw Intents for (Intent intent : intentsToRemove) { intentService.withdraw(intent); - log.trace("SDN-IP Intent Synchronizer: withdrawing intent: {}", + log.trace("Intent Synchronizer: withdrawing intent: {}", intent); } if (!isElectedLeader) { - log.debug("SDN-IP Intent Synchronizer: cannot withdraw intents: " + + log.debug("Intent Synchronizer: cannot withdraw intents: " + "not elected leader anymore"); isActivatedLeader = false; return; @@ -244,11 +220,11 @@ public class IntentSynchronizer implements IntentSynchronizationService { // Add Intents for (Intent intent : intentsToAdd) { intentService.submit(intent); - log.trace("SDN-IP Intent Synchronizer: submitting intent: {}", + log.trace("Intent Synchronizer: submitting intent: {}", intent); } if (!isElectedLeader) { - log.debug("SDN-IP Intent Synchronizer: cannot submit intents: " + + log.debug("Intent Synchronizer: cannot submit intents: " + "not elected leader anymore"); isActivatedLeader = false; return; @@ -259,7 +235,6 @@ public class IntentSynchronizer implements IntentSynchronizationService { } else { isActivatedLeader = false; } - log.debug("SDN-IP intent synchronization completed"); + log.debug("Intent synchronization completed"); } - } diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java index 8e2a3df3..863de12a 100644 --- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentUtils.java @@ -19,13 +19,12 @@ package org.onosproject.sdnip; import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.MultiPointToSinglePointIntent; import org.onosproject.net.intent.PointToPointIntent; +import org.onosproject.net.intent.SinglePointToMultiPointIntent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Objects; -import static com.google.common.base.Preconditions.checkArgument; - /** * Utilities for dealing with intents. */ @@ -49,15 +48,24 @@ public final class IntentUtils { * @return true if the two intents represent the same value, otherwise false */ public static boolean equals(Intent one, Intent two) { - checkArgument(one.getClass() == two.getClass(), - "Intents are not the same type"); + if (one.getClass() != two.getClass()) { + return false; + } if (!(Objects.equals(one.appId(), two.appId()) && Objects.equals(one.key(), two.key()))) { return false; } - if (one instanceof MultiPointToSinglePointIntent) { + if (one instanceof SinglePointToMultiPointIntent) { + SinglePointToMultiPointIntent intent1 = (SinglePointToMultiPointIntent) one; + SinglePointToMultiPointIntent intent2 = (SinglePointToMultiPointIntent) two; + + return Objects.equals(intent1.selector(), intent2.selector()) && + Objects.equals(intent1.treatment(), intent2.treatment()) && + Objects.equals(intent1.ingressPoint(), intent2.ingressPoint()) && + Objects.equals(intent1.egressPoints(), intent2.egressPoints()); + } else if (one instanceof MultiPointToSinglePointIntent) { MultiPointToSinglePointIntent intent1 = (MultiPointToSinglePointIntent) one; MultiPointToSinglePointIntent intent2 = (MultiPointToSinglePointIntent) two; diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java index a27baaf9..fb008aad 100644 --- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java @@ -340,15 +340,15 @@ public class PeerConnectivityManager { private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp, IpAddress dstIp, Short srcTcpPort, Short dstTcpPort) { - TrafficSelector.Builder builder = DefaultTrafficSelector.builder() - .matchEthType(Ethernet.TYPE_IPV4) - .matchIPProtocol(ipProto); + TrafficSelector.Builder builder = DefaultTrafficSelector.builder().matchIPProtocol(ipProto); if (dstIp.isIp4()) { - builder.matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH)) + builder.matchEthType(Ethernet.TYPE_IPV4) + .matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH)) .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH)); } else { - builder.matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH)) + builder.matchEthType(Ethernet.TYPE_IPV6) + .matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH)) .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH)); } diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java index 1b3eda9d..ace888d1 100644 --- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java @@ -15,12 +15,17 @@ */ package org.onosproject.sdnip; +import static org.slf4j.LoggerFactory.getLogger; + +import java.util.Objects; + 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.onosproject.app.ApplicationService; import org.onosproject.cluster.ClusterService; import org.onosproject.cluster.ControllerNode; import org.onosproject.cluster.LeadershipEvent; @@ -28,8 +33,8 @@ import org.onosproject.cluster.LeadershipEventListener; import org.onosproject.cluster.LeadershipService; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; -import org.onosproject.net.config.NetworkConfigService; import org.onosproject.incubator.net.intf.InterfaceService; +import org.onosproject.net.config.NetworkConfigService; import org.onosproject.net.host.HostService; import org.onosproject.net.intent.IntentService; import org.onosproject.routing.IntentSynchronizationService; @@ -38,10 +43,6 @@ import org.onosproject.routing.SdnIpService; import org.onosproject.routing.config.RoutingConfigurationService; import org.slf4j.Logger; -import java.util.Objects; - -import static org.slf4j.LoggerFactory.getLogger; - /** * Component for the SDN-IP peering application. */ @@ -59,6 +60,9 @@ public class SdnIp implements SdnIpService { protected IntentService intentService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ApplicationService applicationService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected HostService hostService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @@ -84,7 +88,7 @@ public class SdnIp implements SdnIpService { private SdnIpFib fib; private LeadershipEventListener leadershipEventListener = - new InnerLeadershipEventListener(); + new InnerLeadershipEventListener(); private ApplicationId appId; private ControllerNode localControllerNode; @@ -113,6 +117,10 @@ public class SdnIp implements SdnIpService { leadershipService.addListener(leadershipEventListener); leadershipService.runForLeadership(appId.name()); + + applicationService.registerDeactivateHook(appId, + intentSynchronizer::removeIntents); + } @Deactivate diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/AddPeerCommand.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/AddPeerCommand.java new file mode 100644 index 00000000..81231ab9 --- /dev/null +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/AddPeerCommand.java @@ -0,0 +1,96 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * 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.sdnip.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onlab.packet.IpAddress; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.incubator.net.intf.InterfaceService; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.routing.RoutingService; +import org.onosproject.routing.config.BgpConfig; + +/** + * Command to add new BGP peer to existing internal speaker. + */ +@Command(scope = "onos", name = "add-bgp-peer", + description = "Adds an external BGP router as peer to an existing BGP speaker") +public class AddPeerCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "name", + description = "Name of the internal BGP speaker", + required = true, multiValued = false) + String name = null; + + @Argument(index = 1, name = "ip", + description = "IP address of the BGP peer", + required = true, multiValued = false) + String ip = null; + + private static final String PEER_ADD_SUCCESS = "Peer Successfully Added."; + private static final String NO_CONFIGURATION = "No speakers configured"; + private static final String SPEAKER_NOT_FOUND = + "Speaker with name \'%s\' not found"; + private static final String NO_INTERFACE = + "No matching interface found for IP \'%s\'"; + + private IpAddress peerAddress = null; + + @Override + protected void execute() { + peerAddress = IpAddress.valueOf(ip); + + NetworkConfigService configService = get(NetworkConfigService.class); + CoreService coreService = get(CoreService.class); + ApplicationId appId = coreService.getAppId(RoutingService.ROUTER_APP_ID); + + BgpConfig config = configService.getConfig(appId, BgpConfig.class); + if (config == null || config.bgpSpeakers().isEmpty()) { + print(NO_CONFIGURATION); + return; + } + + BgpConfig.BgpSpeakerConfig speaker = config.getSpeakerWithName(name); + if (speaker == null) { + print(SPEAKER_NOT_FOUND, name); + return; + } else { + if (speaker.isConnectedToPeer(peerAddress)) { + return; // Peering already exists. + } + } + + InterfaceService interfaceService = get(InterfaceService.class); + if (interfaceService.getMatchingInterface(peerAddress) == null) { + print(NO_INTERFACE, ip); + return; + } + + addPeerToSpeakerConf(config); + configService.applyConfig(appId, BgpConfig.class, config.node()); + + print(PEER_ADD_SUCCESS); + } + + private void addPeerToSpeakerConf(BgpConfig config) { + log.debug("Creating BGP configuration for new peer: {}", ip); + config.addPeerToSpeaker(name, peerAddress); + } +} diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/AddSpeakerCommand.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/AddSpeakerCommand.java new file mode 100644 index 00000000..84353852 --- /dev/null +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/AddSpeakerCommand.java @@ -0,0 +1,90 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * 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.sdnip.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onlab.packet.IpAddress; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.routing.RoutingService; +import org.onosproject.routing.config.BgpConfig; + +import java.util.HashSet; +import java.util.Optional; + +/** + * Command to add a new internal BGP speaker. + */ +@Command(scope = "onos", name = "add-bgp-speaker", + description = "Adds an internal BGP speaker") +public class AddSpeakerCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "name", + description = "Name of the internal BGP speaker", + required = true, multiValued = false) + String name = null; + + @Argument(index = 1, name = "connectionPoint", + description = "Interface to the BGP speaker", + required = true, multiValued = false) + String connectionPoint = null; + + private static final String SPEAKER_ADD_SUCCESS = "Speaker Successfully Added."; + + @Override + protected void execute() { + NetworkConfigService configService = get(NetworkConfigService.class); + CoreService coreService = get(CoreService.class); + ApplicationId appId = coreService.getAppId(RoutingService.ROUTER_APP_ID); + + BgpConfig config = configService.addConfig(appId, BgpConfig.class); + + BgpConfig.BgpSpeakerConfig speaker = config.getSpeakerWithName(name); + if (speaker != null) { + log.debug("Speaker already exists: {}", name); + return; + } + + addSpeakerToConf(config); + configService.applyConfig(appId, BgpConfig.class, config.node()); + + print(SPEAKER_ADD_SUCCESS); + } + + /** + * Adds the speaker to the BgpConfig service. + * + * @param config the BGP configuration + */ + private void addSpeakerToConf(BgpConfig config) { + log.debug("Adding new speaker to configuration: {}", name); + BgpConfig.BgpSpeakerConfig speaker = getSpeaker(); + + config.addSpeaker(speaker); + } + + private BgpConfig.BgpSpeakerConfig getSpeaker() { + ConnectPoint connectPoint = ConnectPoint. + deviceConnectPoint(connectionPoint); + return new BgpConfig.BgpSpeakerConfig(Optional.ofNullable(name), + connectPoint, new HashSet<IpAddress>()); + } +} diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/RemovePeerCommand.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/RemovePeerCommand.java new file mode 100644 index 00000000..bfc6fb7b --- /dev/null +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/RemovePeerCommand.java @@ -0,0 +1,81 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * 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.sdnip.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onlab.packet.IpAddress; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.routing.RoutingService; +import org.onosproject.routing.config.BgpConfig; + +/** + * Command to remove existing BGP peer. + */ +@Command(scope = "onos", name = "remove-bgp-peer", + description = "Removes a BGP peer") +public class RemovePeerCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "ip", + description = "IP address of the BGP peer", + required = true, multiValued = false) + String ip = null; + + private static final String PEER_REMOVE_SUCCESS = "Peer Successfully Removed."; + private static final String NO_CONFIGURATION = "No speakers configured"; + private static final String PEER_NOT_FOUND = + "Peer with IP \'%s\' not found"; + + private IpAddress peerAddress = null; + + @Override + protected void execute() { + peerAddress = IpAddress.valueOf(ip); + + NetworkConfigService configService = get(NetworkConfigService.class); + CoreService coreService = get(CoreService.class); + ApplicationId appId = coreService.getAppId(RoutingService.ROUTER_APP_ID); + + BgpConfig config = configService.getConfig(appId, BgpConfig.class); + if (config == null || config.bgpSpeakers().isEmpty()) { + print(NO_CONFIGURATION); + return; + } + + peerAddress = IpAddress.valueOf(ip); + + BgpConfig.BgpSpeakerConfig speaker = config.getSpeakerFromPeer(peerAddress); + if (speaker == null) { + print(PEER_NOT_FOUND, ip); + return; + } + + removePeerFromSpeakerConf(speaker, config); + configService.applyConfig(appId, BgpConfig.class, config.node()); + + print(PEER_REMOVE_SUCCESS); + } + + private void removePeerFromSpeakerConf(BgpConfig.BgpSpeakerConfig speaker, + BgpConfig config) { + log.debug("Removing BGP configuration for peer: {}", ip); + config.removePeerFromSpeaker(speaker, peerAddress); + } +} diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/RemoveSpeakerCommand.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/RemoveSpeakerCommand.java new file mode 100644 index 00000000..6a51b42f --- /dev/null +++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/cli/RemoveSpeakerCommand.java @@ -0,0 +1,87 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * 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.sdnip.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.routing.RoutingService; +import org.onosproject.routing.config.BgpConfig; + +/** + * Command to remove a internal BGP speaker. + */ +@Command(scope = "onos", name = "remove-bgp-speaker", + description = "Removes an internal BGP speaker") +public class RemoveSpeakerCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "name", + description = "Name of the internal BGP speaker", + required = true, multiValued = false) + String name = null; + + private static final String SPEAKER_REMOVE_SUCCESS = "Speaker Successfully Removed."; + private static final String NO_CONFIGURATION = "No speakers configured"; + private static final String PEERS_EXIST = + "Speaker with name \'%s\' has peer connections"; + private static final String SPEAKER_NOT_FOUND = + "Speaker with name \'%s\' not found"; + + @Override + protected void execute() { + NetworkConfigService configService = get(NetworkConfigService.class); + CoreService coreService = get(CoreService.class); + ApplicationId appId = coreService.getAppId(RoutingService.ROUTER_APP_ID); + + BgpConfig config = configService.getConfig(appId, BgpConfig.class); + if (config == null || config.bgpSpeakers().isEmpty()) { + print(NO_CONFIGURATION); + return; + } + + BgpConfig.BgpSpeakerConfig speaker = config.getSpeakerWithName(name); + if (speaker == null) { + print(SPEAKER_NOT_FOUND, name); + return; + } else { + if (!speaker.peers().isEmpty()) { + // Removal not allowed when peer connections exist. + print(PEERS_EXIST, name); + return; + } + } + + removeSpeakerFromConf(config); + configService.applyConfig(appId, BgpConfig.class, config.node()); + + print(SPEAKER_REMOVE_SUCCESS); + } + + /** + * Removes the speaker from the BgpConfig service. + * + * @param bgpConfig the BGP configuration + */ + private void removeSpeakerFromConf(BgpConfig bgpConfig) { + log.debug("Removing speaker from configuration: {}", name); + + bgpConfig.removeSpeaker(name); + } +} diff --git a/framework/src/onos/apps/sdnip/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/apps/sdnip/src/main/resources/OSGI-INF/blueprint/shell-config.xml index 3be1c79a..97b2f09f 100644 --- a/framework/src/onos/apps/sdnip/src/main/resources/OSGI-INF/blueprint/shell-config.xml +++ b/framework/src/onos/apps/sdnip/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -19,5 +19,17 @@ <command> <action class="org.onosproject.sdnip.cli.PrimaryChangeCommand"/> </command> + <command> + <action class="org.onosproject.sdnip.cli.AddSpeakerCommand"/> + </command> + <command> + <action class="org.onosproject.sdnip.cli.RemoveSpeakerCommand"/> + </command> + <command> + <action class="org.onosproject.sdnip.cli.AddPeerCommand"/> + </command> + <command> + <action class="org.onosproject.sdnip.cli.RemovePeerCommand"/> + </command> </command-bundle> </blueprint> |