aboutsummaryrefslogtreecommitdiffstats
path: root/framework
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-10-23 08:31:31 -0700
committerAshlee Young <ashlee@onosfw.com>2015-10-23 08:31:31 -0700
commite52e67767076b29cb01939aa7bdd8fee9d205cc1 (patch)
treeb8c2d28231bccc2a280fea429a9af7297c62f58f /framework
parenta912c5ce9968da5936a695064f22083898e7b93d (diff)
Update ONOS src to commit id 69b36d5d11e81e28e56b46ba44e4b8cd701c5867
Change-Id: I9c13045711dbf9c0181106b66a6bf22c72bcf330 Signed-off-by: Ashlee Young <ashlee@onosfw.com>
Diffstat (limited to 'framework')
-rw-r--r--framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java244
-rw-r--r--framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java4
-rw-r--r--framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAAIntegrationTest.java151
-rw-r--r--framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java375
-rw-r--r--framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATestBase.java224
-rw-r--r--framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java4
-rw-r--r--framework/src/onos/apps/cordvtn/pom.xml10
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java143
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java1
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java9
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeAddCommand.java65
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeConnectCommand.java60
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java57
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDisconnectCommand.java60
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeListCommand.java74
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/package-info.java20
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/package-info.java20
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml35
-rw-r--r--framework/src/onos/apps/olt/pom.xml9
-rw-r--r--framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceConfig.java43
-rw-r--r--framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceData.java76
-rw-r--r--framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceService.java41
-rw-r--r--framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/OLT.java144
-rw-r--r--framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/SubscriberAddCommand.java58
-rw-r--r--framework/src/onos/apps/olt/src/main/resources/OSGI-INF/blueprint/shell-config.xml29
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java18
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java12
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ECMPShortestPathGraph.java8
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java2
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java8
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java3
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java9
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java9
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java23
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java8
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java6
-rw-r--r--framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml2
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java6
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java30
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ArpPaCriterion.java80
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java13
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java6
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java55
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java12
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java220
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java27
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java3
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java19
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/NodeBadgeTest.java112
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/TopoJsonTest.java46
-rw-r--r--framework/src/onos/docs/internal-apps1
-rw-r--r--framework/src/onos/docs/internal-netconf1
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java2
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java25
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java68
-rw-r--r--framework/src/onos/etc/init/onos.conf37
-rw-r--r--framework/src/onos/etc/org.ops4j.pax.url.mvn.cfg101
-rw-r--r--framework/src/onos/etc/org.ops4j.pax.web.cfg12
-rw-r--r--framework/src/onos/etc/samples/linkGraph.cfg27
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.fwd.ReactiveForwarding.cfg79
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.provider.host.impl.HostLocationProvider.cfg13
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.provider.lldp.impl.LLDPLinkProvider.cfg21
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.provider.netconf.device.impl.NetconfDeviceProvider.cfg11
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.provider.nil.device.impl.NullDeviceProvider.cfg11
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.provider.nil.link.impl.NullLinkProvider.cfg16
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.provider.nil.packet.impl.NullPacketProvider.cfg4
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.proxyarp.ProxyArp.cfg8
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.routing.bgp.BgpSessionManager.cfg8
-rw-r--r--framework/src/onos/etc/samples/org.onosproject.xos.XOS.cfg0
-rw-r--r--framework/src/onos/etc/users.properties34
-rw-r--r--framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java15
-rw-r--r--framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java9
-rw-r--r--framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java8
-rw-r--r--framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java26
-rw-r--r--framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java5
-rw-r--r--framework/src/onos/opt/onos/.empty0
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java9
-rw-r--r--framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java13
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java6
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java8
-rw-r--r--framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java8
-rw-r--r--framework/src/onos/tools/package/config/samples/network-cfg.json4
-rw-r--r--framework/src/onos/tools/package/config/samples/segmentrouting_dell.conf93
-rw-r--r--framework/src/onos/tools/test/scenarios/sequential-example.xml27
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/EthType.java2
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MacAddress.java1
-rwxr-xr-xframework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java3
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java16
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java17
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java23
-rw-r--r--framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Compiler.java69
-rw-r--r--framework/src/onos/utils/stc/src/test/java/org/onlab/stc/CompilerTest.java4
-rw-r--r--framework/src/onos/utils/stc/src/test/resources/org/onlab/stc/scenario.xml7
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/fw/svg/glyph.js2
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js19
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js12
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js8
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_1_addInstance.json14
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_2_addDevice_s1.json18
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_3_addDevice_s2.json18
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json16
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json8
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json30
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json8
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json12
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/traffic/scenario.json4
106 files changed, 2617 insertions, 1097 deletions
diff --git a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java
index 479ec7ed..72a5b122 100644
--- a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java
+++ b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java
@@ -15,10 +15,13 @@
*/
package org.onosproject.aaa;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
-import java.util.Optional;
-import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -30,20 +33,13 @@ import org.onlab.packet.EAP;
import org.onlab.packet.EAPOL;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.RADIUS;
import org.onlab.packet.RADIUSAttribute;
-import org.onlab.packet.TpPort;
-import org.onlab.packet.UDP;
-import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
@@ -53,7 +49,6 @@ import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
@@ -63,6 +58,8 @@ import org.onosproject.net.packet.PacketService;
import org.onosproject.xosintegration.VoltTenantService;
import org.slf4j.Logger;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
import static org.onosproject.net.packet.PacketPriority.CONTROL;
import static org.slf4j.LoggerFactory.getLogger;
@@ -85,10 +82,6 @@ public class AAA {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
- // end host information
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected HostService hostService;
-
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected VoltTenantService voltTenantService;
@@ -121,6 +114,12 @@ public class AAA {
// our unique identifier
private ApplicationId appId;
+ // Socket used for UDP communications with RADIUS server
+ private DatagramSocket radiusSocket;
+
+ // Executor for RADIUS communication thread
+ private ExecutorService executor;
+
// Configuration properties factory
private final ConfigFactory factory =
new ConfigFactory<ApplicationId, AAAConfig>(APP_SUBJECT_FACTORY,
@@ -184,7 +183,16 @@ public class AAA {
StateMachine.initializeMaps();
- hostService.startMonitoringIp(IpAddress.valueOf(radiusIpAddress));
+ try {
+ radiusSocket = new DatagramSocket(radiusServerPort);
+ } catch (Exception ex) {
+ log.error("Can't open RADIUS socket", ex);
+ }
+
+ executor = Executors.newSingleThreadExecutor(
+ new ThreadFactoryBuilder()
+ .setNameFormat("AAA-radius-%d").build());
+ executor.execute(radiusListener);
}
@Deactivate
@@ -195,6 +203,24 @@ public class AAA {
packetService.removeProcessor(processor);
processor = null;
StateMachine.destroyMaps();
+ radiusSocket.close();
+ executor.shutdownNow();
+ }
+
+ protected void sendRADIUSPacket(RADIUS radiusPacket) {
+
+ try {
+ final byte[] data = radiusPacket.serialize();
+ final DatagramSocket socket = radiusSocket;
+
+ DatagramPacket packet =
+ new DatagramPacket(data, data.length,
+ radiusIpAddress, radiusServerPort);
+
+ socket.send(packet);
+ } catch (IOException e) {
+ log.info("Cannot send packet to RADIUS server", e);
+ }
}
/**
@@ -205,14 +231,6 @@ public class AAA {
selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort());
packetService.requestPackets(selector.build(),
CONTROL, appId);
-
- TrafficSelector radSelector = DefaultTrafficSelector.builder()
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .matchIPProtocol(IPv4.PROTOCOL_UDP)
- .matchUdpDst(TpPort.tpPort(radiusServerPort))
- .matchUdpSrc(TpPort.tpPort(radiusServerPort))
- .build();
- packetService.requestPackets(radSelector, CONTROL, appId);
}
/**
@@ -222,14 +240,19 @@ public class AAA {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort());
packetService.cancelPackets(selector.build(), CONTROL, appId);
+ }
- TrafficSelector radSelector = DefaultTrafficSelector.builder()
- .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .matchIPProtocol(IPv4.PROTOCOL_UDP)
- .matchUdpDst(TpPort.tpPort(radiusServerPort))
- .matchUdpSrc(TpPort.tpPort(radiusServerPort))
- .build();
- packetService.cancelPackets(radSelector, CONTROL, appId);
+ /**
+ * Send the ethernet packet to the supplicant.
+ *
+ * @param ethernetPkt the ethernet packet
+ * @param connectPoint the connect point to send out
+ */
+ private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint) {
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
+ OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
+ treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
+ packetService.emit(packet);
}
// our handler defined as a private inner class
@@ -253,26 +276,11 @@ public class AAA {
case EAPOL:
handleSupplicantPacket(context.inPacket());
break;
- case IPV4:
- IPv4 ipv4Packet = (IPv4) ethPkt.getPayload();
- Ip4Address srcIp = Ip4Address.valueOf(ipv4Packet.getSourceAddress());
- Ip4Address radiusIp4Address = Ip4Address.valueOf(radiusIpAddress);
- if (srcIp.equals(radiusIp4Address) && ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) {
- // TODO: check for port as well when it's configurable
- UDP udpPacket = (UDP) ipv4Packet.getPayload();
-
- byte[] datagram = udpPacket.getPayload().serialize();
- RADIUS radiusPacket;
- radiusPacket = RADIUS.deserializer().deserialize(datagram, 0, datagram.length);
- handleRadiusPacket(radiusPacket);
- }
-
- break;
default:
log.trace("Skipping Ethernet packet type {}",
EthType.EtherType.lookup(ethPkt.getEtherType()));
}
- } catch (DeserializationException | StateMachineException e) {
+ } catch (StateMachineException e) {
log.warn("Unable to process RADIUS packet:", e);
}
}
@@ -280,23 +288,26 @@ public class AAA {
/**
* Creates and initializes common fields of a RADIUS packet.
*
- * @param identifier RADIUS identifier
+ * @param stateMachine state machine for the request
* @param eapPacket EAP packet
* @return RADIUS packet
*/
- private RADIUS getRadiusPayload(byte identifier, EAP eapPacket) {
+ private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
RADIUS radiusPayload =
new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
eapPacket.getIdentifier());
+
+ // set Request Authenticator in StateMachine
+ stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
+
radiusPayload.setIdentifier(identifier);
radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
- eapPacket.getData());
+ stateMachine.username());
radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
AAA.this.nasIpAddress.getAddress());
radiusPayload.encapsulateMessage(eapPacket);
- radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret);
return radiusPayload;
}
@@ -329,13 +340,13 @@ public class AAA {
//send an EAP Request/Identify to the supplicant
EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
- Ethernet eth = buildEapolResponse(srcMAC, MacAddress.valueOf(1L),
+ Ethernet eth = buildEapolResponse(srcMAC, MacAddress.valueOf(nasMacAddress),
ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
eapPayload);
stateMachine.setSupplicantAddress(srcMAC);
stateMachine.setVlanId(ethPkt.getVlanID());
- this.sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
+ sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
break;
case EAPOL.EAPOL_PACKET:
@@ -350,11 +361,10 @@ public class AAA {
// request id access to RADIUS
stateMachine.setUsername(eapPacket.getData());
- radiusPayload = getRadiusPayload(stateMachine.identifier(), eapPacket);
+ radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
+ radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret);
- // set Request Authenticator in StateMachine
- stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
- sendRadiusMessage(radiusPayload);
+ sendRADIUSPacket(radiusPayload);
// change the state to "PENDING"
stateMachine.requestAccess();
@@ -365,24 +375,31 @@ public class AAA {
// machine.
if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
//send the RADIUS challenge response
- radiusPayload = getRadiusPayload(stateMachine.challengeIdentifier(), eapPacket);
+ radiusPayload =
+ getRadiusPayload(stateMachine,
+ stateMachine.identifier(),
+ eapPacket);
radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
stateMachine.challengeState());
- sendRadiusMessage(radiusPayload);
+ radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret);
+ sendRADIUSPacket(radiusPayload);
}
break;
case EAP.ATTR_TLS:
// request id access to RADIUS
- radiusPayload = getRadiusPayload(stateMachine.identifier(), eapPacket);
+ radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
stateMachine.challengeState());
stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
- sendRadiusMessage(radiusPayload);
- // TODO: this gets called on every fragment, should only be called at TLS-Start
- stateMachine.requestAccess();
+ radiusPayload.addMessageAuthenticator(AAA.this.radiusSecret);
+ sendRADIUSPacket(radiusPayload);
+
+ if (stateMachine.state() != StateMachine.STATE_PENDING) {
+ stateMachine.requestAccess();
+ }
break;
default:
@@ -392,14 +409,18 @@ public class AAA {
default:
log.trace("Skipping EAPOL message {}", eapol.getEapolType());
}
+
}
+ }
+
+ class RadiusListener implements Runnable {
/**
* Handles RADIUS packets.
*
* @param radiusPacket RADIUS packet coming from the RADIUS server.
*/
- private void handleRadiusPacket(RADIUS radiusPacket) throws StateMachineException {
+ protected void handleRadiusPacket(RADIUS radiusPacket) throws StateMachineException {
StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
if (stateMachine == null) {
log.error("Invalid session identifier, exiting...");
@@ -410,13 +431,16 @@ public class AAA {
Ethernet eth;
switch (radiusPacket.getCode()) {
case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
- byte[] challengeState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE).getValue();
+ byte[] challengeState =
+ radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE).getValue();
eapPayload = radiusPacket.decapsulateMessage();
stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
eth = buildEapolResponse(stateMachine.supplicantAddress(),
- MacAddress.valueOf(1L), stateMachine.vlanId(), EAPOL.EAPOL_PACKET,
+ MacAddress.valueOf(nasMacAddress),
+ stateMachine.vlanId(),
+ EAPOL.EAPOL_PACKET,
eapPayload);
- this.sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
+ sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
break;
case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
//send an EAPOL - Success to the supplicant.
@@ -425,9 +449,11 @@ public class AAA {
eapPayload = new EAP();
eapPayload = (EAP) eapPayload.deserialize(eapMessage, 0, eapMessage.length);
eth = buildEapolResponse(stateMachine.supplicantAddress(),
- MacAddress.valueOf(1L), stateMachine.vlanId(), EAPOL.EAPOL_PACKET,
+ MacAddress.valueOf(nasMacAddress),
+ stateMachine.vlanId(),
+ EAPOL.EAPOL_PACKET,
eapPayload);
- this.sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
+ sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
stateMachine.authorizeAccess();
break;
@@ -439,59 +465,45 @@ public class AAA {
}
}
- private void sendRadiusMessage(RADIUS radiusMessage) {
- Set<Host> hosts = hostService.getHostsByIp(IpAddress.valueOf(radiusIpAddress));
- Optional<Host> odst = hosts.stream().filter(h -> h.vlan().toShort() == VlanId.UNTAGGED).findFirst();
-
- Host dst;
- if (!odst.isPresent()) {
- log.info("Radius server {} is not present", radiusIpAddress);
- return;
- } else {
- dst = odst.get();
- }
-
- UDP udp = new UDP();
- IPv4 ip4Packet = new IPv4();
- Ethernet ethPkt = new Ethernet();
- radiusMessage.setParent(udp);
- udp.setDestinationPort(radiusServerPort);
- udp.setSourcePort(radiusServerPort);
- udp.setPayload(radiusMessage);
- udp.setParent(ip4Packet);
- ip4Packet.setSourceAddress(AAA.this.nasIpAddress.getHostAddress());
- ip4Packet.setDestinationAddress(AAA.this.radiusIpAddress.getHostAddress());
- ip4Packet.setProtocol(IPv4.PROTOCOL_UDP);
- ip4Packet.setPayload(udp);
- ip4Packet.setParent(ethPkt);
- ethPkt.setDestinationMACAddress(radiusMacAddress);
- ethPkt.setSourceMACAddress(nasMacAddress);
- ethPkt.setEtherType(Ethernet.TYPE_IPV4);
- ethPkt.setPayload(ip4Packet);
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(radiusPort)).build();
- OutboundPacket packet = new DefaultOutboundPacket(DeviceId.deviceId(radiusSwitch),
- treatment, ByteBuffer.wrap(ethPkt.serialize()));
- packetService.emit(packet);
- }
+ @Override
+ public void run() {
+ boolean done = false;
+ int packetNumber = 1;
+
+ log.info("UDP listener thread starting up");
+ RADIUS inboundRadiusPacket;
+ while (!done) {
+ try {
+ byte[] packetBuffer = new byte[RADIUS.RADIUS_MAX_LENGTH];
+ DatagramPacket inboundBasePacket =
+ new DatagramPacket(packetBuffer, packetBuffer.length);
+ DatagramSocket socket = radiusSocket;
+ socket.receive(inboundBasePacket);
+ log.info("Packet #{} received", packetNumber++);
+ try {
+ inboundRadiusPacket =
+ RADIUS.deserializer()
+ .deserialize(inboundBasePacket.getData(),
+ 0,
+ inboundBasePacket.getLength());
+ handleRadiusPacket(inboundRadiusPacket);
+ } catch (DeserializationException dex) {
+ log.error("Cannot deserialize packet", dex);
+ } catch (StateMachineException sme) {
+ log.error("Illegal state machine operation", sme);
+ }
- /**
- * Send the ethernet packet to the supplicant.
- *
- * @param ethernetPkt the ethernet packet
- * @param connectPoint the connect point to send out
- */
- private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint) {
- TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
- OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
- treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
- packetService.emit(packet);
+ } catch (IOException e) {
+ log.info("Socket was closed, exiting listener thread");
+ done = true;
+ }
+ }
}
-
}
+ RadiusListener radiusListener = new RadiusListener();
+
private class InternalConfigListener implements NetworkConfigListener {
/**
diff --git a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java
index c18d2bf2..73be7691 100644
--- a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java
+++ b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAAConfig.java
@@ -37,13 +37,13 @@ public class AAAConfig extends Config<ApplicationId> {
private static final String RADIUS_PORT = "radiusPort";
// RADIUS server IP address
- protected static final String DEFAULT_RADIUS_IP = "192.168.1.10";
+ protected static final String DEFAULT_RADIUS_IP = "10.128.10.4";
// RADIUS MAC address
protected static final String DEFAULT_RADIUS_MAC = "00:00:00:00:01:10";
// NAS IP address
- protected static final String DEFAULT_NAS_IP = "192.168.1.11";
+ protected static final String DEFAULT_NAS_IP = "10.128.9.244";
// NAS MAC address
protected static final String DEFAULT_NAS_MAC = "00:00:00:00:10:01";
diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAAIntegrationTest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAAIntegrationTest.java
new file mode 100644
index 00000000..fb513ced
--- /dev/null
+++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAAIntegrationTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2014 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.aaa;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.onlab.packet.EAP;
+import org.onlab.packet.EAPOL;
+import org.onlab.packet.Ethernet;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigRegistryAdapter;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Set of tests of the ONOS application component. These use an existing RADIUS
+ * server and sends live packets over the network to it.
+ */
+@Ignore ("This should not be run as part of the standard build")
+public class AAAIntegrationTest extends AAATestBase {
+
+ private AAA aaa;
+
+ /**
+ * Mocks the network config registry.
+ */
+ @SuppressWarnings("unchecked")
+ static final class TestNetworkConfigRegistry
+ extends NetworkConfigRegistryAdapter {
+ @Override
+ public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+ return (C) new AAAConfig();
+ }
+ }
+
+ /**
+ * Sets up the services required by the AAA application.
+ */
+ @Before
+ public void setUp() {
+ aaa = new AAA();
+ aaa.netCfgService = new TestNetworkConfigRegistry();
+ aaa.coreService = new CoreServiceAdapter();
+ aaa.packetService = new MockPacketService();
+ aaa.activate();
+ }
+
+ /**
+ * Fetches the sent packet at the given index. The requested packet
+ * must be the last packet on the list.
+ *
+ * @param index index into sent packets array
+ * @return packet
+ */
+ private Ethernet fetchPacket(int index) {
+ for (int iteration = 0; iteration < 20; iteration++) {
+ if (savedPackets.size() > index) {
+ return (Ethernet) savedPackets.get(index);
+ } else {
+ try {
+ Thread.sleep(250);
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Tests the authentication path through the AAA application by sending
+ * packets to the RADIUS server and checking the state machine
+ * transitions.
+ *
+ * @throws Exception when an unhandled error occurs
+ */
+ @Test
+ public void testAuthentication() throws Exception {
+
+ // (1) Supplicant start up
+
+ Ethernet startPacket = constructSupplicantStartPacket();
+ sendPacket(startPacket);
+
+ Ethernet responsePacket = fetchPacket(0);
+ assertThat(responsePacket, notNullValue());
+ checkRadiusPacket(aaa, responsePacket, EAP.REQUEST);
+
+ // (2) Supplicant identify
+
+ Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
+ sendPacket(identifyPacket);
+
+ // State machine should have been created by now
+
+ StateMachine stateMachine =
+ StateMachine.lookupStateMachineBySessionId(SESSION_ID);
+ assertThat(stateMachine, notNullValue());
+ assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
+
+ // (3) RADIUS MD5 challenge
+
+ Ethernet radiusChallengeMD5Packet = fetchPacket(1);
+ assertThat(radiusChallengeMD5Packet, notNullValue());
+ checkRadiusPacket(aaa, radiusChallengeMD5Packet, EAP.REQUEST);
+
+
+ // (4) Supplicant MD5 response
+
+ Ethernet md5RadiusPacket =
+ constructSupplicantIdentifyPacket(stateMachine,
+ EAP.ATTR_MD5,
+ stateMachine.challengeIdentifier(),
+ radiusChallengeMD5Packet);
+ sendPacket(md5RadiusPacket);
+
+
+ // (5) RADIUS Success
+
+ Ethernet successRadiusPacket = fetchPacket(2);
+ assertThat(successRadiusPacket, notNullValue());
+ EAPOL successEAPOL = (EAPOL) successRadiusPacket.getPayload();
+ EAP successEAP = (EAP) successEAPOL.getPayload();
+ assertThat(successEAP.getCode(), is(EAP.SUCCESS));
+
+ // State machine should be in authorized state
+
+ assertThat(stateMachine, notNullValue());
+ assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
+
+ }
+
+}
+
diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java
index 75a60336..860a7dbd 100644
--- a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java
+++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATest.java
@@ -15,164 +15,61 @@
*/
package org.onosproject.aaa;
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.onlab.packet.Data;
+import org.onlab.packet.BasePacket;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.EAP;
-import org.onlab.packet.EAPOL;
-import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
import org.onlab.packet.RADIUS;
import org.onlab.packet.RADIUSAttribute;
-import org.onlab.packet.UDP;
-import org.onlab.packet.VlanId;
import org.onosproject.core.CoreServiceAdapter;
-import org.onosproject.net.Annotations;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.host.HostServiceAdapter;
-import org.onosproject.net.packet.DefaultInboundPacket;
-import org.onosproject.net.packet.DefaultPacketContext;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketServiceAdapter;
-import org.onosproject.net.provider.ProviderId;
import com.google.common.base.Charsets;
-import com.google.common.collect.ImmutableSet;
-import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.onosproject.net.NetTestTools.connectPoint;
/**
* Set of tests of the ONOS application component.
*/
-public class AAATest {
+public class AAATest extends AAATestBase {
- MacAddress clientMac = MacAddress.valueOf("1a:1a:1a:1a:1a:1a");
- MacAddress serverMac = MacAddress.valueOf("2a:2a:2a:2a:2a:2a");
+ static final String BAD_IP_ADDRESS = "198.51.100.0";
- PacketProcessor packetProcessor;
private AAA aaa;
- List<Ethernet> savedPackets = new LinkedList<>();
- /**
- * Saves the given packet onto the saved packets list.
- *
- * @param eth packet to save
- */
- private void savePacket(Ethernet eth) {
- savedPackets.add(eth);
+ class AAAWithoutRadiusServer extends AAA {
+ protected void sendRADIUSPacket(RADIUS radiusPacket) {
+ savePacket(radiusPacket);
+ }
}
/**
- * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
+ * Mocks the AAAConfig class to force usage of an unroutable address for the
+ * RADIUS server.
*/
- private class MockPacketService extends PacketServiceAdapter {
-
- @Override
- public void addProcessor(PacketProcessor processor, int priority) {
- packetProcessor = processor;
- }
-
+ static class MockAAAConfig extends AAAConfig {
@Override
- public void emit(OutboundPacket packet) {
+ public InetAddress radiusIp() {
try {
- Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
- 0, packet.data().array().length);
- savePacket(eth);
- } catch (Exception e) {
- fail(e.getMessage());
+ return InetAddress.getByName(BAD_IP_ADDRESS);
+ } catch (UnknownHostException ex) {
+ // can't happen
+ throw new IllegalStateException(ex);
}
}
}
/**
- * Mocks the DefaultPacketContext.
- */
- private final class TestPacketContext extends DefaultPacketContext {
-
- private TestPacketContext(long time, InboundPacket inPkt,
- OutboundPacket outPkt, boolean block) {
- super(time, inPkt, outPkt, block);
- }
-
- @Override
- public void send() {
- // We don't send anything out.
- }
- }
-
- /**
- * Mocks a host to allow locating the Radius server.
- */
- private static final class MockHost implements Host {
- @Override
- public HostId id() {
- return null;
- }
-
- @Override
- public MacAddress mac() {
- return null;
- }
-
- @Override
- public VlanId vlan() {
- return VlanId.vlanId(VlanId.UNTAGGED);
- }
-
- @Override
- public Set<IpAddress> ipAddresses() {
- return null;
- }
-
- @Override
- public HostLocation location() {
- return null;
- }
-
- @Override
- public Annotations annotations() {
- return null;
- }
-
- @Override
- public ProviderId providerId() {
- return null;
- }
- }
-
- /**
- * Mocks the Host service.
- */
- private static final class MockHostService extends HostServiceAdapter {
- @Override
- public Set<Host> getHostsByIp(IpAddress ip) {
- return ImmutableSet.of(new MockHost());
- }
- }
-
- /**
* Mocks the network config registry.
*/
@SuppressWarnings("unchecked")
@@ -180,83 +77,12 @@ public class AAATest {
extends NetworkConfigRegistryAdapter {
@Override
public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
- return (C) new AAAConfig();
+ AAAConfig aaaConfig = new MockAAAConfig();
+ return (C) aaaConfig;
}
}
/**
- * Sends an Ethernet packet to the process method of the Packet Processor.
- *
- * @param reply Ethernet packet
- */
- private void sendPacket(Ethernet reply) {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());
- InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1),
- reply,
- byteBuffer);
-
- PacketContext context = new TestPacketContext(127L, inPacket, null, false);
- packetProcessor.process(context);
- }
-
- /**
- * Constructs an Ethernet packet containing a EAPOL_START Payload.
- *
- * @return Ethernet packet
- */
- private Ethernet constructSupplicantStartPacket() {
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(clientMac.toBytes());
- eth.setSourceMACAddress(serverMac.toBytes());
- eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
- eth.setVlanID((short) 2);
-
- EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 1, EAPOL.EAPOL_START, null);
-
- //eapol header
- EAPOL eapol = new EAPOL();
- eapol.setEapolType(EAPOL.EAPOL_START);
- eapol.setPacketLength(eap.getLength());
-
- //eap part
- eapol.setPayload(eap);
-
- eth.setPayload(eapol);
- eth.setPad(true);
- return eth;
- }
-
- /**
- * Constructs an Ethernet packet containing identification payload.
- *
- * @return Ethernet packet
- */
- private Ethernet constructSupplicantIdentifyPacket(byte type) {
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(clientMac.toBytes());
- eth.setSourceMACAddress(serverMac.toBytes());
- eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
- eth.setVlanID((short) 2);
-
- String username = "user";
- EAP eap = new EAP(EAP.REQUEST, (byte) 1, type,
- username.getBytes(Charsets.US_ASCII));
- eap.setIdentifier((byte) 1);
-
- // eapol header
- EAPOL eapol = new EAPOL();
- eapol.setEapolType(EAPOL.EAPOL_PACKET);
- eapol.setPacketLength(eap.getLength());
-
- // eap part
- eapol.setPayload(eap);
-
- eth.setPayload(eapol);
- eth.setPad(true);
- return eth;
- }
-
- /**
* Constructs an Ethernet packet containing a RADIUS challenge
* packet.
*
@@ -264,18 +90,9 @@ public class AAATest {
* @param challengeType type to use in challenge packet
* @return Ethernet packet
*/
- private Ethernet constructRADIUSCodeAccessChallengePacket(byte challengeCode, byte challengeType) {
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(clientMac.toBytes());
- eth.setSourceMACAddress(serverMac.toBytes());
- eth.setEtherType(EthType.EtherType.IPV4.ethType().toShort());
- eth.setVlanID((short) 2);
-
- IPv4 ipv4 = new IPv4();
- ipv4.setProtocol(IPv4.PROTOCOL_UDP);
- ipv4.setSourceAddress(aaa.radiusIpAddress.getHostAddress());
+ private RADIUS constructRADIUSCodeAccessChallengePacket(byte challengeCode, byte challengeType) {
- String challenge = "1234";
+ String challenge = "12345678901234567";
EAP eap = new EAP(challengeType, (byte) 1, challengeType,
challenge.getBytes(Charsets.US_ASCII));
@@ -291,13 +108,7 @@ public class AAATest {
radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
eap.serialize());
- UDP udp = new UDP();
- udp.setPayload(radius);
- ipv4.setPayload(udp);
-
- eth.setPayload(ipv4);
- eth.setPad(true);
- return eth;
+ return radius;
}
/**
@@ -305,11 +116,10 @@ public class AAATest {
*/
@Before
public void setUp() {
- aaa = new AAA();
+ aaa = new AAAWithoutRadiusServer();
aaa.netCfgService = new TestNetworkConfigRegistry();
aaa.coreService = new CoreServiceAdapter();
aaa.packetService = new MockPacketService();
- aaa.hostService = new MockHostService();
aaa.activate();
}
@@ -324,60 +134,16 @@ public class AAATest {
/**
* Extracts the RADIUS packet from a packet sent by the supplicant.
*
- * @param supplicantPacket packet sent by the supplicant
- * @return RADIUS packet
+ * @param radius RADIUS packet sent by the supplicant
* @throws DeserializationException if deserialization of the packet contents
* fails.
*/
- private RADIUS checkAndFetchRADIUSPacketFromSupplicant(Ethernet supplicantPacket)
+ private void checkRADIUSPacketFromSupplicant(RADIUS radius)
throws DeserializationException {
- assertThat(supplicantPacket, notNullValue());
- assertThat(supplicantPacket.getVlanID(), is(VlanId.UNTAGGED));
- assertThat(supplicantPacket.getSourceMAC().toString(), is(aaa.nasMacAddress));
- assertThat(supplicantPacket.getDestinationMAC().toString(), is(aaa.radiusMacAddress));
-
- assertThat(supplicantPacket.getPayload(), instanceOf(IPv4.class));
- IPv4 ipv4 = (IPv4) supplicantPacket.getPayload();
- assertThat(ipv4, notNullValue());
- assertThat(IpAddress.valueOf(ipv4.getSourceAddress()).toString(),
- is(aaa.nasIpAddress.getHostAddress()));
- assertThat(IpAddress.valueOf(ipv4.getDestinationAddress()).toString(),
- is(aaa.radiusIpAddress.getHostAddress()));
-
- assertThat(ipv4.getPayload(), instanceOf(UDP.class));
- UDP udp = (UDP) ipv4.getPayload();
- assertThat(udp, notNullValue());
-
- assertThat(udp.getPayload(), instanceOf(Data.class));
- Data data = (Data) udp.getPayload();
- RADIUS radius = RADIUS.deserializer()
- .deserialize(data.getData(), 0, data.getData().length);
assertThat(radius, notNullValue());
- return radius;
- }
-
- /**
- * Checks the contents of a RADIUS packet being sent to the RADIUS server.
- *
- * @param radiusPacket packet to check
- * @param code expected code
- */
- private void checkRadiusPacket(Ethernet radiusPacket, byte code) {
- assertThat(radiusPacket.getVlanID(), is((short) 2));
-
- // TODO: These address values seem wrong, but are produced by the current AAA implementation
- assertThat(radiusPacket.getSourceMAC(), is(MacAddress.valueOf(1L)));
- assertThat(radiusPacket.getDestinationMAC(), is(serverMac));
- assertThat(radiusPacket.getPayload(), instanceOf(EAPOL.class));
- EAPOL eapol = (EAPOL) radiusPacket.getPayload();
- assertThat(eapol, notNullValue());
-
- assertThat(eapol.getEapolType(), is(EAPOL.EAPOL_PACKET));
- assertThat(eapol.getPayload(), instanceOf(EAP.class));
- EAP eap = (EAP) eapol.getPayload();
+ EAP eap = radius.decapsulateMessage();
assertThat(eap, notNullValue());
- assertThat(eap.getCode(), is(code));
}
/**
@@ -387,11 +153,10 @@ public class AAATest {
* @param index index into sent packets array
* @return packet
*/
- private Ethernet fetchPacket(int index) {
- assertThat(savedPackets.size(), is(index + 1));
- Ethernet eth = savedPackets.get(index);
- assertThat(eth, notNullValue());
- return eth;
+ private BasePacket fetchPacket(int index) {
+ BasePacket packet = savedPackets.get(index);
+ assertThat(packet, notNullValue());
+ return packet;
}
/**
@@ -400,61 +165,64 @@ public class AAATest {
* @throws DeserializationException if packed deserialization fails.
*/
@Test
- public void testAuthentication() throws DeserializationException {
-
- // Our session id will be the device ID ("of:1") with the port ("1") concatenated
- String sessionId = "of:11";
+ public void testAuthentication() throws Exception {
// (1) Supplicant start up
Ethernet startPacket = constructSupplicantStartPacket();
sendPacket(startPacket);
- Ethernet responsePacket = fetchPacket(0);
- checkRadiusPacket(responsePacket, EAP.ATTR_IDENTITY);
+ Ethernet responsePacket = (Ethernet) fetchPacket(0);
+ checkRadiusPacket(aaa, responsePacket, EAP.ATTR_IDENTITY);
// (2) Supplicant identify
- Ethernet identifyPacket = constructSupplicantIdentifyPacket(EAP.ATTR_IDENTITY);
+ Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
sendPacket(identifyPacket);
- Ethernet radiusIdentifyPacket = fetchPacket(1);
+ RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
+
+ checkRADIUSPacketFromSupplicant(radiusIdentifyPacket);
- RADIUS radiusAccessRequest = checkAndFetchRADIUSPacketFromSupplicant(radiusIdentifyPacket);
- assertThat(radiusAccessRequest, notNullValue());
- assertThat(radiusAccessRequest.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
- assertThat(new String(radiusAccessRequest.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
- is("user"));
+ assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
+ assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
+ is("testuser"));
IpAddress nasIp =
IpAddress.valueOf(IpAddress.Version.INET,
- radiusAccessRequest.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
+ radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
.getValue());
assertThat(nasIp.toString(), is(aaa.nasIpAddress.getHostAddress()));
// State machine should have been created by now
StateMachine stateMachine =
- StateMachine.lookupStateMachineBySessionId(sessionId);
+ StateMachine.lookupStateMachineBySessionId(SESSION_ID);
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
// (3) RADIUS MD5 challenge
- Ethernet radiusCodeAccessChallengePacket =
+ RADIUS radiusCodeAccessChallengePacket =
constructRADIUSCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5);
- sendPacket(radiusCodeAccessChallengePacket);
+ aaa.radiusListener.handleRadiusPacket(radiusCodeAccessChallengePacket);
- Ethernet radiusChallengeMD5Packet = fetchPacket(2);
- checkRadiusPacket(radiusChallengeMD5Packet, EAP.ATTR_MD5);
+ Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
+ checkRadiusPacket(aaa, radiusChallengeMD5Packet, EAP.ATTR_MD5);
// (4) Supplicant MD5 response
- Ethernet md5RadiusPacket = constructSupplicantIdentifyPacket(EAP.ATTR_MD5);
+ Ethernet md5RadiusPacket =
+ constructSupplicantIdentifyPacket(stateMachine,
+ EAP.ATTR_MD5,
+ stateMachine.challengeIdentifier(),
+ radiusChallengeMD5Packet);
sendPacket(md5RadiusPacket);
- Ethernet supplicantMD5ResponsePacket = fetchPacket(3);
- RADIUS responseMd5RadiusPacket = checkAndFetchRADIUSPacketFromSupplicant(supplicantMD5ResponsePacket);
- assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 1));
+
+ RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
+
+ checkRADIUSPacketFromSupplicant(responseMd5RadiusPacket);
+ assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 0));
assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
// State machine should be in pending state
@@ -462,37 +230,20 @@ public class AAATest {
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
- // (5) RADIUS TLS Challenge
-
- Ethernet radiusCodeAccessChallengeTLSPacket =
- constructRADIUSCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_TLS);
- sendPacket(radiusCodeAccessChallengeTLSPacket);
+ // (5) RADIUS Success
- Ethernet radiusChallengeTLSPacket = fetchPacket(4);
- checkRadiusPacket(radiusChallengeTLSPacket, EAP.ATTR_TLS);
-
- // (6) Supplicant TLS response
-
- Ethernet tlsRadiusPacket = constructSupplicantIdentifyPacket(EAP.ATTR_TLS);
- sendPacket(tlsRadiusPacket);
- Ethernet supplicantTLSResponsePacket = fetchPacket(5);
- RADIUS responseTLSRadiusPacket = checkAndFetchRADIUSPacketFromSupplicant(supplicantTLSResponsePacket);
- assertThat(responseTLSRadiusPacket.getIdentifier(), is((byte) 0));
- assertThat(responseTLSRadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
-
- // (7) RADIUS Success
-
- Ethernet successPacket =
+ RADIUS successPacket =
constructRADIUSCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT, EAP.SUCCESS);
- sendPacket(successPacket);
- Ethernet supplicantSuccessPacket = fetchPacket(6);
+ aaa.radiusListener.handleRadiusPacket((successPacket));
+ Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);
- checkRadiusPacket(supplicantSuccessPacket, EAP.SUCCESS);
+ checkRadiusPacket(aaa, supplicantSuccessPacket, EAP.SUCCESS);
// State machine should be in authorized state
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
+
}
/**
@@ -502,7 +253,7 @@ public class AAATest {
public void testConfig() {
assertThat(aaa.nasIpAddress.getHostAddress(), is(AAAConfig.DEFAULT_NAS_IP));
assertThat(aaa.nasMacAddress, is(AAAConfig.DEFAULT_NAS_MAC));
- assertThat(aaa.radiusIpAddress.getHostAddress(), is(AAAConfig.DEFAULT_RADIUS_IP));
+ assertThat(aaa.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
assertThat(aaa.radiusMacAddress, is(AAAConfig.DEFAULT_RADIUS_MAC));
}
}
diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATestBase.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATestBase.java
new file mode 100644
index 00000000..dffcba2f
--- /dev/null
+++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AAATestBase.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 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.aaa;
+
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.onlab.packet.BasePacket;
+import org.onlab.packet.EAP;
+import org.onlab.packet.EAPOL;
+import org.onlab.packet.EthType;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.packet.DefaultInboundPacket;
+import org.onosproject.net.packet.DefaultPacketContext;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketServiceAdapter;
+
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.onosproject.net.NetTestTools.connectPoint;
+
+/**
+ * Common methods for AAA app testing.
+ */
+public class AAATestBase {
+
+ MacAddress clientMac = MacAddress.valueOf("1a:1a:1a:1a:1a:1a");
+ MacAddress serverMac = MacAddress.valueOf("2a:2a:2a:2a:2a:2a");
+
+ // Our session id will be the device ID ("of:1") with the port ("1") concatenated
+ static final String SESSION_ID = "of:11";
+
+ List<BasePacket> savedPackets = new LinkedList<>();
+ PacketProcessor packetProcessor;
+
+ /**
+ * Saves the given packet onto the saved packets list.
+ *
+ * @param packet packet to save
+ */
+ void savePacket(BasePacket packet) {
+ savedPackets.add(packet);
+ }
+
+ /**
+ * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
+ */
+ class MockPacketService extends PacketServiceAdapter {
+
+ @Override
+ public void addProcessor(PacketProcessor processor, int priority) {
+ packetProcessor = processor;
+ }
+
+ @Override
+ public void emit(OutboundPacket packet) {
+ try {
+ Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
+ 0, packet.data().array().length);
+ savePacket(eth);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Mocks the DefaultPacketContext.
+ */
+ final class TestPacketContext extends DefaultPacketContext {
+
+ private TestPacketContext(long time, InboundPacket inPkt,
+ OutboundPacket outPkt, boolean block) {
+ super(time, inPkt, outPkt, block);
+ }
+
+ @Override
+ public void send() {
+ // We don't send anything out.
+ }
+ }
+
+ /**
+ * Sends an Ethernet packet to the process method of the Packet Processor.
+ *
+ * @param reply Ethernet packet
+ */
+ void sendPacket(Ethernet reply) {
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());
+ InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1),
+ reply,
+ byteBuffer);
+
+ PacketContext context = new TestPacketContext(127L, inPacket, null, false);
+ packetProcessor.process(context);
+ }
+
+ /**
+ * Constructs an Ethernet packet containing identification payload.
+ *
+ * @return Ethernet packet
+ */
+ Ethernet constructSupplicantIdentifyPacket(StateMachine stateMachine,
+ byte type,
+ byte id,
+ Ethernet radiusChallenge)
+ throws Exception {
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(clientMac.toBytes());
+ eth.setSourceMACAddress(serverMac.toBytes());
+ eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
+ eth.setVlanID((short) 2);
+
+ String username = "testuser";
+ byte[] data = username.getBytes();
+
+
+ if (type == EAP.ATTR_MD5) {
+ String password = "testpassword";
+ EAPOL eapol = (EAPOL) radiusChallenge.getPayload();
+ EAP eap = (EAP) eapol.getPayload();
+
+ byte[] identifier = new byte[password.length() + eap.getData().length];
+
+ identifier[0] = stateMachine.challengeIdentifier();
+ System.arraycopy(password.getBytes(), 0, identifier, 1, password.length());
+ System.arraycopy(eap.getData(), 1, identifier, 1 + password.length(), 16);
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] hash = md.digest(identifier);
+ data = new byte[17];
+ data[0] = (byte) 16;
+ System.arraycopy(hash, 0, data, 1, 16);
+ }
+ EAP eap = new EAP(EAP.RESPONSE, (byte) 1, type,
+ data);
+ eap.setIdentifier(id);
+
+ // eapol header
+ EAPOL eapol = new EAPOL();
+ eapol.setEapolType(EAPOL.EAPOL_PACKET);
+ eapol.setPacketLength(eap.getLength());
+
+ // eap part
+ eapol.setPayload(eap);
+
+ eth.setPayload(eapol);
+ eth.setPad(true);
+ return eth;
+ }
+
+ /**
+ * Constructs an Ethernet packet containing a EAPOL_START Payload.
+ *
+ * @return Ethernet packet
+ */
+ Ethernet constructSupplicantStartPacket() {
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(clientMac.toBytes());
+ eth.setSourceMACAddress(serverMac.toBytes());
+ eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
+ eth.setVlanID((short) 2);
+
+ EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 2, EAPOL.EAPOL_START, null);
+
+ // eapol header
+ EAPOL eapol = new EAPOL();
+ eapol.setEapolType(EAPOL.EAPOL_START);
+ eapol.setPacketLength(eap.getLength());
+
+ // eap part
+ eapol.setPayload(eap);
+
+ eth.setPayload(eapol);
+ eth.setPad(true);
+ return eth;
+ }
+
+ /**
+ * Checks the contents of a RADIUS packet being sent to the RADIUS server.
+ *
+ * @param radiusPacket packet to check
+ * @param code expected code
+ */
+ void checkRadiusPacket(AAA aaa, Ethernet radiusPacket, byte code) {
+
+ assertThat(radiusPacket.getSourceMAC(),
+ is(MacAddress.valueOf(aaa.nasMacAddress)));
+ assertThat(radiusPacket.getDestinationMAC(), is(serverMac));
+
+ assertThat(radiusPacket.getPayload(), instanceOf(EAPOL.class));
+ EAPOL eapol = (EAPOL) radiusPacket.getPayload();
+ assertThat(eapol, notNullValue());
+
+ assertThat(eapol.getEapolType(), is(EAPOL.EAPOL_PACKET));
+ assertThat(eapol.getPayload(), instanceOf(EAP.class));
+ EAP eap = (EAP) eapol.getPayload();
+ assertThat(eap, notNullValue());
+
+ assertThat(eap.getCode(), is(code));
+ }
+}
diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java
index 04837e85..1838c63e 100644
--- a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java
+++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/StateMachineTest.java
@@ -21,7 +21,9 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import static org.junit.Assert.*;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
public class StateMachineTest {
diff --git a/framework/src/onos/apps/cordvtn/pom.xml b/framework/src/onos/apps/cordvtn/pom.xml
index b8e913d4..1d96108b 100644
--- a/framework/src/onos/apps/cordvtn/pom.xml
+++ b/framework/src/onos/apps/cordvtn/pom.xml
@@ -54,6 +54,16 @@
<artifactId>onos-ovsdb-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>3.0.3</version>
+ </dependency>
</dependencies>
</project>
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
index ba707800..4b28a14b 100644
--- a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -27,7 +27,6 @@ import org.onlab.util.KryoNamespace;
import org.onosproject.cluster.ClusterService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
-import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
@@ -52,6 +51,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -75,7 +75,8 @@ public class CordVtn implements CordVtnService {
.register(KryoNamespaces.API)
.register(DefaultOvsdbNode.class);
private static final String DEFAULT_BRIDGE_NAME = "br-int";
- private static final Map<String, String> VXLAN_OPTIONS = new HashMap<String, String>() {
+ private static final String DEFAULT_TUNNEL = "vxlan";
+ private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
{
put("key", "flow");
put("local_ip", "flow");
@@ -98,9 +99,6 @@ public class CordVtn implements CordVtnService {
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected MastershipService mastershipService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OvsdbController controller;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -117,11 +115,10 @@ public class CordVtn implements CordVtnService {
private final VmHandler vmHandler = new VmHandler();
private ConsistentMap<DeviceId, OvsdbNode> nodeStore;
- private ApplicationId appId;
@Activate
protected void activate() {
- appId = coreService.registerApplication("org.onosproject.cordvtn");
+ ApplicationId appId = coreService.registerApplication("org.onosproject.cordvtn");
nodeStore = storageService.<DeviceId, OvsdbNode>consistentMapBuilder()
.withSerializer(Serializer.using(NODE_SERIALIZER.build()))
.withName("cordvtn-nodestore")
@@ -148,38 +145,59 @@ public class CordVtn implements CordVtnService {
@Override
public void addNode(OvsdbNode ovsdb) {
checkNotNull(ovsdb);
- nodeStore.put(ovsdb.deviceId(), ovsdb);
+
+ nodeStore.putIfAbsent(ovsdb.deviceId(), ovsdb);
+
+ if (isNodeConnected(ovsdb)) {
+ init(ovsdb);
+ } else {
+ connect(ovsdb);
+ }
}
@Override
public void deleteNode(OvsdbNode ovsdb) {
checkNotNull(ovsdb);
+ if (deviceService.getDevice(ovsdb.deviceId()) != null) {
+ if (deviceService.isAvailable(ovsdb.deviceId())) {
+ log.warn("Cannot delete connected node {}", ovsdb.host());
+ return;
+ }
+ }
+ nodeStore.remove(ovsdb.deviceId());
+ }
+
+ @Override
+ public void connect(OvsdbNode ovsdb) {
+ checkNotNull(ovsdb);
+
if (!nodeStore.containsKey(ovsdb.deviceId())) {
+ log.warn("Node {} does not exist", ovsdb.host());
return;
}
- // check ovsdb and integration bridge connection state first
- if (isNodeConnected(ovsdb)) {
- log.warn("Cannot delete connected node {}", ovsdb.host());
- } else {
- nodeStore.remove(ovsdb.deviceId());
+ if (!isNodeConnected(ovsdb)) {
+ controller.connect(ovsdb.ip(), ovsdb.port());
}
}
@Override
- public void connect(OvsdbNode ovsdb) {
+ public void disconnect(OvsdbNode ovsdb) {
checkNotNull(ovsdb);
if (!nodeStore.containsKey(ovsdb.deviceId())) {
log.warn("Node {} does not exist", ovsdb.host());
return;
}
- controller.connect(ovsdb.ip(), ovsdb.port());
+
+ if (isNodeConnected(ovsdb)) {
+ OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
+ ovsdbClient.disconnect();
+ }
}
- @Override
- public void disconnect(OvsdbNode ovsdb) {
+ private void init(OvsdbNode ovsdb) {
checkNotNull(ovsdb);
if (!nodeStore.containsKey(ovsdb.deviceId())) {
@@ -187,11 +205,16 @@ public class CordVtn implements CordVtnService {
return;
}
- OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
- checkNotNull(ovsdbClient);
+ if (!isNodeConnected(ovsdb)) {
+ log.warn("Node {} is not connected", ovsdb.host());
+ return;
+ }
- if (ovsdbClient.isConnected()) {
- ovsdbClient.disconnect();
+ if (deviceService.getDevice(ovsdb.intBrId()) == null ||
+ !deviceService.isAvailable(ovsdb.intBrId())) {
+ createIntegrationBridge(ovsdb);
+ } else if (!checkVxlanPort(ovsdb)) {
+ createVxlanPort(ovsdb);
}
}
@@ -235,11 +258,45 @@ public class CordVtn implements CordVtnService {
OvsdbClientService ovsdbClient = controller.getOvsdbClient(
new OvsdbNodeId(ovsdb.ip(), ovsdb.port().toInt()));
if (ovsdbClient == null) {
- log.warn("Couldn't find ovsdb client of node {}", ovsdb.host());
+ log.debug("Couldn't find ovsdb client for {}", ovsdb.host());
}
return ovsdbClient;
}
+ private void createIntegrationBridge(OvsdbNode ovsdb) {
+ List<ControllerInfo> controllers = new ArrayList<>();
+ Sets.newHashSet(clusterService.getNodes())
+ .forEach(controller -> {
+ ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
+ controllers.add(ctrlInfo);
+ });
+ String dpid = ovsdb.intBrId().toString().substring(DPID_BEGIN);
+
+ // TODO change to use bridge config
+ OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
+ ovsdbClient.createBridge(DEFAULT_BRIDGE_NAME, dpid, controllers);
+ }
+
+ private void createVxlanPort(OvsdbNode ovsdb) {
+ // TODO change to use tunnel config and tunnel description
+ OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
+ ovsdbClient.createTunnel(DEFAULT_BRIDGE_NAME, DEFAULT_TUNNEL,
+ DEFAULT_TUNNEL, DEFAULT_TUNNEL_OPTIONS);
+ }
+
+ private boolean checkVxlanPort(OvsdbNode ovsdb) {
+ // TODO change to use tunnel config
+ OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
+ try {
+ ovsdbClient.getPorts().stream()
+ .filter(p -> p.portName().value().equals(DEFAULT_TUNNEL))
+ .findFirst().get();
+ } catch (NoSuchElementException e) {
+ return false;
+ }
+ return true;
+ }
+
private class InternalDeviceListener implements DeviceListener {
@Override
@@ -252,8 +309,11 @@ public class CordVtn implements CordVtnService {
eventExecutor.submit(() -> handler.connected(device));
break;
case DEVICE_AVAILABILITY_CHANGED:
- eventExecutor.submit(() -> handler.disconnected(device));
- // TODO handle the case that the device is recovered
+ if (deviceService.isAvailable(device.id())) {
+ eventExecutor.submit(() -> handler.connected(device));
+ } else {
+ eventExecutor.submit(() -> handler.disconnected(device));
+ }
break;
default:
break;
@@ -286,20 +346,10 @@ public class CordVtn implements CordVtnService {
public void connected(Device device) {
log.info("Ovsdb {} is connected", device.id());
- if (!mastershipService.isLocalMaster(device.id())) {
- return;
- }
-
- // TODO change to use bridge config
OvsdbNode ovsdb = getNode(device.id());
- OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
-
- List<ControllerInfo> controllers = new ArrayList<>();
- Sets.newHashSet(clusterService.getNodes()).forEach(controller ->
- controllers.add(new ControllerInfo(controller.ip(), OFPORT, "tcp")));
- String dpid = ovsdb.intBrId().toString().substring(DPID_BEGIN);
-
- ovsdbClient.createBridge(DEFAULT_BRIDGE_NAME, dpid, controllers);
+ if (ovsdb != null) {
+ init(ovsdb);
+ }
}
@Override
@@ -314,22 +364,19 @@ public class CordVtn implements CordVtnService {
public void connected(Device device) {
log.info("Integration Bridge {} is detected", device.id());
- OvsdbNode ovsdb = getNodes().stream()
- .filter(node -> node.intBrId().equals(device.id()))
- .findFirst().get();
-
- if (ovsdb == null) {
+ OvsdbNode ovsdb;
+ try {
+ ovsdb = getNodes().stream()
+ .filter(node -> node.intBrId().equals(device.id()))
+ .findFirst().get();
+ } catch (NoSuchElementException e) {
log.warn("Couldn't find OVSDB associated with {}", device.id());
return;
}
- if (!mastershipService.isLocalMaster(ovsdb.deviceId())) {
- return;
+ if (!checkVxlanPort(ovsdb)) {
+ createVxlanPort(ovsdb);
}
-
- // TODO change to use tunnel config and tunnel description
- OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
- ovsdbClient.createTunnel(DEFAULT_BRIDGE_NAME, "vxlan", "vxlan", VXLAN_OPTIONS);
}
@Override
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
index f276c7ca..287f2a34 100644
--- a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
@@ -94,7 +94,6 @@ public class CordVtnConfigManager {
DefaultOvsdbNode ovsdb = new DefaultOvsdbNode(
node.host(), node.ip(), node.port(), node.bridgeId());
cordVtnService.addNode(ovsdb);
- cordVtnService.connect(ovsdb);
});
}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
index c5b7a078..7a9a06a6 100644
--- a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
@@ -19,11 +19,20 @@ import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.net.DeviceId;
+import java.util.Comparator;
+
/**
* Representation of a node with ovsdb server.
*/
public interface OvsdbNode {
+ Comparator<OvsdbNode> OVSDB_NODE_COMPARATOR = new Comparator<OvsdbNode>() {
+ @Override
+ public int compare(OvsdbNode ovsdb1, OvsdbNode ovsdb2) {
+ return ovsdb1.host().compareTo(ovsdb2.host());
+ }
+ };
+
/**
* Returns the IP address of the ovsdb server.
*
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeAddCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeAddCommand.java
new file mode 100644
index 00000000..88d16341
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeAddCommand.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 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.cordvtn.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.DefaultOvsdbNode;
+import org.onosproject.cordvtn.OvsdbNode;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Adds a new OVSDB nodes.
+ */
+@Command(scope = "onos", name = "ovsdb-add",
+ description = "Adds a new OVSDB node to cordvtn")
+public class OvsdbNodeAddCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "host", description = "Hostname or IP",
+ required = true, multiValued = false)
+ private String host = null;
+
+ @Argument(index = 1, name = "address",
+ description = "OVSDB server listening address (ip:port)",
+ required = true, multiValued = false)
+ private String address = null;
+
+ @Argument(index = 2, name = "bridgeId",
+ description = "Device ID of integration bridge",
+ required = true, multiValued = false)
+ private String bridgeId = null;
+
+ @Override
+ protected void execute() {
+ checkArgument(address.contains(":"), "address should be ip:port format");
+ checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format");
+
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+ String[] ipPort = address.split(":");
+ OvsdbNode ovsdb = new DefaultOvsdbNode(host,
+ IpAddress.valueOf(ipPort[0]),
+ TpPort.tpPort(Integer.parseInt(ipPort[1])),
+ DeviceId.deviceId(bridgeId));
+ service.addNode(ovsdb);
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeConnectCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeConnectCommand.java
new file mode 100644
index 00000000..e4ca0f3c
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeConnectCommand.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 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.cordvtn.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.OvsdbNode;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Connects to OVSDBs.
+ */
+@Command(scope = "onos", name = "ovsdb-connect",
+ description = "Connects to OVSDBs")
+public class OvsdbNodeConnectCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "hosts", description = "Hostname(s) or IP(s)",
+ required = true, multiValued = true)
+ private String[] hosts = null;
+
+ @Override
+ protected void execute() {
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+
+ for (String host : hosts) {
+ OvsdbNode ovsdb;
+ try {
+ ovsdb = service.getNodes().stream()
+ .filter(node -> node.host().equals(host))
+ .findFirst().get();
+ } catch (NoSuchElementException e) {
+ print("Unable to find %s", host);
+ continue;
+ }
+
+ if (service.isNodeConnected(ovsdb)) {
+ print("OVSDB %s is already in connected state, do nothing", host);
+ } else {
+ service.connect(ovsdb);
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java
new file mode 100644
index 00000000..a500d0d8
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDeleteCommand.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 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.cordvtn.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.OvsdbNode;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Deletes OVSDB nodes from cordvtn.
+ */
+@Command(scope = "onos", name = "ovsdb-delete",
+ description = "Deletes OVSDB nodes from cordvtn")
+public class OvsdbNodeDeleteCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "hosts", description = "Hostname(s) or IP(s)",
+ required = true, multiValued = true)
+ private String[] hosts = null;
+
+ @Override
+ protected void execute() {
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+
+ for (String host : hosts) {
+ OvsdbNode ovsdb;
+ try {
+ ovsdb = service.getNodes().stream()
+ .filter(node -> node.host().equals(host))
+ .findFirst().get();
+
+ } catch (NoSuchElementException e) {
+ print("Unable to find %s", host);
+ continue;
+ }
+
+ service.deleteNode(ovsdb);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDisconnectCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDisconnectCommand.java
new file mode 100644
index 00000000..14e44e08
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeDisconnectCommand.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 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.cordvtn.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.OvsdbNode;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Disconnects OVSDBs.
+ */
+@Command(scope = "onos", name = "ovsdb-disconnect",
+ description = "Disconnects OVSDBs")
+public class OvsdbNodeDisconnectCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "hosts", description = "Hostname(s) or IP(s)",
+ required = true, multiValued = true)
+ private String[] hosts = null;
+
+ @Override
+ protected void execute() {
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+
+ for (String host : hosts) {
+ OvsdbNode ovsdb;
+ try {
+ ovsdb = service.getNodes().stream()
+ .filter(node -> node.host().equals(host))
+ .findFirst().get();
+ } catch (NoSuchElementException e) {
+ print("Unable to find %s", host);
+ continue;
+ }
+
+ if (!service.isNodeConnected(ovsdb)) {
+ print("OVSDB %s is already in disconnected state, do nothing", host);
+ } else {
+ service.disconnect(ovsdb);
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeListCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeListCommand.java
new file mode 100644
index 00000000..7d125ca6
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/OvsdbNodeListCommand.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 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.cordvtn.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.OvsdbNode;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all OVSDB nodes.
+ */
+@Command(scope = "onos", name = "ovsdbs",
+ description = "Lists all OVSDB nodes registered in cordvtn application")
+public class OvsdbNodeListCommand extends AbstractShellCommand {
+
+ @Override
+ protected void execute() {
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+ List<OvsdbNode> ovsdbs = service.getNodes();
+ Collections.sort(ovsdbs, OvsdbNode.OVSDB_NODE_COMPARATOR);
+
+ if (outputJson()) {
+ print("%s", json(service, ovsdbs));
+ } else {
+ for (OvsdbNode ovsdb : ovsdbs) {
+ print("host=%s, address=%s, br-int=%s, state=%s",
+ ovsdb.host(),
+ ovsdb.ip().toString() + ":" + ovsdb.port().toString(),
+ ovsdb.intBrId().toString(),
+ getState(service, ovsdb));
+ }
+ print("Total %s nodes", service.getNodeCount());
+ }
+ }
+
+ private JsonNode json(CordVtnService service, List<OvsdbNode> ovsdbs) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (OvsdbNode ovsdb : ovsdbs) {
+ String ipPort = ovsdb.ip().toString() + ":" + ovsdb.port().toString();
+ result.add(mapper.createObjectNode()
+ .put("host", ovsdb.host())
+ .put("address", ipPort)
+ .put("brInt", ovsdb.intBrId().toString())
+ .put("state", getState(service, ovsdb)));
+ }
+ return result;
+ }
+
+ private String getState(CordVtnService service, OvsdbNode ovsdb) {
+ return service.isNodeConnected(ovsdb) ? "CONNECTED" : "DISCONNECTED";
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/package-info.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/package-info.java
new file mode 100644
index 00000000..686172ce
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * Console commands to manage OVSDB nodes for cordvtn.
+ */
+package org.onosproject.cordvtn.cli; \ No newline at end of file
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/package-info.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/package-info.java
new file mode 100644
index 00000000..1c13737f
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 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.
+ */
+
+/**
+ * Application for provisioning virtual tenant networks.
+ */
+package org.onosproject.cordvtn; \ No newline at end of file
diff --git a/framework/src/onos/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100644
index 00000000..6e172387
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -0,0 +1,35 @@
+<!--
+ ~ Copyright 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.onosproject.cordvtn.cli.OvsdbNodeListCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.cordvtn.cli.OvsdbNodeAddCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.cordvtn.cli.OvsdbNodeDeleteCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.cordvtn.cli.OvsdbNodeConnectCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.cordvtn.cli.OvsdbNodeDisconnectCommand"/>
+ </command>
+ </command-bundle>
+</blueprint>
diff --git a/framework/src/onos/apps/olt/pom.xml b/framework/src/onos/apps/olt/pom.xml
index 180e026a..f803a61a 100644
--- a/framework/src/onos/apps/olt/pom.xml
+++ b/framework/src/onos/apps/olt/pom.xml
@@ -36,6 +36,15 @@
</properties>
<dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
diff --git a/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceConfig.java b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceConfig.java
new file mode 100644
index 00000000..90ed7403
--- /dev/null
+++ b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceConfig.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 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.olt;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.Config;
+
+/**
+ * Config object for access device data.
+ */
+public class AccessDeviceConfig extends Config<DeviceId> {
+
+ private static final String UPLINK = "uplink";
+ private static final String VLAN = "vlan";
+
+ /**
+ * Gets the access device configuration for this device.
+ *
+ * @return access device configuration
+ */
+ public AccessDeviceData getOlt() {
+ PortNumber uplink = PortNumber.portNumber(node.path(UPLINK).asText());
+ VlanId vlan = VlanId.vlanId(Short.parseShort(node.path(VLAN).asText()));
+
+ return new AccessDeviceData(subject(), uplink, vlan);
+ }
+}
diff --git a/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceData.java b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceData.java
new file mode 100644
index 00000000..f7e40e30
--- /dev/null
+++ b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceData.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 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.olt;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Information about an access device.
+ */
+public class AccessDeviceData {
+ private static final String DEVICE_ID_MISSING = "Device ID cannot be null";
+ private static final String UPLINK_MISSING = "Uplink cannot be null";
+ private static final String VLAN_MISSING = "VLAN ID cannot be null";
+
+ private final DeviceId deviceId;
+ private final PortNumber uplink;
+ private final VlanId vlan;
+
+ /**
+ * Class constructor.
+ *
+ * @param deviceId access device ID
+ * @param uplink uplink port number
+ * @param vlan device VLAN ID
+ */
+ public AccessDeviceData(DeviceId deviceId, PortNumber uplink, VlanId vlan) {
+ this.deviceId = checkNotNull(deviceId, DEVICE_ID_MISSING);
+ this.uplink = checkNotNull(uplink, UPLINK_MISSING);
+ this.vlan = checkNotNull(vlan, VLAN_MISSING);
+ }
+
+ /**
+ * Retrieves the access device ID.
+ *
+ * @return device ID
+ */
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ /**
+ * Retrieves the uplink port number.
+ *
+ * @return port number
+ */
+ public PortNumber uplink() {
+ return uplink;
+ }
+
+ /**
+ * Retrieves the VLAN ID assigned to the device.
+ *
+ * @return vlan ID
+ */
+ public VlanId vlan() {
+ return vlan;
+ }
+}
diff --git a/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceService.java b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceService.java
new file mode 100644
index 00000000..bd82f489
--- /dev/null
+++ b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/AccessDeviceService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 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.olt;
+
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Service for interacting with an access device (OLT).
+ */
+public interface AccessDeviceService {
+
+ /**
+ * Provisions connectivity for a subscriber on an access device.
+ *
+ * @param port subscriber's connection point
+ * @param vlan VLAN ID to provision for subscriber
+ */
+ void provisionSubscriber(ConnectPoint port, VlanId vlan);
+
+ /**
+ * Removes provisioned connectivity for a subscriber from an access device.
+ *
+ * @param port subscriber's connection point
+ */
+ void removeSubscriber(ConnectPoint port);
+}
diff --git a/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/OLT.java b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/OLT.java
index c92f47a2..9aa8865a 100644
--- a/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/OLT.java
+++ b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/OLT.java
@@ -15,7 +15,6 @@
*/
package org.onosproject.olt;
-
import com.google.common.base.Strings;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -24,13 +23,20 @@ import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
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.VlanId;
import org.onlab.util.Tools;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@@ -45,15 +51,17 @@ import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.Dictionary;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import static org.slf4j.LoggerFactory.getLogger;
/**
- * Sample mobility application. Cleans up flowmods when a host moves.
+ * Provisions rules on access devices.
*/
+@Service
@Component(immediate = true)
-public class OLT {
-
+public class OLT implements AccessDeviceService {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -65,10 +73,14 @@ public class OLT {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry networkConfig;
+
private final DeviceListener deviceListener = new InternalDeviceListener();
private ApplicationId appId;
+ private static final VlanId DEFAULT_VLAN = VlanId.vlanId((short) 0);
public static final int OFFSET = 200;
public static final int UPLINK_PORT = 129;
@@ -94,11 +106,39 @@ public class OLT {
label = "The gfast device id")
private String gfastDevice = GFAST_DEVICE;
+ private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
+
+ private InternalNetworkConfigListener configListener =
+ new InternalNetworkConfigListener();
+ private static final Class<AccessDeviceConfig> CONFIG_CLASS =
+ AccessDeviceConfig.class;
+
+ private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
+ new ConfigFactory<DeviceId, AccessDeviceConfig>(
+ SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
+ @Override
+ public AccessDeviceConfig createConfig() {
+ return new AccessDeviceConfig();
+ }
+ };
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.olt");
+ networkConfig.registerConfigFactory(configFactory);
+ networkConfig.addListener(configListener);
+
+ networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
+ subject -> {
+ AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
+ if (config != null) {
+ AccessDeviceData data = config.getOlt();
+ oltData.put(data.deviceId(), data);
+ }
+ }
+ );
+
/*deviceService.addListener(deviceListener);
deviceService.getPorts(DeviceId.deviceId(oltDevice)).stream().forEach(
@@ -129,6 +169,8 @@ public class OLT {
@Deactivate
public void deactivate() {
+ networkConfig.removeListener(configListener);
+ networkConfig.unregisterConfigFactory(configFactory);
log.info("Stopped");
}
@@ -136,16 +178,13 @@ public class OLT {
public void modified(ComponentContext context) {
Dictionary<?, ?> properties = context.getProperties();
-
String s = Tools.get(properties, "uplinkPort");
uplinkPort = Strings.isNullOrEmpty(s) ? UPLINK_PORT : Integer.parseInt(s);
s = Tools.get(properties, "oltDevice");
oltDevice = Strings.isNullOrEmpty(s) ? OLT_DEVICE : s;
-
}
-
private short fetchVlanId(PortNumber port) {
long p = port.toLong() + OFFSET;
if (p > 4095) {
@@ -155,7 +194,6 @@ public class OLT {
return (short) p;
}
-
private void provisionVlanOnPort(String deviceId, int uplinkPort, PortNumber p, short vlanId) {
DeviceId did = DeviceId.deviceId(deviceId);
@@ -198,7 +236,73 @@ public class OLT {
flowObjectiveService.forward(did, upFwd);
flowObjectiveService.forward(did, downFwd);
+ }
+
+ @Override
+ public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
+ AccessDeviceData olt = oltData.get(port.deviceId());
+
+ if (olt == null) {
+ log.warn("No data found for OLT device {}", port.deviceId());
+ return;
+ }
+
+ provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan());
+ }
+
+ private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
+ PortNumber subscriberPort,
+ VlanId subscriberVlan, VlanId deviceVlan) {
+
+ TrafficSelector upstream = DefaultTrafficSelector.builder()
+ .matchVlanId(DEFAULT_VLAN)
+ .matchInPort(subscriberPort)
+ .build();
+
+ TrafficSelector downstream = DefaultTrafficSelector.builder()
+ .matchVlanId(deviceVlan)
+ .matchInPort(uplinkPort)
+ .build();
+
+ TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
+ .setVlanId(subscriberVlan)
+ .pushVlan()
+ .setVlanId(deviceVlan)
+ .setOutput(uplinkPort)
+ .build();
+ TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
+ .popVlan()
+ .setVlanId(DEFAULT_VLAN)
+ .setOutput(subscriberPort)
+ .build();
+
+
+ ForwardingObjective upFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(upstream)
+ .fromApp(appId)
+ .withTreatment(upstreamTreatment)
+ .add();
+
+ ForwardingObjective downFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(downstream)
+ .fromApp(appId)
+ .withTreatment(downstreamTreatment)
+ .add();
+
+ flowObjectiveService.forward(deviceId, upFwd);
+ flowObjectiveService.forward(deviceId, downFwd);
+ }
+
+ @Override
+ public void removeSubscriber(ConnectPoint port) {
+ throw new UnsupportedOperationException("Not yet implemented");
}
private class InternalDeviceListener implements DeviceListener {
@@ -226,7 +330,27 @@ public class OLT {
}
}
+ private class InternalNetworkConfigListener implements NetworkConfigListener {
+ @Override
+ public void event(NetworkConfigEvent event) {
+ switch (event.type()) {
-}
-
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ if (event.configClass().equals(CONFIG_CLASS)) {
+ AccessDeviceConfig config =
+ networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
+ if (config != null) {
+ oltData.put(config.getOlt().deviceId(), config.getOlt());
+ }
+ }
+ break;
+ case CONFIG_UNREGISTERED:
+ case CONFIG_REMOVED:
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/SubscriberAddCommand.java b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/SubscriberAddCommand.java
new file mode 100644
index 00000000..d9b4559b
--- /dev/null
+++ b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/SubscriberAddCommand.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 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.olt;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.packet.VlanId;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+/**
+ * Adds a subscriber to an access device.
+ */
+@Command(scope = "onos", name = "add-subscriber-access",
+ description = "Adds a subscriber to an access device")
+public class SubscriberAddCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "deviceId", description = "Access device ID",
+ required = true, multiValued = false)
+ private String strDeviceId = null;
+
+ @Argument(index = 1, name = "port", description = "Subscriber port number",
+ required = true, multiValued = false)
+ private String strPort = null;
+
+ @Argument(index = 2, name = "vlanId",
+ description = "VLAN ID to add",
+ required = true, multiValued = false)
+ private String strVlanId = null;
+
+ @Override
+ protected void execute() {
+ AccessDeviceService service = AbstractShellCommand.get(AccessDeviceService.class);
+
+ DeviceId deviceId = DeviceId.deviceId(strDeviceId);
+ PortNumber port = PortNumber.portNumber(strPort);
+ VlanId vlan = VlanId.vlanId(Short.parseShort(strVlanId));
+ ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
+
+ service.provisionSubscriber(connectPoint, vlan);
+ }
+}
diff --git a/framework/src/onos/apps/olt/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/apps/olt/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100644
index 00000000..00ebe9d1
--- /dev/null
+++ b/framework/src/onos/apps/olt/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ Copyright 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.onosproject.olt.SubscriberAddCommand"/>
+ <completers>
+ <ref component-id="deviceIdCompleter"/>
+ <null/>
+ </completers>
+ </command>
+ </command-bundle>
+
+ <bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/>
+</blueprint>
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 8b447af4..40ee55fc 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -93,7 +93,7 @@ public class DefaultRoutingHandler {
try {
populationStatus = Status.STARTED;
rulePopulator.resetCounter();
- log.info("Starts to populate routing rules");
+ log.info("Starting to populate segment-routing rules");
log.debug("populateAllRoutingRules: populationStatus is STARTED");
for (Device sw : srManager.deviceService.getDevices()) {
@@ -117,7 +117,7 @@ public class DefaultRoutingHandler {
log.debug("populateAllRoutingRules: populationStatus is SUCCEEDED");
populationStatus = Status.SUCCEEDED;
- log.info("Completes routing rule population. Total # of rules pushed : {}",
+ log.info("Completed routing rule population. Total # of rules pushed : {}",
rulePopulator.getCounter());
return true;
} finally {
@@ -426,7 +426,7 @@ public class DefaultRoutingHandler {
.get(itrIdx);
for (DeviceId targetSw : swViaMap.keySet()) {
Set<DeviceId> nextHops = new HashSet<>();
-
+ log.debug("** Iter: {} root: {} target: {}", itrIdx, destSw, targetSw);
for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
if (via.isEmpty()) {
nextHops.add(destSw);
@@ -456,7 +456,7 @@ public class DefaultRoutingHandler {
// rule for both subnet and router IP.
if (config.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) {
List<Ip4Prefix> subnets = config.getSubnets(destSw);
- log.debug("populateEcmpRoutingRulePartial in device {} towards {} for subnets {}",
+ log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for subnets {}",
targetSw, destSw, subnets);
result = rulePopulator.populateIpRuleForSubnet(targetSw,
subnets,
@@ -468,7 +468,7 @@ public class DefaultRoutingHandler {
Ip4Address routerIp = config.getRouterIp(destSw);
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
- log.debug("populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
+ log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
targetSw, destSw, routerIpPrefix);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
@@ -479,7 +479,7 @@ public class DefaultRoutingHandler {
} else if (config.isEdgeDevice(targetSw)) {
Ip4Address routerIp = config.getRouterIp(destSw);
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
- log.debug("populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
+ log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
targetSw, destSw, routerIpPrefix);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
@@ -488,7 +488,7 @@ public class DefaultRoutingHandler {
}
// Populates MPLS rules to all routers
- log.debug("populateEcmpRoutingRulePartial in device{} towards {} for all MPLS rules",
+ log.debug("* populateEcmpRoutingRulePartial in device{} towards {} for all MPLS rules",
targetSw, destSw);
result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops);
if (!result) {
@@ -500,7 +500,7 @@ public class DefaultRoutingHandler {
/**
* Populates table miss entries for all tables, and pipeline rules for VLAN
- * and TACM tables.
+ * and TCAM tables. XXX rename/rethink
*
* @param deviceId Switch ID to set the rules
*/
@@ -534,6 +534,8 @@ public class DefaultRoutingHandler {
/**
* Resume the flow rule population process if it was aborted for any reason.
* Mostly the process is aborted when the groups required are not set yet.
+ * XXX is this called?
+ *
*/
public void resumePopulationProcess() {
statusLock.lock();
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
index eef1b147..0bc155b8 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
@@ -134,7 +134,7 @@ public class DeviceConfiguration implements DeviceProperties {
@Override
public int getSegmentId(DeviceId deviceId) {
if (deviceConfigMap.get(deviceId) != null) {
- log.debug("getSegmentId for device{} is {}",
+ log.trace("getSegmentId for device{} is {}",
deviceId,
deviceConfigMap.get(deviceId).nodeSid);
return deviceConfigMap.get(deviceId).nodeSid;
@@ -189,7 +189,7 @@ public class DeviceConfiguration implements DeviceProperties {
@Override
public MacAddress getDeviceMac(DeviceId deviceId) {
if (deviceConfigMap.get(deviceId) != null) {
- log.debug("getDeviceMac for device{} is {}",
+ log.trace("getDeviceMac for device{} is {}",
deviceId,
deviceConfigMap.get(deviceId).mac);
return deviceConfigMap.get(deviceId).mac;
@@ -209,7 +209,7 @@ public class DeviceConfiguration implements DeviceProperties {
*/
public Ip4Address getRouterIp(DeviceId deviceId) {
if (deviceConfigMap.get(deviceId) != null) {
- log.debug("getDeviceIp for device{} is {}",
+ log.trace("getDeviceIp for device{} is {}",
deviceId,
deviceConfigMap.get(deviceId).ip);
return deviceConfigMap.get(deviceId).ip;
@@ -231,7 +231,7 @@ public class DeviceConfiguration implements DeviceProperties {
@Override
public boolean isEdgeDevice(DeviceId deviceId) {
if (deviceConfigMap.get(deviceId) != null) {
- log.debug("isEdgeDevice for device{} is {}",
+ log.trace("isEdgeDevice for device{} is {}",
deviceId,
deviceConfigMap.get(deviceId).isEdge);
return deviceConfigMap.get(deviceId).isEdge;
@@ -297,7 +297,7 @@ public class DeviceConfiguration implements DeviceProperties {
*/
public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
if (deviceConfigMap.get(deviceId) != null) {
- log.debug("getSubnetGatewayIps for device{} is {}",
+ log.trace("getSubnetGatewayIps for device{} is {}",
deviceId,
deviceConfigMap.get(deviceId).gatewayIps.values());
return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
@@ -314,7 +314,7 @@ public class DeviceConfiguration implements DeviceProperties {
*/
public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
if (deviceConfigMap.get(deviceId) != null) {
- log.debug("getSubnets for device{} is {}",
+ log.trace("getSubnets for device{} is {}",
deviceId,
deviceConfigMap.get(deviceId).subnets.values());
return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ECMPShortestPathGraph.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ECMPShortestPathGraph.java
index 2e2041c4..e9a59bae 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ECMPShortestPathGraph.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ECMPShortestPathGraph.java
@@ -31,7 +31,7 @@ import java.util.List;
/**
* This class creates bandwidth constrained breadth first tree and returns paths
- * from root Device to leaf Devicees which satisfies the bandwidth condition. If
+ * from root Device to leaf Devices which satisfies the bandwidth condition. If
* bandwidth parameter is not specified, the normal breadth first tree will be
* calculated. The paths are snapshot paths at the point of the class
* instantiation.
@@ -281,7 +281,7 @@ public class ECMPShortestPathGraph {
* Return the complete info of the computed ECMP paths for each Device
* learned in multiple iterations from the root Device.
*
- * @return the hash table of Devicees learned in multiple Dijkstra
+ * @return the hash table of Devices learned in multiple Dijkstra
* iterations and corresponding ECMP paths to it from the root
* Device
*/
@@ -305,8 +305,8 @@ public class ECMPShortestPathGraph {
* Return the complete info of the computed ECMP paths for each Device
* learned in multiple iterations from the root Device.
*
- * @return the hash table of Devicees learned in multiple Dijkstra
- * iterations and corresponding ECMP paths in terms of Devicees to
+ * @return the hash table of Devices learned in multiple Dijkstra
+ * iterations and corresponding ECMP paths in terms of Devices to
* be traversed to it from the root Device
*/
public HashMap<Integer, HashMap<DeviceId,
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java
index e37fe52a..14ce679b 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java
@@ -115,7 +115,7 @@ public class IpHandler {
/**
* Forwards IP packets in the buffer to the destination IP address.
* It is called when the controller finds the destination MAC address
- * via ARP responsees.
+ * via ARP responses.
*
* @param deviceId switch device ID
* @param destIpAddress destination IP address
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index d802be91..7641571d 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -150,7 +150,7 @@ public class RoutingRulePopulator {
/**
* Populates IP flow rules for the router IP address.
*
- * @param deviceId device ID to set the rules
+ * @param deviceId target device ID to set the rules
* @param ipPrefix the IP address of the destination router
* @param destSw device ID of the destination router
* @param nextHops next hop switch ID list
@@ -210,9 +210,9 @@ public class RoutingRulePopulator {
}
/**
- * Populates MPLS flow rules to all transit routers.
+ * Populates MPLS flow rules to all routers.
*
- * @param deviceId device ID of the switch to set the rules
+ * @param deviceId target device ID of the switch to set the rules
* @param destSwId destination switch device ID
* @param nextHops next hops switch ID list
* @return true if all rules are set successfully, false otherwise
@@ -379,7 +379,7 @@ public class RoutingRulePopulator {
.addCondition(Criteria.matchEthDst(config
.getDeviceMac(deviceId)));
fob.permit().fromApp(srManager.appId);
- log.debug("populateTableVlan: Installing filtering objective for router mac");
+ log.debug("populateTableTMac: Installing filtering objective for router mac");
srManager.flowObjectiveService.
filter(deviceId,
fob.add(new SRObjectiveContext(deviceId,
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 9011160c..eb2cf569 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -296,7 +296,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
}
/**
- * Returns the GrouopKey object for the device and the NighborSet given.
+ * Returns the GroupKey object for the device and the NeighborSet given.
+ * XXX is this called
*
* @param ns NeightborSet object for the GroupKey
* @return GroupKey object for the NeighborSet
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
index 3dc312df..c960adca 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
@@ -35,13 +35,14 @@ import org.onosproject.store.service.EventuallyConsistentMap;
* where D0 and D3 are edge devices and D1 and D2 are transit devices.
* Assume device D0 is connected to 2 neighbors (D1 and D2 ).
* The following groups will be created in D0:
- * 1) all ports to D1 + with no label push,
- * 2) all ports to D1 + with label 102 pushed,
- * 3) all ports to D1 + with label 103 pushed,
+ * 1) all ports to D1 + with no label push, // direct attach case, seen
+ * 2) all ports to D1 + with label 102 pushed, // this is not needed
+ * 3) all ports to D1 + with label 103 pushed, // maybe needed, sometimes seen
* 4) all ports to D2 + with no label push,
* 5) all ports to D2 + with label 101 pushed,
* 6) all ports to D2 + with label 103 pushed,
- * 7) all ports to D1 and D2 + with label 103 pushed
+ * 7) all ports to D1 and D2 + with label 103 pushed // ecmp case
+ * 8) what about ecmp no label case
*/
public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java
index 05ebccf9..0a3ea2cd 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/VirtualPortService.java
@@ -18,6 +18,7 @@ package org.onosproject.vtnrsc.virtualport;
import java.util.Collection;
import org.onosproject.net.DeviceId;
+import org.onosproject.vtnrsc.FixedIp;
import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.VirtualPort;
@@ -44,6 +45,14 @@ public interface VirtualPortService {
VirtualPort getPort(VirtualPortId virtualPortId);
/**
+ * Returns the virtualPort associated with the fixedIP.
+ *
+ * @param fixedIP the fixedIP identifier
+ * @return virtualPort.
+ */
+ VirtualPort getPort(FixedIp fixedIP);
+
+ /**
* Returns the collection of the currently known virtualPort.
* @return collection of VirtualPort.
*/
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java
index 926809c9..c45373b9 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java
@@ -17,9 +17,12 @@ package org.onosproject.vtnrsc.virtualport.impl;
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -68,6 +71,7 @@ public class VirtualPortManager implements VirtualPortService {
private static final String TENANTID_NOT_NULL = "TenantId cannot be null";
private static final String NETWORKID_NOT_NULL = "NetworkId cannot be null";
private static final String DEVICEID_NOT_NULL = "DeviceId cannot be null";
+ private static final String FIXEDIP_NOT_NULL = "FixedIp cannot be null";
protected Map<VirtualPortId, VirtualPort> vPortStore;
protected ApplicationId appId;
@@ -125,6 +129,25 @@ public class VirtualPortManager implements VirtualPortService {
}
@Override
+ public VirtualPort getPort(FixedIp fixedIP) {
+ checkNotNull(fixedIP, FIXEDIP_NOT_NULL);
+ List<VirtualPort> vPorts = new ArrayList<>();
+ vPortStore.values().stream().forEach(p -> {
+ Iterator<FixedIp> fixedIps = p.fixedIps().iterator();
+ while (fixedIps.hasNext()) {
+ if (fixedIps.next().equals(fixedIP)) {
+ vPorts.add(p);
+ break;
+ }
+ }
+ });
+ if (vPorts.size() == 0) {
+ return null;
+ }
+ return vPorts.get(0);
+ }
+
+ @Override
public Collection<VirtualPort> getPorts() {
return Collections.unmodifiableCollection(vPortStore.values());
}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java
index 6c33f45c..62cf042a 100644
--- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java
@@ -166,6 +166,10 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
required = false, multiValued = false)
private String pushVlan = null;
+ @Option(name = "--setQueue", description = "Set Queue ID",
+ required = false, multiValued = false)
+ private String setQueue = null;
+
// Priorities
@Option(name = "-p", aliases = "--priority", description = "Priority",
required = false, multiValued = false)
@@ -327,6 +331,10 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(pushVlan)));
emptyTreatment = false;
}
+ if (!isNullOrEmpty(setQueue)) {
+ treatmentBuilder.setQueue(Long.parseLong(setQueue));
+ emptyTreatment = false;
+ }
if (emptyTreatment) {
return DefaultTrafficTreatment.emptyTreatment();
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java
index eefb711a..4fd9b0df 100644
--- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfaceAddCommand.java
@@ -43,7 +43,7 @@ public class InterfaceAddCommand extends AbstractShellCommand {
@Option(name = "-m", aliases = "--mac",
description = "MAC address of the interface",
- required = true, multiValued = false)
+ required = false, multiValued = false)
private String mac = null;
@Option(name = "-i", aliases = "--ip",
@@ -68,10 +68,12 @@ public class InterfaceAddCommand extends AbstractShellCommand {
}
}
+ MacAddress macAddr = mac == null ? null : MacAddress.valueOf(mac);
+
VlanId vlanId = vlan == null ? VlanId.NONE : VlanId.vlanId(Short.parseShort(vlan));
Interface intf = new Interface(ConnectPoint.deviceConnectPoint(connectPoint),
- ipAddresses, MacAddress.valueOf(mac), vlanId);
+ ipAddresses, macAddr, vlanId);
interfaceService.add(intf);
}
diff --git a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 28461e27..cf76febe 100644
--- a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -146,6 +146,8 @@
<action class="org.onosproject.cli.net.AnnotateDeviceCommand"/>
<completers>
<ref component-id="deviceIdCompleter"/>
+ <null/>
+ <null/>
</completers>
</command>
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index a628725c..6174cef6 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -237,6 +237,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
case NOACTION:
case OUTPUT:
case GROUP:
+ case QUEUE:
case L0MODIFICATION:
case L2MODIFICATION:
case L3MODIFICATION:
@@ -381,6 +382,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
}
@Override
+ public Builder setQueue(long queueId) {
+ return add(Instructions.setQueue(queueId));
+ }
+
+ @Override
public TrafficTreatment.Builder meter(MeterId meterId) {
return add(Instructions.meterTraffic(meterId));
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
index 33753afa..c7fe8b85 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -190,14 +190,14 @@ public interface TrafficTreatment {
/**
* Push MPLS ether type.
*
- * @return a treatment builder.
+ * @return a treatment builder
*/
Builder pushMpls();
/**
* Pops MPLS ether type.
*
- * @return a treatment builder.
+ * @return a treatment builder
*/
Builder popMpls();
@@ -205,7 +205,7 @@ public interface TrafficTreatment {
* Pops MPLS ether type and set the new ethertype.
*
* @param etherType an ether type
- * @return a treatment builder.
+ * @return a treatment builder
* @deprecated in Drake Release
*/
@Deprecated
@@ -215,22 +215,22 @@ public interface TrafficTreatment {
* Pops MPLS ether type and set the new ethertype.
*
* @param etherType an ether type
- * @return a treatment builder.
+ * @return a treatment builder
*/
Builder popMpls(EthType etherType);
/**
* Sets the mpls label.
*
- * @param mplsLabel MPLS label.
- * @return a treatment builder.
+ * @param mplsLabel MPLS label
+ * @return a treatment builder
*/
Builder setMpls(MplsLabel mplsLabel);
/**
* Sets the mpls bottom-of-stack indicator bit.
*
- * @param mplsBos boolean to set BOS=1 (true) or BOS=0 (false).
+ * @param mplsBos boolean to set BOS=1 (true) or BOS=0 (false)
* @return a treatment builder.
*/
Builder setMplsBos(boolean mplsBos);
@@ -261,6 +261,14 @@ public interface TrafficTreatment {
Builder group(GroupId groupId);
/**
+ * Sets the Queue ID.
+ *
+ * @param queueId a queue ID
+ * @return a treatment builder
+ */
+ Builder setQueue(long queueId);
+
+ /**
* Sets a meter to be used by this flow.
*
* @param meterId a meter id
@@ -280,14 +288,14 @@ public interface TrafficTreatment {
/**
* Pops outermost VLAN tag.
*
- * @return a treatment builder.
+ * @return a treatment builder
*/
Builder popVlan();
/**
* Pushes a new VLAN tag.
*
- * @return a treatment builder.
+ * @return a treatment builder
*/
Builder pushVlan();
@@ -327,8 +335,8 @@ public interface TrafficTreatment {
/**
* Sets the tunnel id.
*
- * @param tunnelId a tunnel id.
- * @return a treatment builder.
+ * @param tunnelId a tunnel id
+ * @return a treatment builder
*/
Builder setTunnelId(long tunnelId);
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ArpPaCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ArpPaCriterion.java
new file mode 100644
index 00000000..ba5a03d8
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ArpPaCriterion.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 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.net.flow.criteria;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Objects;
+
+import org.onlab.packet.Ip4Address;
+
+/**
+ * Implementation of arp spa or tpa address criterion.
+ */
+public final class ArpPaCriterion implements Criterion {
+ private final Ip4Address ip;
+ private final Type type;
+
+ /**
+ * Constructor.
+ *
+ * @param ip the Ip4 Address to match.
+ * @param type the match type. Should be one of the following:
+ * Type.ARP_SPA, Type.ARP_TPA
+ */
+ ArpPaCriterion(Ip4Address ip, Type type) {
+ this.ip = ip;
+ this.type = type;
+ }
+
+ @Override
+ public Type type() {
+ return this.type;
+ }
+
+ /**
+ * Gets the Ip4 Address to match.
+ *
+ * @return the Ip4 Address to match
+ */
+ public Ip4Address ip() {
+ return this.ip;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("ip", ip).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), ip);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ArpPaCriterion) {
+ ArpPaCriterion that = (ArpPaCriterion) obj;
+ return Objects.equals(ip, that.ip) &&
+ Objects.equals(type, that.type);
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
index ae940bdc..778d50a5 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
@@ -16,6 +16,7 @@
package org.onosproject.net.flow.criteria;
import org.onlab.packet.EthType;
+import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
@@ -25,11 +26,11 @@ import org.onlab.packet.VlanId;
import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OchSignalType;
import org.onosproject.net.OduSignalId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criterion.Type;
-import org.onosproject.net.OchSignalType;
/**
* Factory class to create various traffic selection criteria.
@@ -508,6 +509,16 @@ public final class Criteria {
return new OduSignalTypeCriterion(signalType);
}
+ /**
+ * Creates a match on IPv4 source field using the specified value.
+ *
+ * @param ip ipv4 source value
+ * @return match criterion
+ */
+ public static Criterion matchArpTpa(Ip4Address ip) {
+ return new ArpPaCriterion(ip, Type.ARP_TPA);
+ }
+
public static Criterion dummy() {
return new DummyCriterion();
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
index eddbbb71..2f6a1cc1 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
@@ -49,6 +49,12 @@ public interface Instruction {
GROUP,
/**
+ * Signifies that the traffic should be enqueued to an already-configured
+ queue on a port.
+ */
+ QUEUE,
+
+ /**
* Signifies that traffic should be metered according to a meter.
*/
METER,
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
index 26981e5e..8868bf7c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -94,6 +94,17 @@ public final class Instructions {
return new GroupInstruction(groupId);
}
+ /**
+ * Creates a set-queue instruction.
+ *
+ * @param queueId Queue Id
+ * @return set-queue instruction
+ */
+ public static SetQueueInstruction setQueue(final long queueId) {
+ checkNotNull(queueId, "queue ID cannot be null");
+ return new SetQueueInstruction(queueId);
+ }
+
public static MeterInstruction meterTraffic(final MeterId meterId) {
checkNotNull(meterId, "meter id cannot be null");
return new MeterInstruction(meterId);
@@ -625,6 +636,50 @@ public final class Instructions {
}
/**
+ * Set-Queue Instruction.
+ */
+ public static final class SetQueueInstruction implements Instruction {
+ private final long queueId;
+
+ private SetQueueInstruction(long queueId) {
+ this.queueId = queueId;
+ }
+
+ public long queueId() {
+ return queueId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.QUEUE;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("queueId", queueId).toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), queueId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SetQueueInstruction) {
+ SetQueueInstruction that = (SetQueueInstruction) obj;
+ return Objects.equals(queueId, that.queueId);
+
+ }
+ return false;
+ }
+ }
+
+ /**
* A meter instruction.
*/
public static final class MeterInstruction implements Instruction {
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java
index 0ce6592c..0cc15475 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/DeviceHighlight.java
@@ -17,16 +17,16 @@
package org.onosproject.ui.topo;
/**
- * Denotes the highlighting to apply to a device.
+ * Denotes the highlighting to be applied to a device.
*/
public class DeviceHighlight extends NodeHighlight {
+ /**
+ * Constructs a device highlight entity.
+ *
+ * @param deviceId the device identifier
+ */
public DeviceHighlight(String deviceId) {
super(TopoElementType.DEVICE, deviceId);
}
-
- // TODO: implement device highlighting:
- // - visual highlight
- // - badging
-
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
new file mode 100644
index 00000000..7b517111
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 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.ui.topo;
+
+/**
+ * Designates a badge to be applied to a node in the topology view.
+ */
+public final class NodeBadge {
+
+ private static final String EMPTY = "";
+
+ /** Designates the badge status. */
+ public enum Status {
+ INFO("i"),
+ WARN("w"),
+ ERROR("e");
+
+ private String code;
+
+ Status(String code) {
+ this.code = code;
+ }
+
+ @Override
+ public String toString() {
+ return "{" + code + "}";
+ }
+
+ /** Returns the status code in string form. */
+ public String code() {
+ return code;
+ }
+ }
+
+ private final Status status;
+ private final boolean isGlyph;
+ private final String text;
+ private final String message;
+
+ // only instantiated through static methods.
+ private NodeBadge(Status status, boolean isGlyph, String text, String message) {
+ this.status = status == null ? Status.INFO : status;
+ this.isGlyph = isGlyph;
+ this.text = text;
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return "{Badge " + status +
+ " (" + text + ")" +
+ (isGlyph ? "*G " : " ") +
+ "\"" + message + "\"}";
+ }
+
+ /**
+ * Returns the badge status.
+ *
+ * @return badge status
+ */
+ public Status status() {
+ return status;
+ }
+
+ /**
+ * Returns true if the text for this badge designates a glyph ID.
+ *
+ * @return true if badge uses glyph
+ */
+ public boolean isGlyph() {
+ return isGlyph;
+ }
+
+ /**
+ * Returns the text for the badge.
+ * Note that if {@link #isGlyph} is true, the text is a glyph ID, otherwise
+ * the text is displayed verbatim in the badge.
+ *
+ * @return text for badge
+ */
+ public String text() {
+ return text;
+ }
+
+ /**
+ * Returns the message associated with the badge.
+ *
+ * @return associated message
+ */
+ public String message() {
+ return message;
+ }
+
+ private static String nonNull(String s) {
+ return s == null ? EMPTY : s;
+ }
+
+ /**
+ * Returns an arbitrary text badge, with default status.
+ *
+ * @param txt the text
+ * @return node badge to display text
+ */
+ public static NodeBadge text(String txt) {
+ // TODO: consider length constraint on txt (3 chars?)
+ return new NodeBadge(Status.INFO, false, nonNull(txt), null);
+ }
+
+ /**
+ * Returns a glyph badge, with default status.
+ *
+ * @param gid the glyph ID
+ * @return node badge to display glyph
+ */
+ public static NodeBadge glyph(String gid) {
+ return new NodeBadge(Status.INFO, true, nonNull(gid), null);
+ }
+
+ /**
+ * Returns a numeric badge, with default status.
+ *
+ * @param n the number
+ * @return node badge to display a number
+ */
+ public static NodeBadge number(int n) {
+ // TODO: consider constraints, e.g. 1 <= n <= 999
+ return new NodeBadge(Status.INFO, false, Integer.toString(n), null);
+ }
+
+ /**
+ * Returns an arbitrary text badge, with the given status.
+ *
+ * @param s the status
+ * @param txt the text
+ * @return node badge to display text
+ */
+ public static NodeBadge text(Status s, String txt) {
+ // TODO: consider length constraint on txt (3 chars?)
+ return new NodeBadge(s, false, nonNull(txt), null);
+ }
+
+ /**
+ * Returns a glyph badge, with the given status.
+ *
+ * @param s the status
+ * @param gid the glyph ID
+ * @return node badge to display glyph
+ */
+ public static NodeBadge glyph(Status s, String gid) {
+ return new NodeBadge(s, true, nonNull(gid), null);
+ }
+
+
+ /**
+ * Returns a numeric badge, with the given status and optional message.
+ *
+ * @param s the status
+ * @param n the number
+ * @return node badge to display a number
+ */
+ public static NodeBadge number(Status s, int n) {
+ // TODO: consider constraints, e.g. 1 <= n <= 999
+ return new NodeBadge(s, false, Integer.toString(n), null);
+ }
+
+ /**
+ * Returns an arbitrary text badge, with the given status and optional
+ * message.
+ *
+ * @param s the status
+ * @param txt the text
+ * @param msg the optional message
+ * @return node badge to display text
+ */
+ public static NodeBadge text(Status s, String txt, String msg) {
+ // TODO: consider length constraint on txt (3 chars?)
+ return new NodeBadge(s, false, nonNull(txt), msg);
+ }
+
+ /**
+ * Returns a glyph badge, with the given status and optional message.
+ *
+ * @param s the status
+ * @param gid the glyph ID
+ * @param msg the optional message
+ * @return node badge to display glyph
+ */
+ public static NodeBadge glyph(Status s, String gid, String msg) {
+ return new NodeBadge(s, true, nonNull(gid), msg);
+ }
+
+
+ /**
+ * Returns a numeric badge, with the given status and optional message.
+ *
+ * @param s the status
+ * @param n the number
+ * @param msg the optional message
+ * @return node badge to display a number
+ */
+ public static NodeBadge number(Status s, int n, String msg) {
+ // TODO: consider constraints, e.g. 1 <= n <= 999
+ return new NodeBadge(s, false, Integer.toString(n), msg);
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java
index 61e10c56..69235089 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeHighlight.java
@@ -20,7 +20,34 @@ package org.onosproject.ui.topo;
* Parent class of {@link DeviceHighlight} and {@link HostHighlight}.
*/
public abstract class NodeHighlight extends AbstractHighlight {
+
+ private NodeBadge badge;
+
+ /**
+ * Constructs a node highlight entity.
+ *
+ * @param type element type
+ * @param elementId element identifier
+ */
public NodeHighlight(TopoElementType type, String elementId) {
super(type, elementId);
}
+
+ /**
+ * Sets the badge for this node.
+ *
+ * @param badge badge to apply
+ */
+ public void setBadge(NodeBadge badge) {
+ this.badge = badge;
+ }
+
+ /**
+ * Returns the badge for this node, if any.
+ *
+ * @return badge, or null
+ */
+ public NodeBadge badge() {
+ return badge;
+ }
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java
index 0f42b628..e2034fa7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoConstants.java
@@ -32,14 +32,17 @@ public final class TopoConstants {
public static final class Glyphs {
public static final String UNKNOWN = "unknown";
public static final String BIRD = "bird";
+ public static final String QUERY = "query";
public static final String NODE = "node";
public static final String SWITCH = "switch";
public static final String ROADM = "roadm";
public static final String ENDSTATION = "endstation";
public static final String ROUTER = "router";
public static final String BGP_SPEAKER = "bgpSpeaker";
+ public static final String MICROWAVE = "microwave";
public static final String CHAIN = "chain";
public static final String CROWN = "crown";
+ public static final String LOCK = "lock";
public static final String TOPO = "topo";
public static final String REFRESH = "refresh";
public static final String GARBAGE = "garbage";
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java
index 8df03169..4030abdc 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/TopoJson.java
@@ -37,6 +37,11 @@ public final class TopoJson {
static final String ID = "id";
static final String LABEL = "label";
static final String CSS = "css";
+ static final String BADGE = "badge";
+ static final String STATUS = "status";
+ static final String TXT = "txt";
+ static final String GID = "gid";
+ static final String MSG = "msg";
static final String TITLE = "title";
static final String TYPE = "type";
@@ -97,12 +102,26 @@ public final class TopoJson {
return payload;
}
+ private static ObjectNode json(NodeBadge b) {
+ ObjectNode n = objectNode()
+ .put(STATUS, b.status().code())
+ .put(b.isGlyph() ? GID : TXT, b.text());
+ if (b.message() != null) {
+ n.put(MSG, b.message());
+ }
+ return n;
+ }
+
private static ObjectNode json(DeviceHighlight dh) {
ObjectNode n = objectNode()
.put(ID, dh.elementId());
if (dh.subdued()) {
n.put(SUBDUE, true);
}
+ NodeBadge badge = dh.badge();
+ if (badge != null) {
+ n.set(BADGE, json(badge));
+ }
return n;
}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/NodeBadgeTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/NodeBadgeTest.java
new file mode 100644
index 00000000..c8243695
--- /dev/null
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/NodeBadgeTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 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.ui.topo;
+
+import org.junit.Test;
+import org.onosproject.ui.topo.NodeBadge.Status;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit tests for {@link NodeBadge}.
+ */
+public class NodeBadgeTest {
+
+ private static final String MSG = "a msg";
+ private static final String TXT = "text";
+ private static final String GID = "glyph-id";
+ private static final int NUM = 42;
+ private static final String NUM_STR = Integer.toString(NUM);
+
+ private static final String WR_S = "wrong status";
+ private static final String WR_B = "wrong boolean";
+ private static final String WR_T = "wrong text";
+ private static final String WR_M = "wrong message";
+ private static final String WR_SF = "wrong string format";
+
+ private NodeBadge badge;
+
+ private void checkFields(NodeBadge b, Status s, boolean g,
+ String txt, String msg) {
+ assertEquals(WR_S, s, b.status());
+ assertEquals(WR_B, g, b.isGlyph());
+ assertEquals(WR_T, txt, b.text());
+ assertEquals(WR_M, msg, b.message());
+ }
+
+ @Test
+ public void badgeTypes() {
+ assertEquals(WR_SF, "i", Status.INFO.code());
+ assertEquals(WR_SF, "w", Status.WARN.code());
+ assertEquals(WR_SF, "e", Status.ERROR.code());
+ assertEquals("unexpected size", 3, Status.values().length);
+ }
+
+ @Test
+ public void textOnly() {
+ badge = NodeBadge.text(TXT);
+ checkFields(badge, Status.INFO, false, TXT, null);
+ }
+
+ @Test
+ public void glyphOnly() {
+ badge = NodeBadge.glyph(GID);
+ checkFields(badge, Status.INFO, true, GID, null);
+ }
+
+ @Test
+ public void numberOnly() {
+ badge = NodeBadge.number(NUM);
+ checkFields(badge, Status.INFO, false, NUM_STR, null);
+ }
+
+ @Test
+ public void textInfo() {
+ badge = NodeBadge.text(Status.INFO, TXT);
+ checkFields(badge, Status.INFO, false, TXT, null);
+ }
+
+ @Test
+ public void glyphWarn() {
+ badge = NodeBadge.glyph(Status.WARN, GID);
+ checkFields(badge, Status.WARN, true, GID, null);
+ }
+
+ @Test
+ public void numberError() {
+ badge = NodeBadge.number(Status.ERROR, NUM);
+ checkFields(badge, Status.ERROR, false, NUM_STR, null);
+ }
+
+ @Test
+ public void textInfoMsg() {
+ badge = NodeBadge.text(Status.INFO, TXT, MSG);
+ checkFields(badge, Status.INFO, false, TXT, MSG);
+ }
+
+ @Test
+ public void glyphWarnMsg() {
+ badge = NodeBadge.glyph(Status.WARN, GID, MSG);
+ checkFields(badge, Status.WARN, true, GID, MSG);
+ }
+
+ @Test
+ public void numberErrorMsg() {
+ badge = NodeBadge.number(Status.ERROR, NUM, MSG);
+ checkFields(badge, Status.ERROR, false, NUM_STR, MSG);
+ }
+}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/TopoJsonTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/TopoJsonTest.java
index ac0051cd..50aabf8e 100644
--- a/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/TopoJsonTest.java
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/TopoJsonTest.java
@@ -21,14 +21,22 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;
import org.onosproject.ui.JsonUtils;
import org.onosproject.ui.topo.Highlights.Amount;
+import org.onosproject.ui.topo.NodeBadge.Status;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
/**
* Unit tests for {@link TopoJson}.
*/
public class TopoJsonTest {
+ private static final String DEV1 = "device-1";
+ private static final String DEV2 = "device-2";
+ private static final String SOME_MSG = "Hello there";
+ private static final String GID = "glyph-ID";
+
private ObjectNode payload;
private void checkArrayLength(String key, int expLen) {
@@ -68,4 +76,42 @@ public class TopoJsonTest {
String subdue = JsonUtils.string(payload, TopoJson.SUBDUE);
assertEquals("not max", "max", subdue);
}
+
+ @Test
+ public void badgedDevice() {
+ Highlights h = new Highlights();
+ DeviceHighlight dh = new DeviceHighlight(DEV1);
+ dh.setBadge(NodeBadge.number(7));
+ h.add(dh);
+
+ dh = new DeviceHighlight(DEV2);
+ dh.setBadge(NodeBadge.glyph(Status.WARN, GID, SOME_MSG));
+ h.add(dh);
+
+ payload = TopoJson.json(h);
+// System.out.println(payload);
+
+ // dig into the payload, and verify the badges are set on the devices
+ ArrayNode a = (ArrayNode) payload.get(TopoJson.DEVICES);
+
+ ObjectNode d = (ObjectNode) a.get(0);
+ assertEquals("wrong device id", DEV1, d.get(TopoJson.ID).asText());
+
+ ObjectNode b = (ObjectNode) d.get(TopoJson.BADGE);
+ assertNotNull("missing badge", b);
+ assertEquals("wrong status code", "i", b.get(TopoJson.STATUS).asText());
+ assertEquals("wrong text", "7", b.get(TopoJson.TXT).asText());
+ assertNull("glyph?", b.get(TopoJson.GID));
+ assertNull("msg?", b.get(TopoJson.MSG));
+
+ d = (ObjectNode) a.get(1);
+ assertEquals("wrong device id", DEV2, d.get(TopoJson.ID).asText());
+
+ b = (ObjectNode) d.get(TopoJson.BADGE);
+ assertNotNull("missing badge", b);
+ assertEquals("wrong status code", "w", b.get(TopoJson.STATUS).asText());
+ assertNull("text?", b.get(TopoJson.TXT));
+ assertEquals("wrong text", GID, b.get(TopoJson.GID).asText());
+ assertEquals("wrong message", SOME_MSG, b.get(TopoJson.MSG).asText());
+ }
}
diff --git a/framework/src/onos/docs/internal-apps b/framework/src/onos/docs/internal-apps
index 71aacd03..c930c05f 100644
--- a/framework/src/onos/docs/internal-apps
+++ b/framework/src/onos/docs/internal-apps
@@ -27,4 +27,5 @@ org.onosproject.vtn*
org.onosproject.cord*
org.onosproject.mcast*
org.onosproject.mfwd*
+org.onosproject.mlb*
org.onosproject.igmp.impl
diff --git a/framework/src/onos/docs/internal-netconf b/framework/src/onos/docs/internal-netconf
index 40c159f4..161ad9cc 100644
--- a/framework/src/onos/docs/internal-netconf
+++ b/framework/src/onos/docs/internal-netconf
@@ -1 +1,2 @@
+org.onosproject.netconf*
org.onosproject.provider.netconf*
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java
index f72bde09..c9ef451e 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java
@@ -169,7 +169,7 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline {
}));
}
- private void processAclTable() {
+ protected void processAclTable() {
//table miss entry - catch all to executed action-set
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java
index eebb2e22..c735af3f 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OLTPipeline.java
@@ -30,7 +30,6 @@ import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
-import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowRule;
@@ -86,13 +85,13 @@ public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
flowRuleService = serviceDirectory.get(FlowRuleService.class);
coreService = serviceDirectory.get(CoreService.class);
- try {
+ /*try {
DeviceProviderService providerService = registry.register(provider);
providerService.deviceConnected(deviceId,
description(deviceId, DEVICE, OLT));
} finally {
registry.unregister(provider);
- }
+ }*/
appId = coreService.registerApplication(
"org.onosproject.driver.OLTPipeline");
@@ -109,12 +108,12 @@ public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
PacketPriority.CONTROL.priorityValue(),
appId, 0, true, null);
- flowRuleService.applyFlowRules(flowRule);
+ //flowRuleService.applyFlowRules(flowRule);
}
@Override
public void filter(FilteringObjective filter) {
- throw new UnsupportedOperationException("Single table does not filter.");
+ throw new UnsupportedOperationException("OLT does not filter.");
}
@Override
@@ -140,19 +139,11 @@ public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
TrafficSelector selector = fwd.selector();
TrafficTreatment treatment = fwd.treatment();
- if ((fwd.treatment().deferred().size() == 0) &&
- (fwd.treatment().immediate().size() == 0) &&
- (fwd.treatment().tableTransition() == null) &&
- (!fwd.treatment().clearedDeferred())) {
- TrafficTreatment.Builder flowTreatment = DefaultTrafficTreatment.builder();
- flowTreatment.add(Instructions.createDrop());
- treatment = flowTreatment.build();
- }
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
.forDevice(deviceId)
.withSelector(selector)
- .withTreatment(fwd.treatment())
+ .withTreatment(treatment)
.fromApp(fwd.appId())
.withPriority(fwd.priority());
@@ -162,9 +153,7 @@ public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
ruleBuilder.makeTemporary(fwd.timeout());
}
-
switch (fwd.op()) {
-
case ADD:
flowBuilder.add(ruleBuilder.build());
break;
@@ -190,16 +179,16 @@ public class OLTPipeline extends AbstractHandlerBehaviour implements Pipeliner {
}
}
}));
-
}
@Override
public void next(NextObjective nextObjective) {
- throw new UnsupportedOperationException("Single table does not next hop.");
+ throw new UnsupportedOperationException("OLT does not next hop.");
}
/**
* Build a device description.
+ *
* @param deviceId a deviceId
* @param key the key of the annotation
* @param value the value for the annotation
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
index 270e76a2..5d098390 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
@@ -21,12 +21,14 @@ import java.util.Collection;
import java.util.Collections;
import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.behaviour.PipelinerContext;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleOperations;
@@ -56,11 +58,13 @@ public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
private ServiceDirectory serviceDirectory;
protected FlowObjectiveStore flowObjectiveStore;
protected DeviceId deviceId;
+ protected ApplicationId appId;
protected FlowRuleService flowRuleService;
protected DeviceService deviceService;
private static final int TIME_OUT = 0;
- private static final int MAC_TABLE = 40;
- private static final int PORT_TABLE = 0;
+ private static final int CLASSIFIER_TABLE = 0;
+ private static final int MAC_TABLE = 50;
+ private static final int TABLE_MISS_PRIORITY = 0;
@Override
public void init(DeviceId deviceId, PipelinerContext context) {
@@ -71,9 +75,9 @@ public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
coreService = serviceDirectory.get(CoreService.class);
flowRuleService = serviceDirectory.get(FlowRuleService.class);
flowObjectiveStore = context.store();
- coreService
+ appId = coreService
.registerApplication("org.onosproject.driver.OpenVSwitchPipeline");
-
+ initializePipeline();
}
@Override
@@ -125,6 +129,60 @@ public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
super.next(nextObjective);
}
+ private void initializePipeline() {
+ processClassifierTable(true);
+ processMacTable(true);
+ }
+
+ private void processClassifierTable(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.transition(MAC_TABLE);
+
+ FlowRule rule;
+ rule = DefaultFlowRule.builder().forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(TABLE_MISS_PRIORITY).fromApp(appId)
+ .makePermanent().forTable(CLASSIFIER_TABLE).build();
+
+ applyRules(install, rule);
+ }
+
+ private void processMacTable(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.drop();
+
+ FlowRule rule;
+ rule = DefaultFlowRule.builder().forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(TABLE_MISS_PRIORITY).fromApp(appId)
+ .makePermanent().forTable(MAC_TABLE).build();
+
+ applyRules(install, rule);
+ }
+
+ private void applyRules(boolean install, FlowRule rule) {
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+
+ ops = install ? ops.add(rule) : ops.remove(rule);
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("ONOSW provisioned " + rule.tableId() + " table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("ONOSW failed to provision " + rule.tableId() + " table");
+ }
+ }));
+ }
+
private Collection<FlowRule> processForward(ForwardingObjective fwd) {
switch (fwd.flag()) {
case SPECIFIC:
@@ -164,7 +222,7 @@ public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
tb.allInstructions().forEach(t -> newTraffic.add(t));
newTraffic.transition(MAC_TABLE);
ruleBuilder.withTreatment(newTraffic.build());
- ruleBuilder.forTable(PORT_TABLE);
+ ruleBuilder.forTable(CLASSIFIER_TABLE);
}
return Collections.singletonList(ruleBuilder.build());
}
diff --git a/framework/src/onos/etc/init/onos.conf b/framework/src/onos/etc/init/onos.conf
deleted file mode 100644
index 779df905..00000000
--- a/framework/src/onos/etc/init/onos.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-description "Open Network Operating System"
-author "ON.Lab"
-
-start on (net-device-up
- and local-filesystems
- and runlevel [2345])
-stop on runlevel [016]
-
-console output
-kill timeout 60
-respawn
-
-env LANG=en_US.UTF-8
-
-pre-start script
- [ -f /opt/onos/options ] && . /opt/onos/options
- ONOS_USER=${ONOS_USER:-root}
-
- # Ensure that the environment is initialized
- [ -d /opt/onos ] && mkdir /opt/onos/var 2>/dev/null && chown $ONOS_USER.$ONOS_USER /opt/onos/var
- [ -d /opt/onos ] && mkdir /opt/onos/config 2>/dev/null && chown $ONOS_USER.$ONOS_USER /opt/onos/config
- # TODO make karaf version configurable
- [ -d /opt/onos ] && [ ! -h /opt/onos/log ] \
- && ln -s /opt/onos/apache-karaf-3.0.3/data/log /opt/onos/log || :
-end script
-
-pre-stop script
- /opt/onos/bin/onos halt 2>>/opt/onos/var/stderr.log
- sleep 1
-end script
-
-script
- [ -f /opt/onos/options ] && . /opt/onos/options
- start-stop-daemon --signal INT --start --chuid ${ONOS_USER:-root} \
- --exec /opt/onos/bin/onos-service -- ${ONOS_OPTS:-server} \
- >/opt/onos/var/stdout.log 2>/opt/onos/var/stderr.log
-end script
diff --git a/framework/src/onos/etc/org.ops4j.pax.url.mvn.cfg b/framework/src/onos/etc/org.ops4j.pax.url.mvn.cfg
deleted file mode 100644
index 15167a3b..00000000
--- a/framework/src/onos/etc/org.ops4j.pax.url.mvn.cfg
+++ /dev/null
@@ -1,101 +0,0 @@
-################################################################################
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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.
-#
-################################################################################
-
-#
-# If set to true, the following property will not allow any certificate to be used
-# when accessing Maven repositories through SSL
-#
-#org.ops4j.pax.url.mvn.certificateCheck=
-
-#
-# Path to the local Maven settings file.
-# The repositories defined in this file will be automatically added to the list
-# of default repositories if the 'org.ops4j.pax.url.mvn.repositories' property
-# below is not set.
-# The following locations are checked for the existence of the settings.xml file
-# * 1. looks for the specified url
-# * 2. if not found looks for ${user.home}/.m2/settings.xml
-# * 3. if not found looks for ${maven.home}/conf/settings.xml
-# * 4. if not found looks for ${M2_HOME}/conf/settings.xml
-#
-#org.ops4j.pax.url.mvn.settings=
-
-#
-# Path to the local Maven repository which is used to avoid downloading
-# artifacts when they already exist locally.
-# The value of this property will be extracted from the settings.xml file
-# above, or defaulted to:
-# System.getProperty( "user.home" ) + "/.m2/repository"
-#
-#org.ops4j.pax.url.mvn.localRepository=
-
-#
-# Default this to false. It's just weird to use undocumented repos
-#
-org.ops4j.pax.url.mvn.useFallbackRepositories=false
-
-#
-# Uncomment if you don't wanna use the proxy settings
-# from the Maven conf/settings.xml file
-#
-# org.ops4j.pax.url.mvn.proxySupport=false
-
-#
-# Comma separated list of repositories scanned when resolving an artifact.
-# Those repositories will be checked before iterating through the
-# below list of repositories and even before the local repository
-# A repository url can be appended with zero or more of the following flags:
-# @snapshots : the repository contains snaphots
-# @noreleases : the repository does not contain any released artifacts
-#
-# The following property value will add the system folder as a repo.
-#
-org.ops4j.pax.url.mvn.defaultRepositories=\
- file:${karaf.home}/${karaf.default.repository}@id=system.repository@snapshots,\
- file:${karaf.data}/kar@id=kar.repository@multi@snapshots
-
-# Use the default local repo (e.g.~/.m2/repository) as a "remote" repo
-#org.ops4j.pax.url.mvn.defaultLocalRepoAsRemote=false
-
-#
-# Comma separated list of repositories scanned when resolving an artifact.
-# The default list includes the following repositories:
-# http://repo1.maven.org/maven2@id=central
-# http://repository.springsource.com/maven/bundles/release@id=spring.ebr
-# http://repository.springsource.com/maven/bundles/external@id=spring.ebr.external
-# http://zodiac.springsource.com/maven/bundles/release@id=gemini
-# http://repository.apache.org/content/groups/snapshots-group@id=apache@snapshots@noreleases
-# https://oss.sonatype.org/content/repositories/snapshots@id=sonatype.snapshots.deploy@snapshots@noreleases
-# https://oss.sonatype.org/content/repositories/ops4j-snapshots@id=ops4j.sonatype.snapshots.deploy@snapshots@noreleases
-# To add repositories to the default ones, prepend '+' to the list of repositories
-# to add.
-# A repository url can be appended with zero or more of the following flags:
-# @snapshots : the repository contains snapshots
-# @noreleases : the repository does not contain any released artifacts
-# @id=repository.id : the id for the repository, just like in the settings.xml this is optional but recommended
-#
-org.ops4j.pax.url.mvn.repositories= \
- ${org.ops4j.pax.url.mvn.defaultRepositories}, \
- http://repo1.maven.org/maven2@id=central, \
- http://repository.springsource.com/maven/bundles/release@id=spring.ebr.release, \
- http://repository.springsource.com/maven/bundles/external@id=spring.ebr.external, \
- http://zodiac.springsource.com/maven/bundles/release@id=gemini, \
- http://repository.apache.org/content/groups/snapshots-group@id=apache@snapshots@noreleases, \
- https://oss.sonatype.org/content/repositories/snapshots@id=sonatype.snapshots.deploy@snapshots@noreleases, \
- https://oss.sonatype.org/content/repositories/ops4j-snapshots@id=ops4j.sonatype.snapshots.deploy@snapshots@noreleases
diff --git a/framework/src/onos/etc/org.ops4j.pax.web.cfg b/framework/src/onos/etc/org.ops4j.pax.web.cfg
deleted file mode 100644
index c8fb3b3d..00000000
--- a/framework/src/onos/etc/org.ops4j.pax.web.cfg
+++ /dev/null
@@ -1,12 +0,0 @@
-org.osgi.service.http.port=8181
-org.osgi.service.http.port.secure=8443
-
-org.osgi.service.http.enabled=true
-org.osgi.service.http.secure.enabled=false
-
-org.ops4j.pax.web.ssl.keystore=etc/keystore
-org.ops4j.pax.web.ssl.password=OBF:1xtn1w1u1uob1xtv1y7z1xtn1unn1w1o1xtv
-org.ops4j.pax.web.ssl.keypassword=OBF:1xtn1w1u1uob1xtv1y7z1xtn1unn1w1o1xtv
-
-org.ops4j.pax.web.session.url=none
-org.ops4j.pax.web.config.file=./etc/jetty.xml
diff --git a/framework/src/onos/etc/samples/linkGraph.cfg b/framework/src/onos/etc/samples/linkGraph.cfg
deleted file mode 100644
index 41ce5bdc..00000000
--- a/framework/src/onos/etc/samples/linkGraph.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-# NullLinkProvider topology description (config file).
-#
-# Dot-style topology graph. Each controller's topology begins with
-#
-# graph <node ID>, followed by a list of links between braces.
-#
-# The links are either bidirectional (--) or directed (->). The directed
-# edges are used to connect together Null devices of different controllers.
-# The endpoint has the format:
-#
-# devID:port:NodeId
-#
-# The NodeId is only added if the destination is another node's device.
-#
-graph 192.168.56.20 {
- 0:0 -- 1:0
- 1:1 -> 0:0:192.168.56.30
- 1:2 -- 2:0
- 2:1 -> 1:0:192.168.56.30
-}
-graph 192.168.56.30 {
- 0:0 -> 1:1:192.168.56.20
- 0:1 -- 1:1
- 1:0 -> 2:1:192.168.56.20
- 1:2 -- 2:0
-}
-# Bugs: Comments cannot be appended to a line to be read.
diff --git a/framework/src/onos/etc/samples/org.onosproject.fwd.ReactiveForwarding.cfg b/framework/src/onos/etc/samples/org.onosproject.fwd.ReactiveForwarding.cfg
deleted file mode 100644
index 4befc706..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.fwd.ReactiveForwarding.cfg
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# Sample configuration for onos-app-fwd.
-#
-
-#
-# Reactive flows default matching is InPort, Src MAC, Dst MAC and EtherType fields
-#
-
-#
-# Enable packet-out only forwarding.
-# This flag affects to both IPv4 and IPv6.
-#
-# packetOutOnly = true
-
-#
-# Enable forwarding of the first packet by using OFPP_TABLE port in the
-# PacketOut message instead of sending it directly to the switch port
-#
-# packetOutOfppTable = true
-
-#
-# Timeout of reactively installed flows (in seconds).
-# Default is 10 sec
-#
-# flowTimeout = 10
-
-#
-# Priority of reactively installed flows
-#
-# flowPriority = 10
-
-#
-# Enable IPv6 forwarding.
-#
-# ipv6Forwarding = true
-
-#
-# Flows matching destination MAC only - as legacy L2 switches
-# - This option overrides all other options below
-#
-# matchDstMacOnly = true
-
-#
-# Matching of VLAN ID in Ethernet header
-#
-# matchVlanId = true
-
-#
-# Matching of IPv4 addresses and Protocol field
-# - must be enabled to match IPv4 DSCP, TCP/UDP ports and ICMP type/code
-#
-# matchIpv4Address = true
-
-#
-# Matching of IPv4 DSCP and ECN fields
-#
-# matchIpv4Dscp = true
-
-#
-# Matching of IPv6 addresses and Next-Header field
-# - must be enabled to match IPv6 Flow Label, TCP/UDP ports and ICMP type/code
-#
-# matchIpv6Address = true
-
-#
-# Matching of IPv6 Flow Label
-#
-# matchIpv6FlowLabel = true
-
-#
-# Matching of TCP/UDP ports for IPv4 and IPv6
-#
-# matchTcpUdpPorts = true
-
-#
-# Matching of ICMP Type and Code fields for IPv4 and IPv6
-#
-# matchIcmpFields = true
-
diff --git a/framework/src/onos/etc/samples/org.onosproject.provider.host.impl.HostLocationProvider.cfg b/framework/src/onos/etc/samples/org.onosproject.provider.host.impl.HostLocationProvider.cfg
deleted file mode 100644
index 6d3a50d9..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.provider.host.impl.HostLocationProvider.cfg
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Sample configuration for Host Location Provider
-#
-
-#
-# Enable host removal on port/device down events.
-#
-# hostRemovalEnabled = true
-
-#
-# Enable using IPv6 Neighbor Discovery by the Host Location Provider.
-#
-# ipv6NeighborDiscovery = true
diff --git a/framework/src/onos/etc/samples/org.onosproject.provider.lldp.impl.LLDPLinkProvider.cfg b/framework/src/onos/etc/samples/org.onosproject.provider.lldp.impl.LLDPLinkProvider.cfg
deleted file mode 100644
index 6eb39a11..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.provider.lldp.impl.LLDPLinkProvider.cfg
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Sample configuration for link discovery
-#
-
-#
-# Disable Link Dicovery Permanently (Note: changing this property at runtime will have NO effect)
-# WARNING: This should only be used for special projects like bgprouter, where ONOS is controlling
-# a single switch
-#
-#disableLinkDiscovery = true
-
-#
-# Enable Broadcast Discovery Protocol (EthType=0x8942)
-#
-#useBDDP = false
-
-#
-# Disable LLDP's received from specific devices
-# Details of the devices are in the file configured below
-#
-#lldpSuppression = ../config/lldp_suppresion.json
diff --git a/framework/src/onos/etc/samples/org.onosproject.provider.netconf.device.impl.NetconfDeviceProvider.cfg b/framework/src/onos/etc/samples/org.onosproject.provider.netconf.device.impl.NetconfDeviceProvider.cfg
deleted file mode 100644
index 30ed0c26..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.provider.netconf.device.impl.NetconfDeviceProvider.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Instance-specific configurations, in this case, the number of
-# devices per node.
-#
-devConfigs = cisco:cisco@192.168.56.20:2022:inactive,sdn:rocks@192.168.56.30:22:inactive
-
-#
-# Number of ports per device. This is global to all devices
-# on all instances.
-#
-# numPorts = 8
diff --git a/framework/src/onos/etc/samples/org.onosproject.provider.nil.device.impl.NullDeviceProvider.cfg b/framework/src/onos/etc/samples/org.onosproject.provider.nil.device.impl.NullDeviceProvider.cfg
deleted file mode 100644
index 194bf037..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.provider.nil.device.impl.NullDeviceProvider.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Instance-specific configurations, in this case, the number of
-# devices per node.
-#
-devConfigs = 192.168.56.20:3,192.168.56.30:3
-
-#
-# Number of ports per device. This is global to all devices
-# on all instances.
-#
-# numPorts = 8
diff --git a/framework/src/onos/etc/samples/org.onosproject.provider.nil.link.impl.NullLinkProvider.cfg b/framework/src/onos/etc/samples/org.onosproject.provider.nil.link.impl.NullLinkProvider.cfg
deleted file mode 100644
index ef72b1ee..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.provider.nil.link.impl.NullLinkProvider.cfg
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Sample configurations for the NullLinkProvider.
-#
-
-#
-# If enabled, sets the time between LinkEvent generation,
-# in microseconds.
-#
-
-#eventRate = 1000000
-
-#
-# If enabled, points to the full path to the topology file.
-#
-
-#cfgFile = /tmp/foo.cfg
diff --git a/framework/src/onos/etc/samples/org.onosproject.provider.nil.packet.impl.NullPacketProvider.cfg b/framework/src/onos/etc/samples/org.onosproject.provider.nil.packet.impl.NullPacketProvider.cfg
deleted file mode 100644
index db4342c0..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.provider.nil.packet.impl.NullPacketProvider.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Uncomment and tweak to tune the rate of Packet events (per second)
-#
-# pktRate = 100
diff --git a/framework/src/onos/etc/samples/org.onosproject.proxyarp.ProxyArp.cfg b/framework/src/onos/etc/samples/org.onosproject.proxyarp.ProxyArp.cfg
deleted file mode 100644
index 108de136..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.proxyarp.ProxyArp.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Sample configuration for onos-app-proxyarp.
-#
-
-#
-# Enable IPv6 Neighbor Discovery.
-#
-# ipv6NeighborDiscovery = true
diff --git a/framework/src/onos/etc/samples/org.onosproject.routing.bgp.BgpSessionManager.cfg b/framework/src/onos/etc/samples/org.onosproject.routing.bgp.BgpSessionManager.cfg
deleted file mode 100644
index fbcc13f9..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.routing.bgp.BgpSessionManager.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Sample configuration for onos-app-sdnip.
-#
-
-#
-# The port number that SDN-IP listens for incoming BGP connections on.
-#
-# bgpPort=2000 \ No newline at end of file
diff --git a/framework/src/onos/etc/samples/org.onosproject.xos.XOS.cfg b/framework/src/onos/etc/samples/org.onosproject.xos.XOS.cfg
deleted file mode 100644
index e69de29b..00000000
--- a/framework/src/onos/etc/samples/org.onosproject.xos.XOS.cfg
+++ /dev/null
diff --git a/framework/src/onos/etc/users.properties b/framework/src/onos/etc/users.properties
deleted file mode 100644
index 9f7a2667..00000000
--- a/framework/src/onos/etc/users.properties
+++ /dev/null
@@ -1,34 +0,0 @@
-################################################################################
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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 file contains the users, groups, and roles.
-# Each line has to be of the format:
-#
-# USER=PASSWORD,ROLE1,ROLE2,...
-# USER=PASSWORD,_g_:GROUP,...
-# _g_\:GROUP=ROLE1,ROLE2,...
-#
-# All users, grousp, and roles entered in this file are available after Karaf startup
-# and modifiable via the JAAS command group. These users reside in a JAAS domain
-# with the name "karaf".
-#
-karaf = karaf,_g_:admingroup
-onos = rocks,_g_:admingroup
-_g_\:admingroup = group,admin,manager,viewer,webconsole
diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java
index 592336c2..9f2d4105 100644
--- a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java
+++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java
@@ -39,7 +39,6 @@ public class InterfaceConfig extends Config<ConnectPoint> {
public static final String MAC = "mac";
public static final String VLAN = "vlan";
- public static final String MAC_MISSING_ERROR = "Must have a MAC address for each interface";
public static final String CONFIG_VALUE_ERROR = "Error parsing config value";
/**
@@ -55,15 +54,12 @@ public class InterfaceConfig extends Config<ConnectPoint> {
for (JsonNode intfNode : array) {
Set<InterfaceIpAddress> ips = getIps(intfNode);
- if (intfNode.path(MAC).isMissingNode()) {
- throw new ConfigException(MAC_MISSING_ERROR);
- }
-
- MacAddress mac = MacAddress.valueOf(intfNode.path(MAC).asText());
+ String mac = intfNode.path(MAC).asText();
+ MacAddress macAddr = mac.isEmpty() ? null : MacAddress.valueOf(mac);
VlanId vlan = getVlan(intfNode);
- interfaces.add(new Interface(subject, ips, mac, vlan));
+ interfaces.add(new Interface(subject, ips, macAddr, vlan));
}
} catch (IllegalArgumentException e) {
throw new ConfigException(CONFIG_VALUE_ERROR, e);
@@ -79,7 +75,10 @@ public class InterfaceConfig extends Config<ConnectPoint> {
*/
public void addInterface(Interface intf) {
ObjectNode intfNode = array.addObject();
- intfNode.put(MAC, intf.mac().toString());
+
+ if (intf.mac() != null) {
+ intfNode.put(MAC, intf.mac().toString());
+ }
if (!intf.ipAddresses().isEmpty()) {
intfNode.set(IPS, putIps(intf.ipAddresses()));
diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java
index 69d14bce..b9d3eadf 100644
--- a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java
+++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java
@@ -30,7 +30,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* An Interface maps network configuration information (such as addresses and
- * vlans) to a port in the network.
+ * vlans) to a port in the network. This is considered a L2/L3 network
+ * interface.
*/
@Beta
public class Interface {
@@ -51,9 +52,9 @@ public class Interface {
Set<InterfaceIpAddress> ipAddresses,
MacAddress macAddress, VlanId vlan) {
this.connectPoint = checkNotNull(connectPoint);
- this.ipAddresses = Sets.newHashSet(checkNotNull(ipAddresses));
- this.macAddress = checkNotNull(macAddress);
- this.vlan = checkNotNull(vlan);
+ this.ipAddresses = ipAddresses == null ? Sets.newHashSet() : ipAddresses;
+ this.macAddress = macAddress == null ? MacAddress.NONE : macAddress;
+ this.vlan = vlan == null ? VlanId.NONE : vlan;
}
/**
diff --git a/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java b/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
index 1b6810be..51a2ce42 100644
--- a/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
+++ b/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
@@ -30,6 +30,14 @@ public interface OpenFlowSwitch {
/**
* Writes the message to the driver.
*
+ * Note:
+ * Calling {@link #sendMsg(OFMessage)} does NOT guarantee the messages to be
+ * transmitted on the wire in order, especially during role transition.
+ * The messages may be reordered at the switch side.
+ *
+ * Calling {@link #sendMsg(List)} guarantee the messages inside the list
+ * to be transmitted on the wire in order.
+ *
* @param msg the message to write
*/
void sendMsg(OFMessage msg);
diff --git a/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index 2f6357bd..2c19837e 100644
--- a/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -79,6 +79,8 @@ public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
protected OFFeaturesReply features;
protected OFDescStatsReply desc;
+ List<OFMessage> messagesPendingMastership;
+
@Override
public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
this.dpid = dpid;
@@ -96,16 +98,21 @@ public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
}
@Override
- public void sendMsg(OFMessage m) {
- if (role == RoleState.MASTER && channel.isConnected()) {
- channel.write(Collections.singletonList(m));
- }
+ public void sendMsg(OFMessage msg) {
+ this.sendMsg(Collections.singletonList(msg));
}
@Override
public final void sendMsg(List<OFMessage> msgs) {
if (role == RoleState.MASTER && channel.isConnected()) {
channel.write(msgs);
+ } else if (messagesPendingMastership != null) {
+ messagesPendingMastership.addAll(msgs);
+ log.debug("Enqueue message for switch {}. queue size after is {}",
+ dpid, messagesPendingMastership.size());
+ } else {
+ log.warn("Dropping message for switch {} (role: {}, connected: {}): {}",
+ dpid, role, channel.isConnected(), msgs);
}
}
@@ -232,6 +239,12 @@ public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
@Override
public final void transitionToMasterSwitch() {
this.agent.transitionToMasterSwitch(dpid);
+ if (messagesPendingMastership != null) {
+ this.sendMsg(messagesPendingMastership);
+ log.debug("Sending {} pending messages to switch {}",
+ messagesPendingMastership.size(), dpid);
+ messagesPendingMastership = null;
+ }
}
@Override
@@ -278,6 +291,11 @@ public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
log.debug("Sending role {} to switch {}", role, getStringId());
if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
this.role = role;
+ } else {
+ if (messagesPendingMastership == null) {
+ log.debug("Initializing new queue for switch {}", dpid);
+ messagesPendingMastership = new ArrayList<>();
+ }
}
} else {
this.role = role;
diff --git a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java
index df7865d3..4c1b16fe 100644
--- a/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java
+++ b/framework/src/onos/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFMessageEncoder.java
@@ -25,7 +25,6 @@ import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import org.projectfloodlight.openflow.protocol.OFMessage;
-
/**
* Encode an openflow message for output into a ChannelBuffer, for use in a
* netty pipeline.
@@ -50,7 +49,9 @@ public class OFMessageEncoder extends OneToOneEncoder {
ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
for (OFMessage ofm : msglist) {
- ofm.writeTo(buf);
+ if (ofm != null) {
+ ofm.writeTo(buf);
+ }
}
return buf;
}
diff --git a/framework/src/onos/opt/onos/.empty b/framework/src/onos/opt/onos/.empty
deleted file mode 100644
index e69de29b..00000000
--- a/framework/src/onos/opt/onos/.empty
+++ /dev/null
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index 2575a256..3280ad34 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -175,14 +175,19 @@ public class DefaultOvsdbClient
*
* @param dbName the ovsdb database name
* @param tableName the ovsdb table name
- * @return ovsRowStore, empty if row store is find
+ * @return ovsRowStore, empty store if no rows exist in the table
*/
private OvsdbRowStore getRowStore(String dbName, String tableName) {
OvsdbTableStore tableStore = getTableStore(dbName);
if (tableStore == null) {
return null;
}
- return tableStore.getRows(tableName);
+
+ OvsdbRowStore rowStore = tableStore.getRows(tableName);
+ if (rowStore == null) {
+ rowStore = new OvsdbRowStore();
+ }
+ return rowStore;
}
/**
diff --git a/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
index 329df20b..a7e334f4 100644
--- a/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -319,6 +319,9 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
}
DeviceId did = deviceId(uri(dpid));
OpenFlowSwitch sw = controller.getSwitch(dpid);
+ if (sw == null) {
+ return;
+ }
ChassisId cId = new ChassisId(dpid.value());
@@ -339,9 +342,14 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
providerService.updatePorts(did, buildPortDescriptions(sw));
PortStatsCollector psc =
- new PortStatsCollector(controller.getSwitch(dpid), portStatsPollFrequency);
+ new PortStatsCollector(sw, portStatsPollFrequency);
psc.start();
collectors.put(dpid, psc);
+
+ //figure out race condition for collectors.remove() and collectors.put()
+ if (controller.getSwitch(dpid) == null) {
+ switchRemoved(dpid);
+ }
}
@Override
@@ -364,6 +372,9 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
}
DeviceId did = deviceId(uri(dpid));
OpenFlowSwitch sw = controller.getSwitch(dpid);
+ if (sw == null) {
+ return;
+ }
providerService.updatePorts(did, buildPortDescriptions(sw));
}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index cf918605..1039d049 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -55,6 +55,7 @@ import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
@@ -333,6 +334,10 @@ public class FlowEntryBuilder {
OFActionGroup group = (OFActionGroup) act;
builder.group(new DefaultGroupId(group.getGroup().getGroupNumber()));
break;
+ case SET_QUEUE:
+ OFActionSetQueue setQueue = (OFActionSetQueue) act;
+ builder.setQueue(setQueue.getQueueId());
+ break;
case STRIP_VLAN:
case POP_VLAN:
builder.popVlan();
@@ -350,7 +355,6 @@ public class FlowEntryBuilder {
case SET_NW_ECN:
case SET_NW_TOS:
case SET_NW_TTL:
- case SET_QUEUE:
case ENQUEUE:
default:
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index cc265758..64b4360a 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -26,6 +26,7 @@ import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
@@ -50,6 +51,7 @@ import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
@@ -244,6 +246,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.setGroup(OFGroup.of(group.groupId().id()));
actions.add(groupBuilder.build());
break;
+ case QUEUE:
+ SetQueueInstruction queue = (SetQueueInstruction) i;
+ OFActionSetQueue.Builder queueBuilder = factory().actions().buildSetQueue()
+ .setQueueId(queue.queueId());
+ actions.add(queueBuilder.build());
+ break;
case TABLE:
//FIXME: should not occur here.
tableFound = true;
diff --git a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
index 78650fe6..8acf08ee 100644
--- a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
+++ b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
@@ -334,12 +334,20 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
@Override
public void switchAdded(Dpid dpid) {
OpenFlowSwitch sw = controller.getSwitch(dpid);
+ if (sw == null) {
+ return;
+ }
if (isGroupSupported(sw)) {
GroupStatsCollector gsc = new GroupStatsCollector(
controller.getSwitch(dpid), POLL_INTERVAL);
gsc.start();
collectors.put(dpid, gsc);
}
+
+ //figure out race condition
+ if (controller.getSwitch(dpid) == null) {
+ switchRemoved(dpid);
+ }
}
@Override
diff --git a/framework/src/onos/tools/package/config/samples/network-cfg.json b/framework/src/onos/tools/package/config/samples/network-cfg.json
index c2af8b81..92328479 100644
--- a/framework/src/onos/tools/package/config/samples/network-cfg.json
+++ b/framework/src/onos/tools/package/config/samples/network-cfg.json
@@ -28,8 +28,8 @@
"routerMac" : "00:00:00:00:01:80",
"isEdgeRouter" : true,
"adjacencySids" : [
- { "sid" : 100, "port" : [2, 3] },
- { "sid" : 200, "port" : [4, 5] }
+ { "sid" : 100, "ports" : [2, 3] },
+ { "sid" : 200, "ports" : [4, 5] }
]
}
},
diff --git a/framework/src/onos/tools/package/config/samples/segmentrouting_dell.conf b/framework/src/onos/tools/package/config/samples/segmentrouting_dell.conf
deleted file mode 100644
index be489a65..00000000
--- a/framework/src/onos/tools/package/config/samples/segmentrouting_dell.conf
+++ /dev/null
@@ -1,93 +0,0 @@
-{
- "comment": " Multilayer topology description and configuration",
- "restrictSwitches": true,
- "restrictLinks": true,
-
- "switchConfig":
- [
- { "nodeDpid" : "of:00010001e88b9368", "name": "Dell-R1", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.1/32",
- "routerMac": "00:01:e8:8b:93:6b",
- "nodeSid": 101,
- "isEdgeRouter" : true,
- "subnets": [
- { "portNo": 46, "subnetIp": "10.200.1.1/24" }
- ]
- }
- },
-
- { "nodeDpid": "of:00010001e88b939b", "name": "Dell-R2", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.2/32",
- "routerMac": "00:01:e8:8b:93:9e",
- "nodeSid": 102,
- "isEdgeRouter" : true,
- "subnets": [
- { "portNo": 46, "subnetIp": "10.200.2.1/24" }
- ]
- }
- },
-
- { "nodeDpid": "of:00010001e88b938c", "name": "Dell-R3", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.3/32",
- "routerMac": "00:01:e8:8b:93:8f",
- "nodeSid": 103,
- "isEdgeRouter" : true,
- "subnets": [
- { "portNo": 46, "subnetIp": "10.200.3.1/24" }
- ]
- }
- },
-
- { "nodeDpid": "of:00010001e88b93ad", "name": "Dell-R4", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.4/32",
- "routerMac": "00:01:e8:8b:93:b0",
- "nodeSid": 104,
- "isEdgeRouter" : true,
- "subnets": [
- { "portNo": 46, "subnetIp": "10.200.4.1/24" }
- ]
- }
- },
-
- { "nodeDpid": "of:00010001e88b93bc", "name": "Dell-R5", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.5/32",
- "routerMac": "00:01:e8:8b:93:bf",
- "nodeSid": 105,
- "isEdgeRouter" : false
- }
- },
-
- { "nodeDpid": "of:00010001e88b93c2", "name": "Dell-R6", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.6/32",
- "routerMac": "00:01:e8:8b:93:c5",
- "nodeSid": 106,
- "isEdgeRouter" : false
- }
- },
-
- { "nodeDpid": "of:00010001e88b9398", "name": "Dell-R7", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.7/32",
- "routerMac": "00:01:e8:8b:93:9b",
- "nodeSid": 107,
- "isEdgeRouter": false
- }
- },
-
- { "nodeDpid": "of:00010001e88b27e3", "name": "Dell-R8", "type": "Router_SR", "allowed": true,
- "latitude": 80.80, "longitude": 90.10,
- "params": { "routerIp": "192.168.0.8/32",
- "routerMac": "00:01:e8:8b:27:e6",
- "nodeSid": 108,
- "isEdgeRouter": false
- }
- }
-
- ]
-}
diff --git a/framework/src/onos/tools/test/scenarios/sequential-example.xml b/framework/src/onos/tools/test/scenarios/sequential-example.xml
new file mode 100644
index 00000000..eee32d30
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/sequential-example.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright 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.
+ -->
+<scenario name="example" description="sequential scenario example">
+ <group name="Wrapup">
+ <!-- 'starts' is a comma-separated list of patterns that name steps starting the current iteration of the sequence -->
+ <!-- 'ends' is a comma-separated list of patterns that name steps ending the previous iteration of the sequence -->
+ <!-- In this example each Final-Check-Logs-(N) will become dependent on Fetch-Logs-(N-1), for N > 1 -->
+ <sequential var="${OC#}" starts="Final-Check-Logs-${#}" ends="Fetch-Logs-${#-1}">
+ <step name="Final-Check-Logs-${#}" exec="onos-check-logs ${OC#}"/>
+ <step name="Fetch-Logs-${#}" exec="onos-fetch-logs ${OC#}"
+ cwd="${WORKSPACE}/tmp/stc" requires="~^"/>
+ </sequential>
+ </group>
+</scenario>
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/EthType.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/EthType.java
index 561c9307..b3b79e2c 100644
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/EthType.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/EthType.java
@@ -45,7 +45,7 @@ public class EthType {
private final Deserializer<?> deserializer;
/**
- * Constucts a new ethertype.
+ * Constructs a new ethertype.
*
* @param ethType The actual ethertype
* @param type it's textual representation
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MacAddress.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
index 89cddbae..cb7f2013 100644
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
@@ -22,6 +22,7 @@ import java.util.Arrays;
*/
public class MacAddress {
+ public static final MacAddress NONE = valueOf("a4:23:05:00:00:00");
public static final MacAddress ZERO = valueOf("00:00:00:00:00:00");
public static final MacAddress BROADCAST = valueOf("ff:ff:ff:ff:ff:ff");
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java
index d9a5e83f..e6ef0aed 100755
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java
@@ -43,6 +43,9 @@ public class PIM extends BasePacket {
public static final int PIM_HEADER_LEN = 4;
+ public static final byte ADDRESS_FAMILY_IP4 = 0x1;
+ public static final byte ADDRESS_FAMILY_IP6 = 0x2;
+
public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
new HashMap<>();
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java
index be4ab19a..0db82afb 100644
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java
@@ -17,9 +17,11 @@ package org.onlab.packet.pim;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
-import org.onlab.packet.Ip6Address;
+import org.onlab.packet.PIM;
+
import java.nio.ByteBuffer;
@@ -41,7 +43,7 @@ public class PIMAddrGroup {
* PIM Encoded Group Address.
*/
public PIMAddrGroup() {
- this.family = 4;
+ this.family = PIM.ADDRESS_FAMILY_IP4;
this.encType = 0;
this.reserved = 0;
this.bBit = false;
@@ -83,7 +85,7 @@ public class PIMAddrGroup {
public void setAddr(IpPrefix pfx) {
this.addr = pfx.address();
this.masklen = (byte) pfx.prefixLength();
- this.family = (byte) ((this.addr.isIp4()) ? 4 : 6);
+ this.family = (byte) ((this.addr.isIp4()) ? PIM.ADDRESS_FAMILY_IP4 : PIM.ADDRESS_FAMILY_IP6);
}
/**
@@ -181,9 +183,9 @@ public class PIMAddrGroup {
checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV4_BYTE_LENGTH);
this.family = bb.get();
- if (family != 4 && family != 6) {
+ if (family != PIM.ADDRESS_FAMILY_IP4 && family != PIM.ADDRESS_FAMILY_IP6) {
throw new DeserializationException("Illegal IP version number: " + family + "\n");
- } else if (family == 6) {
+ } else if (family == PIM.ADDRESS_FAMILY_IP6) {
// Check for one less by since we have already read the first byte of the packet.
checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV6_BYTE_LENGTH - 1);
@@ -201,9 +203,9 @@ public class PIMAddrGroup {
this.reserved |= 0x7d;
this.masklen = bb.get();
- if (this.family == 4) {
+ if (this.family == PIM.ADDRESS_FAMILY_IP4) {
this.addr = IpAddress.valueOf(bb.getInt());
- } else if (this.family == 6) {
+ } else if (this.family == PIM.ADDRESS_FAMILY_IP6) {
this.addr = Ip6Address.valueOf(bb.array(), 2);
}
return this;
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java
index 21526408..762dad56 100644
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java
@@ -17,9 +17,10 @@ package org.onlab.packet.pim;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
-import org.onlab.packet.Ip6Address;
+import org.onlab.packet.PIM;
import java.nio.ByteBuffer;
@@ -66,7 +67,7 @@ public class PIMAddrSource {
}
private void init() {
- this.family = 4;
+ this.family = PIM.ADDRESS_FAMILY_IP4;
this.encType = 0;
this.reserved = 0;
this.sBit = true;
@@ -92,7 +93,7 @@ public class PIMAddrSource {
public void setAddr(IpPrefix spfx) {
this.addr = spfx.address();
this.masklen = (byte) spfx.prefixLength();
- this.family = (byte) ((this.addr.isIp4()) ? 4 : 6);
+ this.family = (byte) ((this.addr.isIp4()) ? PIM.ADDRESS_FAMILY_IP4 : PIM.ADDRESS_FAMILY_IP6);
}
/**
@@ -156,7 +157,7 @@ public class PIMAddrSource {
*/
public int getByteSize() {
int size = 4;
- size += addr.isIp4() ? 4 : 16;
+ size += addr.isIp4() ? PIM.ADDRESS_FAMILY_IP4 : PIM.ADDRESS_FAMILY_IP6;
return size;
}
@@ -202,9 +203,9 @@ public class PIMAddrSource {
checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_SOURCE_IPV4_BYTE_LENGTH);
this.family = bb.get();
- if (family != 4 && family != 6) {
+ if (family != PIM.ADDRESS_FAMILY_IP4 && family != PIM.ADDRESS_FAMILY_IP6) {
throw new DeserializationException("Illegal IP version number: " + family + "\n");
- } else if (family == 6) {
+ } else if (family == PIM.ADDRESS_FAMILY_IP6) {
// Check for one less by since we have already read the first byte of the packet.
checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_SOURCE_IPV6_BYTE_LENGTH - 1);
@@ -226,9 +227,9 @@ public class PIMAddrSource {
this.reserved &= 0xf8;
this.masklen = bb.get();
- if (this.family == 4) {
+ if (this.family == PIM.ADDRESS_FAMILY_IP4) {
this.addr = IpAddress.valueOf(bb.getInt());
- } else if (this.family == 6) {
+ } else if (this.family == PIM.ADDRESS_FAMILY_IP6) {
this.addr = Ip6Address.valueOf(bb.array(), 2);
}
return this;
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java
index a6ba3895..3327a8e7 100644
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java
@@ -15,10 +15,13 @@
*/
package org.onlab.packet.pim;
+
+
import org.onlab.packet.DeserializationException;
import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.PIM;
import java.nio.ByteBuffer;
@@ -36,7 +39,7 @@ public class PIMAddrUnicast {
* PIM Encoded Source Address.
*/
public PIMAddrUnicast() {
- this.family = 4;
+ this.family = PIM.ADDRESS_FAMILY_IP4;
this.encType = 0;
}
@@ -48,9 +51,9 @@ public class PIMAddrUnicast {
public PIMAddrUnicast(String addr) {
this.addr = IpAddress.valueOf(addr);
if (this.addr.isIp4()) {
- this.family = 4;
+ this.family = PIM.ADDRESS_FAMILY_IP4;
} else {
- this.family = 6;
+ this.family = PIM.ADDRESS_FAMILY_IP6;
}
this.encType = 0;
}
@@ -63,9 +66,9 @@ public class PIMAddrUnicast {
public void setAddr(IpAddress addr) {
this.addr = addr;
if (this.addr.isIp4()) {
- this.family = 4;
+ this.family = PIM.ADDRESS_FAMILY_IP4;
} else {
- this.family = 6;
+ this.family = PIM.ADDRESS_FAMILY_IP6;
}
}
@@ -121,17 +124,17 @@ public class PIMAddrUnicast {
this.family = bb.get();
// If we have IPv6 we need to ensure we have adequate buffer space.
- if (this.family != 4 && this.family != 6) {
+ if (this.family != PIM.ADDRESS_FAMILY_IP4 && this.family != PIM.ADDRESS_FAMILY_IP6) {
throw new DeserializationException("Invalid address family: " + this.family);
- } else if (this.family == 6) {
+ } else if (this.family == PIM.ADDRESS_FAMILY_IP6) {
// Subtract -1 from ENC_UNICAST_IPv6 BYTE_LENGTH because we read one byte for family previously.
checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_UNICAST_IPV6_BYTE_LENGTH - 1);
}
this.encType = bb.get();
- if (this.family == 4) {
+ if (this.family == PIM.ADDRESS_FAMILY_IP4) {
this.addr = IpAddress.valueOf(bb.getInt());
- } else if (this.family == 6) {
+ } else if (this.family == PIM.ADDRESS_FAMILY_IP6) {
this.addr = Ip6Address.valueOf(bb.array(), 2);
}
return this;
diff --git a/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Compiler.java b/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Compiler.java
index add71eb5..919cbd5b 100644
--- a/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Compiler.java
+++ b/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Compiler.java
@@ -48,6 +48,7 @@ public class Compiler {
private static final String GROUP = "group";
private static final String STEP = "step";
private static final String PARALLEL = "parallel";
+ private static final String SEQUENTIAL = "sequential";
private static final String DEPENDENCY = "dependency";
private static final String LOG_DIR = "[@logDir]";
@@ -59,12 +60,16 @@ public class Compiler {
private static final String IF = "[@if]";
private static final String UNLESS = "[@unless]";
private static final String VAR = "[@var]";
+ private static final String STARTS = "[@starts]";
+ private static final String ENDS = "[@ends]";
private static final String FILE = "[@file]";
private static final String NAMESPACE = "[@namespace]";
static final String PROP_START = "${";
static final String PROP_END = "}";
+
private static final String HASH = "#";
+ private static final String HASH_PREV = "#-1";
private final Scenario scenario;
@@ -72,7 +77,7 @@ public class Compiler {
private final Map<String, Step> inactiveSteps = Maps.newHashMap();
private final Map<String, String> requirements = Maps.newHashMap();
private final Set<Dependency> dependencies = Sets.newHashSet();
- private final List<Integer> parallels = Lists.newArrayList();
+ private final List<Integer> clonables = Lists.newArrayList();
private ProcessFlow processFlow;
private File logDir;
@@ -175,6 +180,10 @@ public class Compiler {
cfg.configurationsAt(PARALLEL)
.forEach(c -> processParallelGroup(c, namespace, parentGroup));
+ // Scan all sequential groups
+ cfg.configurationsAt(SEQUENTIAL)
+ .forEach(c -> processSequentialGroup(c, namespace, parentGroup));
+
// Scan all dependencies
cfg.configurationsAt(DEPENDENCY)
.forEach(c -> processDependency(c, namespace));
@@ -309,14 +318,62 @@ public class Compiler {
int i = 1;
while (condition(var, i).length() > 0) {
- parallels.add(0, i);
+ clonables.add(0, i);
+ compile(cfg, namespace, parentGroup);
+ clonables.remove(0);
+ i++;
+ }
+ }
+
+ /**
+ * Processes a sequential clone group directive.
+ *
+ * @param cfg hierarchical definition
+ * @param namespace optional namespace
+ * @param parentGroup optional parent group
+ */
+ private void processSequentialGroup(HierarchicalConfiguration cfg,
+ String namespace, Group parentGroup) {
+ String var = cfg.getString(VAR);
+ String starts = cfg.getString(STARTS);
+ String ends = cfg.getString(ENDS);
+ print("sequential var=%s", var);
+
+ int i = 1;
+ while (condition(var, i).length() > 0) {
+ clonables.add(0, i);
compile(cfg, namespace, parentGroup);
- parallels.remove(0);
+ if (i > 1) {
+ processSequentialRequirements(starts, ends, namespace);
+ }
+ clonables.remove(0);
i++;
}
}
/**
+ * Hooks starts of this sequence tier to the previous tier.
+ *
+ * @param starts comma-separated list of start steps
+ * @param ends comma-separated list of end steps
+ * @param namespace optional namespace
+ */
+ private void processSequentialRequirements(String starts, String ends,
+ String namespace) {
+ for (String s : split(starts)) {
+ String start = expand(prefix(s, namespace));
+ String reqs = requirements.get(s);
+ for (String n : split(ends)) {
+ boolean isSoft = n.startsWith("~");
+ String name = n.replaceFirst("^~", "");
+ name = (isSoft ? "~" : "") + expand(prefix(name, namespace));
+ reqs = reqs == null ? name : (reqs + "," + name);
+ }
+ requirements.put(start, reqs);
+ }
+ }
+
+ /**
* Returns the elaborated repetition construct conditional.
*
* @param var repetition var property
@@ -413,9 +470,11 @@ public class Compiler {
String prop = pString.substring(start + PROP_START.length(), end);
String value;
if (prop.equals(HASH)) {
- value = parallels.get(0).toString();
+ value = Integer.toString(clonables.get(0));
+ } else if (prop.equals(HASH_PREV)) {
+ value = Integer.toString(clonables.get(0) - 1);
} else if (prop.endsWith(HASH)) {
- pString = pString.replaceFirst("#}", parallels.get(0).toString() + "}");
+ pString = pString.replaceFirst("#}", clonables.get(0) + "}");
last = start;
continue;
} else {
diff --git a/framework/src/onos/utils/stc/src/test/java/org/onlab/stc/CompilerTest.java b/framework/src/onos/utils/stc/src/test/java/org/onlab/stc/CompilerTest.java
index d70eff08..59b55307 100644
--- a/framework/src/onos/utils/stc/src/test/java/org/onlab/stc/CompilerTest.java
+++ b/framework/src/onos/utils/stc/src/test/java/org/onlab/stc/CompilerTest.java
@@ -69,8 +69,8 @@ public class CompilerTest {
ProcessFlow flow = compiler.processFlow();
assertSame("incorrect scenario", scenario, compiler.scenario());
- assertEquals("incorrect step count", 24, flow.getVertexes().size());
- assertEquals("incorrect dependency count", 16, flow.getEdges().size());
+ assertEquals("incorrect step count", 33, flow.getVertexes().size());
+ assertEquals("incorrect dependency count", 26, flow.getEdges().size());
assertEquals("incorrect logDir",
new File(TEST_DIR.getAbsolutePath(), "foo"), compiler.logDir());
diff --git a/framework/src/onos/utils/stc/src/test/resources/org/onlab/stc/scenario.xml b/framework/src/onos/utils/stc/src/test/resources/org/onlab/stc/scenario.xml
index 34e67fd5..533b11ea 100644
--- a/framework/src/onos/utils/stc/src/test/resources/org/onlab/stc/scenario.xml
+++ b/framework/src/onos/utils/stc/src/test/resources/org/onlab/stc/scenario.xml
@@ -44,4 +44,11 @@
<step name="ding-${#}" exec="asdads" requires="ping-${#},pong-${#}"/>
<dependency name="maybe" requires="ding-${#}"/>
</parallel>
+
+ <sequential var="${TOC#}" requires="alpha" starts="fifi-${#},gigi-${#}" ends="gaga-${#-1}">
+ <step name="fifi-${#}" exec="asdads ${TOC#}"/>
+ <step name="gigi-${#}" exec="asdads"/>
+ <step name="gaga-${#}" exec="asdads" requires="fifi-${#},gigi-${#}"/>
+ <dependency name="maybe" requires="gaga-${#}"/>
+ </sequential>
</scenario> \ No newline at end of file
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/glyph.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/glyph.js
index 28f262a1..d8dce362 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/glyph.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/glyph.js
@@ -49,6 +49,8 @@
// otn, roadm_otn, firewall, balancer, ips, ids,
// controller, virtual, fiber_switch, other
+ // NOTE: when adding glyphs, please also update TopoConstants.Glyphs class.
+
glyphDataSet = {
_viewbox: "0 0 110 110",
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js
index d29748b1..1f061dd6 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js
@@ -218,6 +218,24 @@
.attr('transform', sus.translate(dx, dy));
}
+ function updateDeviceBadge(d) {
+ // TODO: Fix this WIP
+ var node = d.el,
+ bsel;
+
+ if (d.badge) {
+ bsel = node.append('g')
+ .classed('badge', true)
+ .attr('transform', sus.translate(-14, -14));
+
+ bsel.append('circle')
+ .attr('r', 14);
+ bsel.append('text')
+ .attr('transform', sus.translate(-5, 3))
+ .text('42');
+ }
+ }
+
function updateHostLabel(d) {
var label = trimLabel(hostLabel(d));
d.el.select('text').text(label);
@@ -241,6 +259,7 @@
var node = d.el;
node.classed('online', d.online);
updateDeviceLabel(d);
+ updateDeviceBadge(d);
api.posNode(d, true);
}
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
index dbe8f9f5..f00b87fa 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -860,6 +860,16 @@
});
}
+ function clearNodeDeco() {
+ node.selectAll('g.badge').remove();
+ }
+
+ function removeNodeBadges() {
+ network.nodes.forEach(function (d) {
+ d.badge = null;
+ });
+ }
+
function updateLinkLabelModel() {
// create the backing data for showing labels..
var data = [];
@@ -923,6 +933,8 @@
function mkOverlayApi() {
return {
+ clearNodeDeco: clearNodeDeco,
+ removeNodeBadges: removeNodeBadges,
clearLinkTrafficStyle: clearLinkTrafficStyle,
removeLinkLabels: removeLinkLabels,
findLinkById: tms.findLinkById,
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
index 74fa2f24..9a3b4358 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -294,7 +294,8 @@
unsupLink( key, [less] )
*/
- // TODO: clear node highlighting
+ api.clearNodeDeco();
+ api.removeNodeBadges();
api.clearLinkTrafficStyle();
api.removeLinkLabels();
@@ -319,8 +320,11 @@
});
data.devices.forEach(function (device) {
- var ddata = api.findNodeById(device.id);
+ var ddata = api.findNodeById(device.id),
+ badgeData = device.badge || null;
+
if (ddata && !ddata.el.empty()) {
+ ddata.badge = badgeData;
if (!device.subdue) {
api.unsupNode(ddata.id, less);
}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_1_addInstance.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_1_addInstance.json
new file mode 100644
index 00000000..cdb95361
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_1_addInstance.json
@@ -0,0 +1,14 @@
+{
+ "event": "addInstance",
+ "payload": {
+ "id": "ONOS",
+ "ip": "192.168.56.101",
+ "online": true,
+ "uiAttached": true,
+ "switches": 2,
+ "labels": [
+ "ONOS",
+ "192.168.56.101"
+ ]
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_2_addDevice_s1.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_2_addDevice_s1.json
new file mode 100644
index 00000000..2e9d30f2
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_2_addDevice_s1.json
@@ -0,0 +1,18 @@
+{
+ "event": "addDevice",
+ "payload": {
+ "id": "of:0000000000000001",
+ "type": "switch",
+ "online": true,
+ "master": "ONOS",
+ "labels": [
+ "",
+ "switch-1",
+ "of:0000000000000001"
+ ],
+ "metaUi": {
+ "x": 200,
+ "y": 200
+ }
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_3_addDevice_s2.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_3_addDevice_s2.json
new file mode 100644
index 00000000..79c04d3a
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_3_addDevice_s2.json
@@ -0,0 +1,18 @@
+{
+ "event": "addDevice",
+ "payload": {
+ "id": "of:0000000000000002",
+ "type": "switch",
+ "online": true,
+ "master": "ONOS",
+ "labels": [
+ "",
+ "switch-2",
+ "of:0000000000000002"
+ ],
+ "metaUi": {
+ "x": 400,
+ "y": 220
+ }
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json
new file mode 100644
index 00000000..fb952837
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json
@@ -0,0 +1,16 @@
+{
+ "event": "addLink",
+ "payload": {
+ "id": "of:0000000000000001/5-of:0000000000000002/7",
+ "type": "direct",
+ "online": true,
+ "linkWidth": 2,
+ "src": "of:0000000000000001",
+ "srcPort": "5",
+ "dst": "of:0000000000000002",
+ "dstPort": "7",
+ "props" : {
+ "BW": "70 Gb"
+ }
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json
new file mode 100644
index 00000000..615efd25
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json
@@ -0,0 +1,8 @@
+{
+ "event": "showHighlights",
+ "payload": {
+ "devices": [],
+ "hosts": [],
+ "links": []
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json
new file mode 100644
index 00000000..74c42c5c
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json
@@ -0,0 +1,30 @@
+{
+ "event": "showHighlights",
+ "payload": {
+ "devices": [
+ {
+ "id": "of:0000000000000001",
+ "badge": {
+ "status": "e",
+ "gid": "xMark",
+ "msg": "x marks the spot"
+ }
+ },
+ {
+ "id": "of:0000000000000002",
+ "badge": {
+ "status": "w",
+ "txt": "7"
+ }
+ }
+ ],
+ "hosts": [],
+ "links": [
+ {
+ "css": "primary",
+ "id": "of:0000000000000001/5-of:0000000000000002/7",
+ "label": "Antz!"
+ }
+ ]
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json
new file mode 100644
index 00000000..615efd25
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json
@@ -0,0 +1,8 @@
+{
+ "event": "showHighlights",
+ "payload": {
+ "devices": [],
+ "hosts": [],
+ "links": []
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json
new file mode 100644
index 00000000..0ca4f4f4
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json
@@ -0,0 +1,12 @@
+{
+ "comments": [
+ "Demo of adding badges to devices"
+ ],
+ "title": "Demo adding badges",
+ "params": {
+ "lastAuto": 5
+ },
+ "description": [
+ "Demonstrate the device badging feature."
+ ]
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/traffic/scenario.json b/framework/src/onos/web/gui/src/test/_karma/ev/traffic/scenario.json
index 57c03733..4e7ce4f8 100644
--- a/framework/src/onos/web/gui/src/test/_karma/ev/traffic/scenario.json
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/traffic/scenario.json
@@ -1,6 +1,8 @@
{
"comments": [
- "Stepping through showTraffic"
+ "Stepping through showTraffic",
+ "NOTE: showTraffic event is deprecated",
+ " This needs to be re-worked to use showHighlights"
],
"title": "Show Traffic Scenario",
"params": {