ONOS-6626 OFAgent - return port info in PortDescStatsReply and PortStatus messages
Change-Id: I79201784f533dae34d8274fe2fb54e259e8a4a48
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchOperationService.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchOperationService.java
index 6e2f5ad..4def7a7 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchOperationService.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchOperationService.java
@@ -28,13 +28,21 @@
/**
* Processes a new port of the switch.
- * It sends out FEATURE_REPLY message to the controllers.
+ * It sends out PORT_STATUS asynchronous message to the controllers.
*
* @param port virtual port
*/
void processPortAdded(Port port);
/**
+ * Processes the removal of a port from the switch.
+ * It sends out PORT_STATUS asynchronous message to the controllers.
+ *
+ * @param port virtual port
+ */
+ void processPortRemoved(Port port);
+
+ /**
* Processes port link down.
* It sends out PORT_STATUS asynchronous message to the controllers.
*
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
index 898aede..b836e72 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
@@ -16,6 +16,8 @@
package org.onosproject.ofagent.api;
import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
import java.util.Set;
@@ -38,4 +40,13 @@
* @return set of openflow switches; empty set if no devices exist on the network
*/
Set<OFSwitch> ofSwitches(NetworkId networkId);
+
+ /**
+ * Returns all ports of the specified device in the specified network.
+ *
+ * @param networkId network id
+ * @param deviceId device id
+ * @return set of ports; empty set if no ports exist for the specified device
+ */
+ Set<Port> ports(NetworkId networkId, DeviceId deviceId);
}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
index 8aa6b49..d52654f 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
@@ -17,11 +17,15 @@
import com.google.common.collect.ImmutableSet;
import io.netty.channel.Channel;
+import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.ofagent.api.OFSwitch;
import org.onosproject.ofagent.api.OFSwitchCapabilities;
+import org.onosproject.ofagent.api.OFSwitchService;
import org.projectfloodlight.openflow.protocol.OFBarrierReply;
import org.projectfloodlight.openflow.protocol.OFControllerRole;
import org.projectfloodlight.openflow.protocol.OFEchoReply;
@@ -33,6 +37,9 @@
import org.projectfloodlight.openflow.protocol.OFHello;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortReason;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFRoleReply;
import org.projectfloodlight.openflow.protocol.OFRoleRequest;
import org.projectfloodlight.openflow.protocol.OFSetConfig;
@@ -41,10 +48,13 @@
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -64,8 +74,12 @@
private final Logger log;
+ private final OFSwitchService ofSwitchService;
+
private final DatapathId dpId;
private final OFSwitchCapabilities capabilities;
+ private final NetworkId networkId;
+ private final DeviceId deviceId;
// miss_send_len field (in OFSetConfig and OFGetConfig messages) indicates the max
// bytes of a packet that the switch sends to the controller
@@ -77,16 +91,24 @@
private int handshakeTransactionIds = -1;
- private DefaultOFSwitch(DatapathId dpid, OFSwitchCapabilities capabilities) {
+ private DefaultOFSwitch(DatapathId dpid, OFSwitchCapabilities capabilities,
+ NetworkId networkId, DeviceId deviceId,
+ OFSwitchService ofSwitchService) {
this.dpId = dpid;
this.capabilities = capabilities;
+ this.networkId = networkId;
+ this.deviceId = deviceId;
+ this.ofSwitchService = ofSwitchService;
log = LoggerFactory.getLogger(getClass().getName() + " : " + dpid);
}
- public static DefaultOFSwitch of(DatapathId dpid, OFSwitchCapabilities capabilities) {
+ public static DefaultOFSwitch of(DatapathId dpid, OFSwitchCapabilities capabilities,
+ NetworkId networkId, DeviceId deviceId,
+ ServiceDirectory serviceDirectory) {
checkNotNull(dpid, "DPID cannot be null");
checkNotNull(capabilities, "OF capabilities cannot be null");
- return new DefaultOFSwitch(dpid, capabilities);
+ return new DefaultOFSwitch(dpid, capabilities, networkId, deviceId,
+ serviceDirectory.get(OFSwitchService.class));
}
@Override
@@ -142,8 +164,12 @@
@Override
public void processPortAdded(Port port) {
- // TODO generate FEATURES_REPLY message and send it to the controller
- log.debug("Functionality not yet supported for {}", port);
+ sendPortStatus(port, OFPortReason.ADD);
+ }
+
+ @Override
+ public void processPortRemoved(Port port) {
+ sendPortStatus(port, OFPortReason.DELETE);
}
@Override
@@ -176,6 +202,32 @@
log.debug("Functionality not yet supported for {}", msg);
}
+ private void sendPortStatus(Port port, OFPortReason ofPortReason) {
+ Set<Channel> channels = controllerChannels();
+ if (channels.isEmpty()) {
+ log.trace("No channels present. Port status will not be sent.");
+ return;
+ }
+ OFPortDesc ofPortDesc = portDesc(port);
+ OFPortStatus ofPortStatus = FACTORY.buildPortStatus()
+ .setDesc(ofPortDesc)
+ .setReason(ofPortReason)
+ .build();
+ log.trace("Sending port status {}", ofPortStatus);
+ channels.forEach(channel -> {
+ channel.writeAndFlush(Collections.singletonList(ofPortStatus));
+ });
+ }
+
+ private OFPortDesc portDesc(Port port) {
+ OFPort ofPort = OFPort.of((int) port.number().toLong());
+ // TODO handle port state and other port attributes
+ OFPortDesc ofPortDesc = FACTORY.buildPortDesc()
+ .setPortNo(ofPort)
+ .build();
+ return ofPortDesc;
+ }
+
@Override
public void processStatsRequest(Channel channel, OFMessage msg) {
if (msg.getType() != OFType.STATS_REQUEST) {
@@ -187,8 +239,15 @@
OFStatsReply ofStatsReply = null;
switch (ofStatsRequest.getStatsType()) {
case PORT_DESC:
+ List<OFPortDesc> portDescs = new ArrayList<>();
+ Set<Port> ports = ofSwitchService.ports(networkId, deviceId);
+ ports.forEach(port -> {
+ OFPortDesc ofPortDesc = portDesc(port);
+ portDescs.add(ofPortDesc);
+ });
ofStatsReply = FACTORY.buildPortDescStatsReply()
.setXid(msg.getXid())
+ .setEntries(portDescs)
//TODO add details
.build();
break;
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java
index e23cb81..59a2b2c 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java
@@ -33,8 +33,10 @@
import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
+import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@@ -157,10 +159,19 @@
return ImmutableSet.copyOf(ofSwitches);
}
+ @Override
+ public Set<Port> ports(NetworkId networkId, DeviceId deviceId) {
+ Set<Port> ports = virtualNetService.getVirtualPorts(networkId, deviceId)
+ .stream()
+ .collect(Collectors.toSet());
+ return ImmutableSet.copyOf(ports);
+ }
+
private void addOFSwitch(NetworkId networkId, DeviceId deviceId) {
OFSwitch ofSwitch = DefaultOFSwitch.of(
dpidWithDeviceId(deviceId),
- DEFAULT_CAPABILITIES);
+ DEFAULT_CAPABILITIES, networkId, deviceId,
+ virtualNetService.getServiceDirectory());
ofSwitchMap.put(deviceId, ofSwitch);
log.info("Added virtual OF switch for {}", deviceId);
@@ -289,6 +300,7 @@
@Override
public void event(VirtualNetworkEvent event) {
+ log.trace("Vnet event {}", event);
switch (event.type()) {
case VIRTUAL_DEVICE_ADDED:
eventExecutor.execute(() -> {
@@ -312,14 +324,46 @@
case NETWORK_UPDATED:
case NETWORK_REMOVED:
case NETWORK_ADDED:
+ break;
case VIRTUAL_PORT_ADDED:
+ eventExecutor.execute(() -> {
+ OFSwitch ofSwitch = ofSwitch(event.virtualPort());
+ if (ofSwitch != null) {
+ ofSwitch.processPortAdded(event.virtualPort());
+ log.debug("Virtual port {} added to network {}",
+ event.virtualPort(),
+ event.subject());
+ }
+ });
+ break;
case VIRTUAL_PORT_UPDATED:
+ break;
case VIRTUAL_PORT_REMOVED:
+ eventExecutor.execute(() -> {
+ OFSwitch ofSwitch = ofSwitch(event.virtualPort());
+ if (ofSwitch != null) {
+ ofSwitch.processPortRemoved(event.virtualPort());
+ log.debug("Virtual port {} removed from network {}",
+ event.virtualPort(),
+ event.subject());
+ }
+ });
+ break;
default:
// do nothing
break;
}
}
+
+ private OFSwitch ofSwitch(VirtualPort virtualPort) {
+ OFSwitch ofSwitch = ofSwitchMap.get(virtualPort.element().id());
+ if (ofSwitch == null) {
+ log.warn("Switch does not exist for port {}", virtualPort);
+ } else {
+ log.trace("Switch exists for port {}", virtualPort);
+ }
+ return ofSwitch;
+ }
}
private class InternalOFAgentListener implements OFAgentListener {