alshabib

link discovery and providers are implemented

...@@ -2,7 +2,7 @@ package org.onlab.onos.net; ...@@ -2,7 +2,7 @@ package org.onlab.onos.net;
2 2
3 import java.util.Objects; 3 import java.util.Objects;
4 4
5 -import static com.google.common.base.MoreObjects.toStringHelper; 5 +import com.google.common.base.MoreObjects;
6 6
7 /** 7 /**
8 * Abstraction of a network connection point expressed as a pair of the 8 * Abstraction of a network connection point expressed as a pair of the
...@@ -42,7 +42,6 @@ public class ConnectPoint { ...@@ -42,7 +42,6 @@ public class ConnectPoint {
42 * @throws java.lang.IllegalStateException if connection point is not 42 * @throws java.lang.IllegalStateException if connection point is not
43 * associated with a device 43 * associated with a device
44 */ 44 */
45 - @SuppressWarnings("unchecked")
46 public DeviceId deviceId() { 45 public DeviceId deviceId() {
47 if (elementId instanceof DeviceId) { 46 if (elementId instanceof DeviceId) {
48 return (DeviceId) elementId; 47 return (DeviceId) elementId;
...@@ -77,7 +76,7 @@ public class ConnectPoint { ...@@ -77,7 +76,7 @@ public class ConnectPoint {
77 76
78 @Override 77 @Override
79 public String toString() { 78 public String toString() {
80 - return toStringHelper(this) 79 + return MoreObjects.toStringHelper(this)
81 .add("elementId", elementId) 80 .add("elementId", elementId)
82 .add("portNumber", portNumber) 81 .add("portNumber", portNumber)
83 .toString(); 82 .toString();
......
1 package org.onlab.onos.net.trivial.impl; 1 package org.onlab.onos.net.trivial.impl;
2 2
3 -import com.google.common.collect.Sets; 3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import java.util.Set;
7 +
4 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
5 import org.apache.felix.scr.annotations.Component; 9 import org.apache.felix.scr.annotations.Component;
6 import org.apache.felix.scr.annotations.Deactivate; 10 import org.apache.felix.scr.annotations.Deactivate;
...@@ -24,10 +28,7 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; ...@@ -24,10 +28,7 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry;
24 import org.onlab.onos.net.provider.AbstractProviderService; 28 import org.onlab.onos.net.provider.AbstractProviderService;
25 import org.slf4j.Logger; 29 import org.slf4j.Logger;
26 30
27 -import java.util.Set; 31 +import com.google.common.collect.Sets;
28 -
29 -import static com.google.common.base.Preconditions.checkNotNull;
30 -import static org.slf4j.LoggerFactory.getLogger;
31 32
32 /** 33 /**
33 * Provides basic implementation of the link SB & NB APIs. 34 * Provides basic implementation of the link SB & NB APIs.
...@@ -35,8 +36,8 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -35,8 +36,8 @@ import static org.slf4j.LoggerFactory.getLogger;
35 @Component(immediate = true) 36 @Component(immediate = true)
36 @Service 37 @Service
37 public class SimpleLinkManager 38 public class SimpleLinkManager
38 - extends AbstractProviderRegistry<LinkProvider, LinkProviderService> 39 +extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
39 - implements LinkService, LinkAdminService, LinkProviderRegistry { 40 +implements LinkService, LinkAdminService, LinkProviderRegistry {
40 41
41 private static final String DEVICE_ID_NULL = "Device ID cannot be null"; 42 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
42 private static final String LINK_DESC_NULL = "Link description cannot be null"; 43 private static final String LINK_DESC_NULL = "Link description cannot be null";
...@@ -156,7 +157,7 @@ public class SimpleLinkManager ...@@ -156,7 +157,7 @@ public class SimpleLinkManager
156 public void linkDetected(LinkDescription linkDescription) { 157 public void linkDetected(LinkDescription linkDescription) {
157 checkNotNull(linkDescription, LINK_DESC_NULL); 158 checkNotNull(linkDescription, LINK_DESC_NULL);
158 checkValidity(); 159 checkValidity();
159 - log.info("Link {} detected", linkDescription); 160 + log.debug("Link {} detected", linkDescription);
160 LinkEvent event = store.createOrUpdateLink(provider().id(), 161 LinkEvent event = store.createOrUpdateLink(provider().id(),
161 linkDescription); 162 linkDescription);
162 post(event); 163 post(event);
......
...@@ -75,4 +75,9 @@ public final class DefaultPacketContext implements PacketContext { ...@@ -75,4 +75,9 @@ public final class DefaultPacketContext implements PacketContext {
75 return new DefaultPacketContext(s, pkt); 75 return new DefaultPacketContext(s, pkt);
76 } 76 }
77 77
78 + @Override
79 + public Integer inPort() {
80 + return pktin.getInPort().getPortNumber();
81 + }
82 +
78 } 83 }
......
...@@ -48,4 +48,10 @@ public interface PacketContext { ...@@ -48,4 +48,10 @@ public interface PacketContext {
48 * @return the dpid of the switch. 48 * @return the dpid of the switch.
49 */ 49 */
50 public Dpid dpid(); 50 public Dpid dpid();
51 +
52 + /**
53 + * Provide the port on which the packet arrived.
54 + * @return the port
55 + */
56 + public Integer inPort();
51 } 57 }
......
...@@ -415,12 +415,14 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { ...@@ -415,12 +415,14 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
415 OFDescStatsReply drep = (OFDescStatsReply) m; 415 OFDescStatsReply drep = (OFDescStatsReply) m;
416 // Here is where we differentiate between different kinds of switches 416 // Here is where we differentiate between different kinds of switches
417 h.sw = h.controller.getOFSwitchInstance(h.thisdpid, drep, h.ofVersion); 417 h.sw = h.controller.getOFSwitchInstance(h.thisdpid, drep, h.ofVersion);
418 +
418 h.sw.setOFVersion(h.ofVersion); 419 h.sw.setOFVersion(h.ofVersion);
419 h.sw.setFeaturesReply(h.featuresReply); 420 h.sw.setFeaturesReply(h.featuresReply);
420 h.sw.setPortDescReply(h.portDescReply); 421 h.sw.setPortDescReply(h.portDescReply);
421 h.sw.setConnected(true); 422 h.sw.setConnected(true);
422 h.sw.setChannel(h.channel); 423 h.sw.setChannel(h.channel);
423 boolean success = h.sw.connectSwitch(); 424 boolean success = h.sw.connectSwitch();
425 +
424 if (!success) { 426 if (!success) {
425 disconnectDuplicate(h); 427 disconnectDuplicate(h);
426 return; 428 return;
...@@ -432,10 +434,10 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { ...@@ -432,10 +434,10 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
432 log.info("Switch {} bound to class {}, description {}", 434 log.info("Switch {} bound to class {}, description {}",
433 new Object[] {h.sw, h.sw.getClass(), drep }); 435 new Object[] {h.sw, h.sw.getClass(), drep });
434 //Put switch in EQUAL mode until we hear back from the global registry 436 //Put switch in EQUAL mode until we hear back from the global registry
435 - log.debug("Setting new switch {} to EQUAL and sending Role request", 437 + //log.debug("Setting new switch {} to EQUAL and sending Role request",
436 - h.sw.getStringId()); 438 + // h.sw.getStringId());
437 - h.sw.activateEqualSwitch(); 439 + //h.sw.activateEqualSwitch();
438 - h.setSwitchRole(RoleState.EQUAL); 440 + //h.setSwitchRole(RoleState.EQUAL);
439 441
440 h.sw.startDriverHandshake(); 442 h.sw.startDriverHandshake();
441 h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE); 443 h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
......
1 package org.onlab.onos.of.controller.impl; 1 package org.onlab.onos.of.controller.impl;
2 2
3 +import java.util.ArrayList;
4 +import java.util.HashSet;
5 +import java.util.List;
6 +import java.util.Set;
7 +import java.util.concurrent.ConcurrentHashMap;
8 +import java.util.concurrent.locks.Lock;
9 +import java.util.concurrent.locks.ReentrantLock;
10 +
3 import org.apache.felix.scr.annotations.Activate; 11 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 12 import org.apache.felix.scr.annotations.Component;
5 import org.apache.felix.scr.annotations.Deactivate; 13 import org.apache.felix.scr.annotations.Deactivate;
6 import org.apache.felix.scr.annotations.Service; 14 import org.apache.felix.scr.annotations.Service;
15 +import org.onlab.onos.of.controller.DefaultPacketContext;
7 import org.onlab.onos.of.controller.Dpid; 16 import org.onlab.onos.of.controller.Dpid;
8 import org.onlab.onos.of.controller.OpenFlowController; 17 import org.onlab.onos.of.controller.OpenFlowController;
9 import org.onlab.onos.of.controller.OpenFlowSwitch; 18 import org.onlab.onos.of.controller.OpenFlowSwitch;
...@@ -12,18 +21,11 @@ import org.onlab.onos.of.controller.PacketListener; ...@@ -12,18 +21,11 @@ import org.onlab.onos.of.controller.PacketListener;
12 import org.onlab.onos.of.controller.RoleState; 21 import org.onlab.onos.of.controller.RoleState;
13 import org.onlab.onos.of.controller.driver.OpenFlowAgent; 22 import org.onlab.onos.of.controller.driver.OpenFlowAgent;
14 import org.projectfloodlight.openflow.protocol.OFMessage; 23 import org.projectfloodlight.openflow.protocol.OFMessage;
24 +import org.projectfloodlight.openflow.protocol.OFPacketIn;
15 import org.projectfloodlight.openflow.protocol.OFPortStatus; 25 import org.projectfloodlight.openflow.protocol.OFPortStatus;
16 import org.slf4j.Logger; 26 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory; 27 import org.slf4j.LoggerFactory;
18 28
19 -import java.util.ArrayList;
20 -import java.util.HashSet;
21 -import java.util.List;
22 -import java.util.Set;
23 -import java.util.concurrent.ConcurrentHashMap;
24 -import java.util.concurrent.locks.Lock;
25 -import java.util.concurrent.locks.ReentrantLock;
26 -
27 @Component(immediate = true) 29 @Component(immediate = true)
28 @Service 30 @Service
29 public class OpenFlowControllerImpl implements OpenFlowController { 31 public class OpenFlowControllerImpl implements OpenFlowController {
...@@ -125,11 +127,14 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -125,11 +127,14 @@ public class OpenFlowControllerImpl implements OpenFlowController {
125 case PACKET_IN: 127 case PACKET_IN:
126 for (PacketListener p : ofPacketListener) { 128 for (PacketListener p : ofPacketListener) {
127 //TODO fix me! 129 //TODO fix me!
128 - p.handlePacket(null); 130 + p.handlePacket(DefaultPacketContext
131 + .packetContextFromPacketIn(this.getSwitch(dpid),
132 + (OFPacketIn) msg));
129 } 133 }
130 break; 134 break;
131 default: 135 default:
132 - log.warn("Handling message type {} not yet implemented", msg.getType()); 136 + log.warn("Handling message type {} not yet implemented {}",
137 + msg.getType(), msg);
133 } 138 }
134 } 139 }
135 140
...@@ -224,10 +229,13 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -224,10 +229,13 @@ public class OpenFlowControllerImpl implements OpenFlowController {
224 } 229 }
225 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid); 230 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
226 if (sw == null) { 231 if (sw == null) {
232 + sw = getSwitch(dpid);
233 + if (sw == null) {
227 log.error("Transition to master called on sw {}, but switch " 234 log.error("Transition to master called on sw {}, but switch "
228 + "was not found in controller-cache", dpid); 235 + "was not found in controller-cache", dpid);
229 return; 236 return;
230 } 237 }
238 + }
231 log.info("Transitioned switch {} to MASTER", dpid); 239 log.info("Transitioned switch {} to MASTER", dpid);
232 activeMasterSwitches.put(dpid, sw); 240 activeMasterSwitches.put(dpid, sw);
233 } finally { 241 } finally {
......
...@@ -84,7 +84,7 @@ class RoleManager implements RoleHandler { ...@@ -84,7 +84,7 @@ class RoleManager implements RoleHandler {
84 default: 84 default:
85 // ensuring that the only two roles sent to 1.0 switches with 85 // ensuring that the only two roles sent to 1.0 switches with
86 // Nicira role support, are MASTER and SLAVE 86 // Nicira role support, are MASTER and SLAVE
87 - roleToSend = OFNiciraControllerRole.ROLE_SLAVE; 87 + roleToSend = OFNiciraControllerRole.ROLE_OTHER;
88 log.warn("Sending Nx Role.SLAVE to switch {}.", sw); 88 log.warn("Sending Nx Role.SLAVE to switch {}.", sw);
89 } 89 }
90 int xid = sw.getNextTransactionId(); 90 int xid = sw.getNextTransactionId();
......
...@@ -50,8 +50,7 @@ public class OFSwitchImplOVS10 extends AbstractOpenFlowSwitch { ...@@ -50,8 +50,7 @@ public class OFSwitchImplOVS10 extends AbstractOpenFlowSwitch {
50 50
51 @Override 51 @Override
52 public void write(OFMessage msg) { 52 public void write(OFMessage msg) {
53 - channel.write(msg); 53 + channel.write(Collections.singletonList(msg));
54 -
55 } 54 }
56 55
57 @Override 56 @Override
......
...@@ -62,6 +62,14 @@ ...@@ -62,6 +62,14 @@
62 </dependency> 62 </dependency>
63 63
64 <dependency> 64 <dependency>
65 + <groupId>io.netty</groupId>
66 + <artifactId>netty</artifactId>
67 + <version>3.9.0.Final</version>
68 + </dependency>
69 +
70 +
71 +
72 + <dependency>
65 <groupId>com.google.guava</groupId> 73 <groupId>com.google.guava</groupId>
66 <artifactId>guava-testlib</artifactId> 74 <artifactId>guava-testlib</artifactId>
67 <version>18.0</version> 75 <version>18.0</version>
......
1 +/*******************************************************************************
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + ******************************************************************************/
16 +package org.onlab.onos.provider.of.link.impl;
17 +
18 +import static org.slf4j.LoggerFactory.getLogger;
19 +
20 +import java.util.Collections;
21 +import java.util.HashMap;
22 +import java.util.HashSet;
23 +import java.util.Iterator;
24 +import java.util.List;
25 +import java.util.Map;
26 +import java.util.Set;
27 +import java.util.concurrent.TimeUnit;
28 +import java.util.concurrent.atomic.AtomicInteger;
29 +
30 +import org.jboss.netty.util.Timeout;
31 +import org.jboss.netty.util.TimerTask;
32 +import org.onlab.onos.net.ConnectPoint;
33 +import org.onlab.onos.net.DeviceId;
34 +import org.onlab.onos.net.Link.Type;
35 +import org.onlab.onos.net.PortNumber;
36 +import org.onlab.onos.net.link.DefaultLinkDescription;
37 +import org.onlab.onos.net.link.LinkDescription;
38 +import org.onlab.onos.net.link.LinkProviderService;
39 +import org.onlab.onos.of.controller.Dpid;
40 +import org.onlab.onos.of.controller.OpenFlowController;
41 +import org.onlab.onos.of.controller.OpenFlowSwitch;
42 +import org.onlab.packet.Ethernet;
43 +import org.onlab.packet.ONLabLddp;
44 +import org.onlab.packet.ONLabLddp.DPIDandPort;
45 +import org.onlab.timer.Timer;
46 +import org.projectfloodlight.openflow.protocol.OFFactory;
47 +import org.projectfloodlight.openflow.protocol.OFMessage;
48 +import org.projectfloodlight.openflow.protocol.OFPacketOut;
49 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
50 +import org.projectfloodlight.openflow.protocol.action.OFAction;
51 +import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
52 +import org.projectfloodlight.openflow.types.OFBufferId;
53 +import org.projectfloodlight.openflow.types.OFPort;
54 +import org.slf4j.Logger;
55 +
56 +
57 +
58 +/**
59 + * Run discovery process from a physical switch. Ports are initially labeled as
60 + * slow ports. When an LLDP is successfully received, label the remote port as
61 + * fast. Every probeRate milliseconds, loop over all fast ports and send an
62 + * LLDP, send an LLDP for a single slow port. Based on FlowVisor topology
63 + * discovery implementation.
64 + *
65 + * TODO: add 'fast discovery' mode: drop LLDPs in destination switch but listen
66 + * for flow_removed messages
67 + */
68 +public class LinkDiscovery implements TimerTask {
69 +
70 + private final OpenFlowSwitch sw;
71 + // send 1 probe every probeRate milliseconds
72 + private final long probeRate;
73 + private final Set<Integer> slowPorts;
74 + private final Set<Integer> fastPorts;
75 + // number of unacknowledged probes per port
76 + private final Map<Integer, AtomicInteger> portProbeCount;
77 + // number of probes to send before link is removed
78 + private static final short MAX_PROBE_COUNT = 3;
79 + private Iterator<Integer> slowIterator;
80 + private final OFFactory ofFactory;
81 + private final Logger log = getLogger(getClass());
82 + private final ONLabLddp lldpPacket;
83 + private final Ethernet ethPacket;
84 + private Ethernet bddpEth;
85 + private final boolean useBDDP;
86 + private final OpenFlowController ctrl;
87 + private final LinkProviderService linkProvider;
88 +
89 + /**
90 + * Instantiates discovery manager for the given physical switch. Creates a
91 + * generic LLDP packet that will be customized for the port it is sent out on.
92 + * Starts the the timer for the discovery process.
93 + *
94 + * @param sw the physical switch
95 + * @param useBDDP flag to also use BDDP for discovery
96 + */
97 + public LinkDiscovery(final OpenFlowSwitch sw,
98 + OpenFlowController ctrl, LinkProviderService providerService, Boolean... useBDDP) {
99 + this.sw = sw;
100 + this.ofFactory = sw.factory();
101 + this.ctrl = ctrl;
102 + this.probeRate = 1000;
103 + this.linkProvider = providerService;
104 + this.slowPorts = Collections.synchronizedSet(new HashSet<Integer>());
105 + this.fastPorts = Collections.synchronizedSet(new HashSet<Integer>());
106 + this.portProbeCount = new HashMap<Integer, AtomicInteger>();
107 + this.lldpPacket = new ONLabLddp();
108 + this.lldpPacket.setSwitch(this.sw.getId());
109 + this.ethPacket = new Ethernet();
110 + this.ethPacket.setEtherType(Ethernet.TYPE_LLDP);
111 + this.ethPacket.setDestinationMACAddress(ONLabLddp.LLDP_NICIRA);
112 + this.ethPacket.setPayload(this.lldpPacket);
113 + this.ethPacket.setPad(true);
114 + this.useBDDP = useBDDP.length > 0 ? useBDDP[0] : false;
115 + if (this.useBDDP) {
116 + this.bddpEth = new Ethernet();
117 + this.bddpEth.setPayload(this.lldpPacket);
118 + this.bddpEth.setEtherType(Ethernet.TYPE_BSN);
119 + this.bddpEth.setDestinationMACAddress(ONLabLddp.BDDP_MULTICAST);
120 + this.bddpEth.setPad(true);
121 + log.info("Using BDDP to discover network");
122 + }
123 + for (OFPortDesc port : sw.getPorts()) {
124 + if (port.getPortNo() != OFPort.LOCAL) {
125 + addPort(port);
126 + }
127 + }
128 + Timer.getTimer().newTimeout(this, this.probeRate,
129 + TimeUnit.MILLISECONDS);
130 + this.log.debug("Started discovery manager for switch {}",
131 + sw.getId());
132 +
133 + }
134 +
135 + /**
136 + * Add physical port port to discovery process.
137 + * Send out initial LLDP and label it as slow port.
138 + *
139 + * @param port the port
140 + */
141 + public void addPort(final OFPortDesc port) {
142 + // Ignore ports that are not on this switch, or already booted. */
143 +
144 + synchronized (this) {
145 + this.log.debug("sending init probe to port {}",
146 + port.getPortNo().getPortNumber());
147 + OFPacketOut pkt;
148 +
149 + pkt = this.createLLDPPacketOut(port);
150 + this.sw.sendMsg(pkt);
151 + if (useBDDP) {
152 + OFPacketOut bpkt = this.createBDDPPacketOut(port);
153 + this.sw.sendMsg(bpkt);
154 + }
155 +
156 + this.slowPorts.add(port.getPortNo().getPortNumber());
157 + this.slowIterator = this.slowPorts.iterator();
158 + }
159 +
160 + }
161 +
162 + /**
163 + * Removes physical port from discovery process.
164 + *
165 + * @param port the port
166 + */
167 + public void removePort(final OFPort port) {
168 + // Ignore ports that are not on this switch
169 +
170 + int portnum = port.getPortNumber();
171 + synchronized (this) {
172 + if (this.slowPorts.contains(portnum)) {
173 + this.slowPorts.remove(portnum);
174 + this.slowIterator = this.slowPorts.iterator();
175 +
176 + } else if (this.fastPorts.contains(portnum)) {
177 + this.fastPorts.remove(portnum);
178 + this.portProbeCount.remove(portnum);
179 + // no iterator to update
180 + } else {
181 + this.log.warn(
182 + "tried to dynamically remove non-existing port {}",
183 + portnum);
184 + }
185 + }
186 +
187 + }
188 +
189 + /**
190 + * Method called by remote port to acknowledge receipt of LLDP sent by
191 + * this port. If slow port, updates label to fast. If fast port, decrements
192 + * number of unacknowledged probes.
193 + *
194 + * @param port the port
195 + */
196 + public void ackProbe(final Integer port) {
197 + final int portNumber = port;
198 + synchronized (this) {
199 + if (this.slowPorts.contains(portNumber)) {
200 + this.log.debug("Setting slow port to fast: {}:{}",
201 + this.sw.getId(), portNumber);
202 + this.slowPorts.remove(portNumber);
203 + this.slowIterator = this.slowPorts.iterator();
204 + this.fastPorts.add(portNumber);
205 + this.portProbeCount.put(portNumber, new AtomicInteger(0));
206 + } else {
207 + if (this.fastPorts.contains(portNumber)) {
208 + this.portProbeCount.get(portNumber).set(0);
209 + } else {
210 + this.log.debug(
211 + "Got ackProbe for non-existing port: {}",
212 + portNumber);
213 + }
214 + }
215 + }
216 + }
217 +
218 + /**
219 + * Creates packet_out LLDP for specified output port.
220 + *
221 + * @param port the port
222 + * @return Packet_out message with LLDP data
223 + * @throws PortMappingException
224 + */
225 + private OFPacketOut createLLDPPacketOut(final OFPortDesc port) {
226 + OFPacketOut.Builder packetOut = this.ofFactory.buildPacketOut();
227 + packetOut.setBufferId(OFBufferId.NO_BUFFER);
228 + OFAction act = this.ofFactory.actions().buildOutput()
229 + .setPort(port.getPortNo()).build();
230 + packetOut.setActions(Collections.singletonList(act));
231 + this.lldpPacket.setPort(port.getPortNo().getPortNumber());
232 + this.ethPacket.setSourceMACAddress(port.getHwAddr().getBytes());
233 +
234 + final byte[] lldp = this.ethPacket.serialize();
235 + packetOut.setData(lldp);
236 + return packetOut.build();
237 + }
238 +
239 + /**
240 + * Creates packet_out BDDP for specified output port.
241 + *
242 + * @param port the port
243 + * @return Packet_out message with LLDP data
244 + * @throws PortMappingException
245 + */
246 + private OFPacketOut createBDDPPacketOut(final OFPortDesc port) {
247 + OFPacketOut.Builder packetOut = sw.factory().buildPacketOut();
248 +
249 + packetOut.setBufferId(OFBufferId.NO_BUFFER);
250 +
251 + OFActionOutput.Builder act = sw.factory().actions().buildOutput()
252 + .setPort(port.getPortNo());
253 + OFAction out = act.build();
254 + packetOut.setActions(Collections.singletonList(out));
255 + this.lldpPacket.setPort(port.getPortNo().getPortNumber());
256 + this.bddpEth.setSourceMACAddress(port.getHwAddr().getBytes());
257 +
258 + final byte[] bddp = this.bddpEth.serialize();
259 + packetOut.setData(bddp);
260 +
261 + return packetOut.build();
262 + }
263 +
264 +
265 + private void sendMsg(final OFMessage msg) {
266 + this.sw.sendMsg(msg);
267 + }
268 +
269 + public String getName() {
270 + return "LinkDiscovery " + this.sw.getStringId();
271 + }
272 +
273 + /*
274 + * Handles an incoming LLDP packet. Creates link in topology and sends ACK
275 + * to port where LLDP originated.
276 + */
277 + @SuppressWarnings("rawtypes")
278 + public void handleLLDP(final Ethernet eth, Integer inPort) {
279 +
280 + final byte[] pkt = eth.serialize();
281 +
282 + if (ONLabLddp.isOVXLLDP(pkt)) {
283 + final Integer dstPort = inPort;
284 + final DPIDandPort dp = ONLabLddp.parseLLDP(pkt);
285 + final OpenFlowSwitch srcSwitch = ctrl.getSwitch(new Dpid(dp.getDpid()));
286 + final Integer srcPort = dp.getPort();
287 + if (srcSwitch == null) {
288 + return;
289 + }
290 + this.ackProbe(srcPort);
291 + ConnectPoint src = new ConnectPoint(
292 + DeviceId.deviceId("of:" + Long.toHexString(srcSwitch.getId())),
293 + PortNumber.portNumber(srcPort));
294 +
295 + ConnectPoint dst = new ConnectPoint(
296 + DeviceId.deviceId("of:" + Long.toHexString(sw.getId())),
297 + PortNumber.portNumber(dstPort));
298 + LinkDescription ld;
299 + if (eth.getEtherType() == Ethernet.TYPE_BSN) {
300 + ld = new DefaultLinkDescription(src, dst, Type.INDIRECT);
301 + } else {
302 + ld = new DefaultLinkDescription(src, dst, Type.DIRECT);
303 + }
304 + linkProvider.linkDetected(ld);
305 + } else {
306 + this.log.debug("Ignoring unknown LLDP");
307 + }
308 + }
309 +
310 + private OFPortDesc findPort(List<OFPortDesc> ports, Integer inPort) {
311 + for (OFPortDesc p : ports) {
312 + if (p.getPortNo().getPortNumber() == inPort) {
313 + return p;
314 + }
315 + }
316 + return null;
317 + }
318 +
319 + /**
320 + * Execute this method every t milliseconds. Loops over all ports
321 + * labeled as fast and sends out an LLDP. Send out an LLDP on a single slow
322 + * port.
323 + *
324 + * @param t timeout
325 + * @throws Exception
326 + */
327 + @Override
328 + public void run(final Timeout t) {
329 + this.log.debug("sending probes");
330 + synchronized (this) {
331 + final Iterator<Integer> fastIterator = this.fastPorts.iterator();
332 + while (fastIterator.hasNext()) {
333 + final Integer portNumber = fastIterator.next();
334 + final int probeCount = this.portProbeCount.get(portNumber)
335 + .getAndIncrement();
336 + OFPortDesc port = findPort(this.sw.getPorts(), portNumber);
337 + if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) {
338 + this.log.debug("sending fast probe to port");
339 +
340 + OFPacketOut pkt = this.createLLDPPacketOut(port);
341 + this.sendMsg(pkt);
342 + if (useBDDP) {
343 + OFPacketOut bpkt = this.createBDDPPacketOut(port);
344 + this.sendMsg(bpkt);
345 + }
346 + } else {
347 + // Update fast and slow ports
348 + fastIterator.remove();
349 + this.slowPorts.add(portNumber);
350 + this.slowIterator = this.slowPorts.iterator();
351 + this.portProbeCount.remove(portNumber);
352 +
353 + // Remove link from topology
354 + final OFPortDesc srcPort = port;
355 +
356 + ConnectPoint cp = new ConnectPoint(
357 + DeviceId.deviceId("of:" + Long.toHexString(sw.getId())),
358 + PortNumber.portNumber(srcPort.getPortNo().getPortNumber()));
359 + linkProvider.linksVanished(cp);
360 + }
361 + }
362 +
363 + // send a probe for the next slow port
364 + if (this.slowPorts.size() > 0) {
365 + if (!this.slowIterator.hasNext()) {
366 + this.slowIterator = this.slowPorts.iterator();
367 + }
368 + if (this.slowIterator.hasNext()) {
369 + final int portNumber = this.slowIterator.next();
370 + this.log.debug("sending slow probe to port {}", portNumber);
371 + OFPortDesc port = findPort(this.sw.getPorts(), portNumber);
372 +
373 + OFPacketOut pkt = this.createLLDPPacketOut(port);
374 + this.sendMsg(pkt);
375 + if (useBDDP) {
376 + OFPacketOut bpkt = this.createBDDPPacketOut(port);
377 + this.sendMsg(bpkt);
378 + }
379 +
380 + }
381 + }
382 + }
383 +
384 + // reschedule timer
385 + Timer.getTimer().newTimeout(this, this.probeRate,
386 + TimeUnit.MILLISECONDS);
387 + }
388 +
389 + public void removeAllPorts() {
390 + for (OFPortDesc port : sw.getPorts()) {
391 + removePort(port.getPortNo());
392 + }
393 + }
394 +
395 +}
...@@ -2,11 +2,17 @@ package org.onlab.onos.provider.of.link.impl; ...@@ -2,11 +2,17 @@ package org.onlab.onos.provider.of.link.impl;
2 2
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
5 +import java.util.Map;
6 +import java.util.concurrent.ConcurrentHashMap;
7 +
5 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
6 import org.apache.felix.scr.annotations.Component; 9 import org.apache.felix.scr.annotations.Component;
7 import org.apache.felix.scr.annotations.Deactivate; 10 import org.apache.felix.scr.annotations.Deactivate;
8 import org.apache.felix.scr.annotations.Reference; 11 import org.apache.felix.scr.annotations.Reference;
9 import org.apache.felix.scr.annotations.ReferenceCardinality; 12 import org.apache.felix.scr.annotations.ReferenceCardinality;
13 +import org.onlab.onos.net.ConnectPoint;
14 +import org.onlab.onos.net.DeviceId;
15 +import org.onlab.onos.net.PortNumber;
10 import org.onlab.onos.net.link.LinkProvider; 16 import org.onlab.onos.net.link.LinkProvider;
11 import org.onlab.onos.net.link.LinkProviderRegistry; 17 import org.onlab.onos.net.link.LinkProviderRegistry;
12 import org.onlab.onos.net.link.LinkProviderService; 18 import org.onlab.onos.net.link.LinkProviderService;
...@@ -17,6 +23,10 @@ import org.onlab.onos.of.controller.OpenFlowController; ...@@ -17,6 +23,10 @@ import org.onlab.onos.of.controller.OpenFlowController;
17 import org.onlab.onos.of.controller.OpenFlowSwitchListener; 23 import org.onlab.onos.of.controller.OpenFlowSwitchListener;
18 import org.onlab.onos.of.controller.PacketContext; 24 import org.onlab.onos.of.controller.PacketContext;
19 import org.onlab.onos.of.controller.PacketListener; 25 import org.onlab.onos.of.controller.PacketListener;
26 +import org.onlab.timer.Timer;
27 +import org.projectfloodlight.openflow.protocol.OFPortConfig;
28 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
29 +import org.projectfloodlight.openflow.protocol.OFPortState;
20 import org.projectfloodlight.openflow.protocol.OFPortStatus; 30 import org.projectfloodlight.openflow.protocol.OFPortStatus;
21 import org.slf4j.Logger; 31 import org.slf4j.Logger;
22 32
...@@ -37,6 +47,8 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid ...@@ -37,6 +47,8 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
37 47
38 private LinkProviderService providerService; 48 private LinkProviderService providerService;
39 49
50 + private final boolean useBDDP = true;
51 +
40 private final InternalLinkProvider listener = new InternalLinkProvider(); 52 private final InternalLinkProvider listener = new InternalLinkProvider();
41 53
42 /** 54 /**
...@@ -60,32 +72,61 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid ...@@ -60,32 +72,61 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
60 controller.removeListener(listener); 72 controller.removeListener(listener);
61 controller.removePacketListener(listener); 73 controller.removePacketListener(listener);
62 providerService = null; 74 providerService = null;
75 + Timer.getTimer().stop();
63 log.info("Stopped"); 76 log.info("Stopped");
64 } 77 }
65 78
66 79
67 private class InternalLinkProvider implements PacketListener, OpenFlowSwitchListener { 80 private class InternalLinkProvider implements PacketListener, OpenFlowSwitchListener {
68 81
82 + private final Map<Dpid, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
83 +
69 @Override 84 @Override
70 public void handlePacket(PacketContext pktCtx) { 85 public void handlePacket(PacketContext pktCtx) {
86 + LinkDiscovery ld = discoverers.get(pktCtx.dpid());
87 + if (ld == null) {
88 + return;
89 + }
90 + ld.handleLLDP(pktCtx.parsed(),
91 + pktCtx.inPort());
71 92
72 } 93 }
73 94
74 @Override 95 @Override
75 public void switchAdded(Dpid dpid) { 96 public void switchAdded(Dpid dpid) {
76 - // TODO Auto-generated method stub 97 + discoverers.put(dpid, new LinkDiscovery(controller.getSwitch(dpid),
98 + controller, providerService, useBDDP));
77 99
78 } 100 }
79 101
80 @Override 102 @Override
81 public void switchRemoved(Dpid dpid) { 103 public void switchRemoved(Dpid dpid) {
82 - // TODO Auto-generated method stub 104 + LinkDiscovery ld = this.discoverers.remove(dpid);
83 - 105 + if (ld != null) {
106 + ld.removeAllPorts();
107 + }
108 + providerService.linksVanished(
109 + DeviceId.deviceId("of:" + Long.toHexString(dpid.value())));
84 } 110 }
85 111
86 @Override 112 @Override
87 public void portChanged(Dpid dpid, OFPortStatus status) { 113 public void portChanged(Dpid dpid, OFPortStatus status) {
88 - // TODO Auto-generated method stub 114 + LinkDiscovery ld = discoverers.get(dpid);
115 + if (ld == null) {
116 + return;
117 + }
118 + final OFPortDesc port = status.getDesc();
119 + final boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) &&
120 + !port.getConfig().contains(OFPortConfig.PORT_DOWN);
121 + if (enabled) {
122 + ld.addPort(port);
123 + } else {
124 + ConnectPoint cp = new ConnectPoint(
125 + DeviceId.deviceId("of:" + Long.toHexString(dpid.value())),
126 + PortNumber.portNumber(port.getPortNo().getPortNumber()));
127 + providerService.linksVanished(cp);
128 + ld.removePort(port.getPortNo());
129 + }
89 130
90 } 131 }
91 132
......
...@@ -25,7 +25,10 @@ ...@@ -25,7 +25,10 @@
25 <dependency> 25 <dependency>
26 <groupId>io.netty</groupId> 26 <groupId>io.netty</groupId>
27 <artifactId>netty</artifactId> 27 <artifactId>netty</artifactId>
28 - <version>3.9.0.Final</version> 28 + </dependency>
29 + <dependency>
30 + <groupId>commons-lang</groupId>
31 + <artifactId>commons-lang</artifactId>
29 </dependency> 32 </dependency>
30 </dependencies> 33 </dependencies>
31 34
......
...@@ -21,6 +21,8 @@ import java.util.LinkedList; ...@@ -21,6 +21,8 @@ import java.util.LinkedList;
21 import java.util.List; 21 import java.util.List;
22 22
23 import org.apache.commons.lang.ArrayUtils; 23 import org.apache.commons.lang.ArrayUtils;
24 +import org.slf4j.Logger;
25 +import org.slf4j.LoggerFactory;
24 26
25 27
26 /** 28 /**
...@@ -31,6 +33,7 @@ import org.apache.commons.lang.ArrayUtils; ...@@ -31,6 +33,7 @@ import org.apache.commons.lang.ArrayUtils;
31 @SuppressWarnings("rawtypes") 33 @SuppressWarnings("rawtypes")
32 public class ONLabLddp extends LLDP { 34 public class ONLabLddp extends LLDP {
33 35
36 + private static final Logger log = LoggerFactory.getLogger(ONLabLddp.class);
34 // ON.Lab OUI and OVX name for organizationally specific TLVs 37 // ON.Lab OUI and OVX name for organizationally specific TLVs
35 public static final byte[] ONLAB_OUI = {(byte) 0xa4, 0x23, 0x05}; 38 public static final byte[] ONLAB_OUI = {(byte) 0xa4, 0x23, 0x05};
36 public static final String OVX_NAME = "OpenVirteX"; 39 public static final String OVX_NAME = "OpenVirteX";
...@@ -50,7 +53,7 @@ public class ONLabLddp extends LLDP { ...@@ -50,7 +53,7 @@ public class ONLabLddp extends LLDP {
50 private static final byte CHASSIS_TLV_SUBTYPE = 4; 53 private static final byte CHASSIS_TLV_SUBTYPE = 4;
51 54
52 private static final byte PORT_TLV_TYPE = 2; 55 private static final byte PORT_TLV_TYPE = 2;
53 - private static final byte PORT_TLV_SIZE = 7; 56 + private static final byte PORT_TLV_SIZE = 5;
54 private static final byte PORT_TLV_SUBTYPE = 2; 57 private static final byte PORT_TLV_SUBTYPE = 2;
55 58
56 private static final byte TTL_TLV_TYPE = 3; 59 private static final byte TTL_TLV_TYPE = 3;
...@@ -60,7 +63,7 @@ public class ONLabLddp extends LLDP { ...@@ -60,7 +63,7 @@ public class ONLabLddp extends LLDP {
60 // 4 = OUI (3) + subtype (1) 63 // 4 = OUI (3) + subtype (1)
61 private static final byte NAME_TLV_SIZE = (byte) (4 + ONLabLddp.OVX_NAME.length()); 64 private static final byte NAME_TLV_SIZE = (byte) (4 + ONLabLddp.OVX_NAME.length());
62 private static final byte NAME_TLV_SUBTYPE = 1; 65 private static final byte NAME_TLV_SUBTYPE = 1;
63 - private static final short NAME_TLV_OFFSET = 32; 66 + private static final short NAME_TLV_OFFSET = 34;
64 private static final short NAME_TLV_HEADER = (short) ((NAME_TLV_TYPE << 9) | NAME_TLV_SIZE); 67 private static final short NAME_TLV_HEADER = (short) ((NAME_TLV_TYPE << 9) | NAME_TLV_SIZE);
65 // Contents of full name TLV 68 // Contents of full name TLV
66 private static final byte[] NAME_TLV = ByteBuffer.allocate(NAME_TLV_SIZE + 2) 69 private static final byte[] NAME_TLV = ByteBuffer.allocate(NAME_TLV_SIZE + 2)
...@@ -85,7 +88,7 @@ public class ONLabLddp extends LLDP { ...@@ -85,7 +88,7 @@ public class ONLabLddp extends LLDP {
85 // Default switch, port number and TTL 88 // Default switch, port number and TTL
86 private static final byte[] DEFAULT_DPID = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 89 private static final byte[] DEFAULT_DPID = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00 }; 90 0x00, 0x00 };
88 - private static final short DEFAULT_PORT = 0; 91 + private static final int DEFAULT_PORT = 0;
89 private static final short DEFAULT_TTL = 120; // in seconds 92 private static final short DEFAULT_TTL = 120; // in seconds
90 93
91 // Minimum and OVX-generated LLDP packet sizes 94 // Minimum and OVX-generated LLDP packet sizes
...@@ -97,7 +100,7 @@ public class ONLabLddp extends LLDP { ...@@ -97,7 +100,7 @@ public class ONLabLddp extends LLDP {
97 // Field offsets in OVX-generated LLDP 100 // Field offsets in OVX-generated LLDP
98 private static final short ETHERTYPE_OFFSET = 12; 101 private static final short ETHERTYPE_OFFSET = 12;
99 private static final short PORT_OFFSET = 26; 102 private static final short PORT_OFFSET = 26;
100 - private static final short DPID_OFFSET = 54; 103 + private static final short DPID_OFFSET = 56;
101 104
102 // Private member fields 105 // Private member fields
103 // Byte arrays for TLV information string 106 // Byte arrays for TLV information string
...@@ -167,10 +170,10 @@ public class ONLabLddp extends LLDP { ...@@ -167,10 +170,10 @@ public class ONLabLddp extends LLDP {
167 * 170 *
168 * @param portNumber the port number 171 * @param portNumber the port number
169 */ 172 */
170 - private void setPortTLV(final long portNumber) { 173 + private void setPortTLV(final int portNumber) {
171 this.bb = ByteBuffer.wrap(this.portId); 174 this.bb = ByteBuffer.wrap(this.portId);
172 this.bb.put(PORT_TLV_SUBTYPE); 175 this.bb.put(PORT_TLV_SUBTYPE);
173 - this.bb.putLong(portNumber); 176 + this.bb.putInt(portNumber);
174 177
175 this.portTLV.setLength(PORT_TLV_SIZE); 178 this.portTLV.setLength(PORT_TLV_SIZE);
176 this.portTLV.setType(PORT_TLV_TYPE); 179 this.portTLV.setType(PORT_TLV_TYPE);
...@@ -240,8 +243,8 @@ public class ONLabLddp extends LLDP { ...@@ -240,8 +243,8 @@ public class ONLabLddp extends LLDP {
240 * 243 *
241 * @param port the port instance 244 * @param port the port instance
242 */ 245 */
243 - public void setPort(long port) { 246 + public void setPort(int port) {
244 - long portNumber = port; 247 + int portNumber = port;
245 this.setPortTLV(portNumber); 248 this.setPortTLV(portNumber);
246 } 249 }
247 250
...@@ -335,7 +338,7 @@ public class ONLabLddp extends LLDP { ...@@ -335,7 +338,7 @@ public class ONLabLddp extends LLDP {
335 * @param packet 338 * @param packet
336 * @return Dpid and port 339 * @return Dpid and port
337 */ 340 */
338 - /* public static long parseLLDP(final byte[] packet) { 341 + public static DPIDandPort parseLLDP(final byte[] packet) {
339 final ByteBuffer bb = ByteBuffer.wrap(packet); 342 final ByteBuffer bb = ByteBuffer.wrap(packet);
340 343
341 // Extra offset due to VLAN tag 344 // Extra offset due to VLAN tag
...@@ -345,10 +348,30 @@ public class ONLabLddp extends LLDP { ...@@ -345,10 +348,30 @@ public class ONLabLddp extends LLDP {
345 offset = 4; 348 offset = 4;
346 } 349 }
347 350
348 - final short port = bb.getLong(PORT_OFFSET + offset); 351 + final int port = bb.getInt(PORT_OFFSET + offset);
349 final long dpid = bb.getLong(DPID_OFFSET + offset); 352 final long dpid = bb.getLong(DPID_OFFSET + offset);
350 353
351 - return dpid 354 + return new DPIDandPort(dpid, port);
352 } 355 }
353 - */ 356 +
357 + public static class DPIDandPort {
358 +
359 + private final long dpid;
360 + private final int port;
361 +
362 + public DPIDandPort(long dpid, int port) {
363 + this.dpid = dpid;
364 + this.port = port;
365 + }
366 +
367 + public long getDpid() {
368 + return this.dpid;
369 + }
370 +
371 + public int getPort() {
372 + return this.port;
373 + }
374 +
375 + }
376 +
354 } 377 }
......
1 +package org.onlab.timer;
2 +
3 +import org.jboss.netty.util.HashedWheelTimer;
4 +
5 +
6 +public final class Timer {
7 +
8 + private Timer() {}
9 +
10 + private static HashedWheelTimer timer;
11 +
12 + public static HashedWheelTimer getTimer() {
13 + if (Timer.timer == null) {
14 + Timer.timer = new HashedWheelTimer();
15 + Timer.timer.start();
16 + }
17 + return Timer.timer;
18 + }
19 +
20 +}