blob: ac50a300d60c5d2d41fd3b6db88077045e9225d4 [file] [log] [blame]
/*
* Copyright 2022-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.
*
* This work was partially supported by EC H2020 project B5G-OPEN (101016663).
*/
package org.onosproject.drivers.odtn;
import com.google.common.collect.ImmutableList;
import org.onosproject.drivers.odtn.impl.DeviceConnectionCache;
import org.onosproject.drivers.odtn.impl.FlowRuleParser;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.netconf.DatastoreId;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery.OC_OPTICAL_CHANNEL_NAME;
/**
* Implementation of FlowRuleProgrammable interface for Cassini device running Ocnos v5.
*/
public class CassiniOcnos5FlowRuleProgrammable
extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
private static final Logger log =
LoggerFactory.getLogger(CassiniOcnos5FlowRuleProgrammable.class);
private static final String RPC_TAG_NETCONF_BASE =
"<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
private static final String RPC_CLOSE_TAG = "</rpc>";
/**
* Apply the flow entries specified in the collection rules.
*
* @param rules A collection of Flow Rules to be applied
* @return The collection of added Flow Entries
*/
@Override
public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
NetconfSession session = getNetconfSession();
if (session == null) {
ocnosError("null session");
return ImmutableList.of();
}
List<FlowRule> added = new ArrayList<>();
for (FlowRule r : rules) {
try {
String connectionId = applyFlowRule(session, r);
getConnectionCache().add(did(), connectionId, r);
added.add(r);
} catch (Exception e) {
ocnosError("Error {}", e);
continue;
}
}
ocnosLog("applyFlowRules added {}", added.size());
return added;
}
/**
* Get the flow entries that are present on the device.
*
* @return A collection of Flow Entries
*/
@Override
public Collection<FlowEntry> getFlowEntries() {
DeviceConnectionCache cache = getConnectionCache();
if (cache.get(did()) == null) {
return ImmutableList.of();
}
List<FlowEntry> entries = new ArrayList<>();
for (FlowRule r : cache.get(did())) {
entries.add(
new DefaultFlowEntry(r, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
}
return entries;
}
/**
* Remove the specified flow rules.
*
* @param rules A collection of Flow Rules to be removed
* @return The collection of removed Flow Entries
*/
@Override
public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
NetconfSession session = getNetconfSession();
if (session == null) {
ocnosError("null session");
return ImmutableList.of();
}
List<FlowRule> removed = new ArrayList<>();
for (FlowRule r : rules) {
try {
String connectionId = removeFlowRule(session, r);
getConnectionCache().remove(did(), connectionId);
removed.add(r);
} catch (Exception e) {
ocnosError("Error {}", e);
continue;
}
}
ocnosLog("removedFlowRules removed {}", removed.size());
return removed;
}
private DeviceConnectionCache getConnectionCache() {
return DeviceConnectionCache.init();
}
/**
* Helper method to get the device id.
*/
private DeviceId did() {
return data().deviceId();
}
/**
* Helper method to log from this class adding DeviceId.
*/
private void ocnosLog(String format, Object... arguments) {
log.info("OCNOS5 {}: " + format, did(), arguments);
}
/**
* Helper method to log an error from this class adding DeviceId.
*/
private void ocnosError(String format, Object... arguments) {
log.error("OCNOS5 {}: " + format, did(), arguments);
}
/**
* Helper method to get the Netconf Session.
*/
private NetconfSession getNetconfSession() {
NetconfController controller =
checkNotNull(handler().get(NetconfController.class));
return controller.getNetconfDevice(did()).getSession();
}
/**
* Get the OpenConfig component name for the OpticalChannel component.
*
* @param portNumber ONOS port number of the Line port ().
* @return the channel component name or null
*/
protected String getOpticalChannel(PortNumber portNumber) {
Port clientPort = handler().get(DeviceService.class).getPort(did(), portNumber);
return clientPort.annotations().value(OC_OPTICAL_CHANNEL_NAME);
}
public void setOpticalChannelFrequency(NetconfSession session, FlowRuleParser r)
throws NetconfException {
StringBuilder sbSet = new StringBuilder();
String slot = getOpticalChannel(r.getPortNumber());
sbSet.append("<terminal-device xmlns='http://www.ipinfusion.com/yang/ocnos/ipi-platform-terminal-device'>"
+ "<coherent-module>"
+ " <slot-index>" + slot + "</slot-index>"
+ " <config>"
+ " <slot-index>" + slot + "</slot-index>"
+ " </config>"
+ "<network-interfaces>"
+ "<interface>"
+ " <net-index>0</net-index>"
+ " <config>"
+ " <net-index>0</net-index>"
+ " <frequency>" + r.getCentralFrequency().asHz() + "Hz</frequency>"
+ " </config>"
+ "</interface>"
+ "</network-interfaces>"
+ "</coherent-module>"
+ "</terminal-device>");
log.info("Configure optical channel {}", sbSet);
boolean set = session.editConfig(DatastoreId.CANDIDATE, null, sbSet.toString());
if (!set) {
throw new NetconfException("error editing channel frequency");
}
log.info("Commit configure optical channel");
boolean commit2 = session.commit();
if (!commit2) {
throw new NetconfException("error committing channel frequency");
}
};
public void deleteOpticalChannelFrequency(NetconfSession session, FlowRuleParser r)
throws NetconfException {
StringBuilder sb = new StringBuilder();
String slot = getOpticalChannel(r.getPortNumber());
sb.append("<terminal-device xmlns='http://www.ipinfusion.com/yang/ocnos/ipi-platform-terminal-device'>"
+ "<coherent-module>"
+ " <slot-index>" + slot + "</slot-index>"
+ " <config>"
+ " <slot-index>" + slot + "</slot-index>"
+ " </config>"
+ "<network-interfaces>"
+ "<interface>"
+ " <net-index>0</net-index>"
+ " <config>"
+ " <net-index>0</net-index>"
+ " <frequency>" + r.getCentralFrequency().asHz() + "Hz</frequency>"
+ " </config>"
+ "</interface>"
+ "</network-interfaces>"
+ "</coherent-module>"
+ "</terminal-device>");
log.info("Disable service and delete optical channel {}", sb);
boolean edit = session.editConfig(DatastoreId.CANDIDATE, null, sb.toString());
if (!edit) {
throw new NetconfException("error editing channel frequency");
}
log.info("Commit optical channel");
boolean commit = session.commit();
if (!commit) {
throw new NetconfException("error committing channel frequency");
}
};
/**
* Apply the flowrule.
*
* @param session The Netconf session.
* @param r Flow Rules to be applied.
* @return the optical channel + the frequency or just channel as identifier fo the config installed on the device
* @throws NetconfException if exchange goes wrong
*/
protected String applyFlowRule(NetconfSession session, FlowRule r)
throws NetconfException {
FlowRuleParser frp = new FlowRuleParser(r);
setOpticalChannelFrequency(session, frp);
return frp.getPortNumber() + ":" + frp.getCentralFrequency().asGHz();
}
protected String removeFlowRule(NetconfSession session, FlowRule r)
throws NetconfException {
FlowRuleParser frp = new FlowRuleParser(r);
deleteOpticalChannelFrequency(session, frp);
return frp.getPortNumber() + ":" + frp.getCentralFrequency().asGHz();
}
}