Showing
14 changed files
with
792 additions
and
282 deletions
... | @@ -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,13 +42,12 @@ public class ConnectPoint { | ... | @@ -42,13 +42,12 @@ 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; |
49 | } | 48 | } |
50 | throw new IllegalStateException("Connection point not associated " + | 49 | throw new IllegalStateException("Connection point not associated " + |
51 | - "with an infrastructure device"); | 50 | + "with an infrastructure device"); |
52 | } | 51 | } |
53 | 52 | ||
54 | /** | 53 | /** |
... | @@ -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"; |
... | @@ -45,7 +46,7 @@ public class SimpleLinkManager | ... | @@ -45,7 +46,7 @@ public class SimpleLinkManager |
45 | private final Logger log = getLogger(getClass()); | 46 | private final Logger log = getLogger(getClass()); |
46 | 47 | ||
47 | private final AbstractListenerRegistry<LinkEvent, LinkListener> | 48 | private final AbstractListenerRegistry<LinkEvent, LinkListener> |
48 | - listenerRegistry = new AbstractListenerRegistry<>(); | 49 | + listenerRegistry = new AbstractListenerRegistry<>(); |
49 | 50 | ||
50 | private final SimpleLinkStore store = new SimpleLinkStore(); | 51 | private final SimpleLinkStore store = new SimpleLinkStore(); |
51 | 52 | ||
... | @@ -83,7 +84,7 @@ public class SimpleLinkManager | ... | @@ -83,7 +84,7 @@ public class SimpleLinkManager |
83 | public Set<Link> getDeviceLinks(DeviceId deviceId) { | 84 | public Set<Link> getDeviceLinks(DeviceId deviceId) { |
84 | checkNotNull(deviceId, DEVICE_ID_NULL); | 85 | checkNotNull(deviceId, DEVICE_ID_NULL); |
85 | return Sets.union(store.getDeviceEgressLinks(deviceId), | 86 | return Sets.union(store.getDeviceEgressLinks(deviceId), |
86 | - store.getDeviceIngressLinks(deviceId)); | 87 | + store.getDeviceIngressLinks(deviceId)); |
87 | } | 88 | } |
88 | 89 | ||
89 | @Override | 90 | @Override |
... | @@ -102,7 +103,7 @@ public class SimpleLinkManager | ... | @@ -102,7 +103,7 @@ public class SimpleLinkManager |
102 | public Set<Link> getLinks(ConnectPoint connectPoint) { | 103 | public Set<Link> getLinks(ConnectPoint connectPoint) { |
103 | checkNotNull(connectPoint, CONNECT_POINT_NULL); | 104 | checkNotNull(connectPoint, CONNECT_POINT_NULL); |
104 | return Sets.union(store.getEgressLinks(connectPoint), | 105 | return Sets.union(store.getEgressLinks(connectPoint), |
105 | - store.getIngressLinks(connectPoint)); | 106 | + store.getIngressLinks(connectPoint)); |
106 | } | 107 | } |
107 | 108 | ||
108 | @Override | 109 | @Override |
... | @@ -146,7 +147,7 @@ public class SimpleLinkManager | ... | @@ -146,7 +147,7 @@ public class SimpleLinkManager |
146 | 147 | ||
147 | // Personalized link provider service issued to the supplied provider. | 148 | // Personalized link provider service issued to the supplied provider. |
148 | private class InternalLinkProviderService extends AbstractProviderService<LinkProvider> | 149 | private class InternalLinkProviderService extends AbstractProviderService<LinkProvider> |
149 | - implements LinkProviderService { | 150 | + implements LinkProviderService { |
150 | 151 | ||
151 | public InternalLinkProviderService(LinkProvider provider) { | 152 | public InternalLinkProviderService(LinkProvider provider) { |
152 | super(provider); | 153 | super(provider); |
... | @@ -156,9 +157,9 @@ public class SimpleLinkManager | ... | @@ -156,9 +157,9 @@ 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); |
163 | } | 164 | } |
164 | 165 | ||
... | @@ -168,7 +169,7 @@ public class SimpleLinkManager | ... | @@ -168,7 +169,7 @@ public class SimpleLinkManager |
168 | checkValidity(); | 169 | checkValidity(); |
169 | log.info("Link {} vanished", linkDescription); | 170 | log.info("Link {} vanished", linkDescription); |
170 | LinkEvent event = store.removeLink(linkDescription.src(), | 171 | LinkEvent event = store.removeLink(linkDescription.src(), |
171 | - linkDescription.dst()); | 172 | + linkDescription.dst()); |
172 | post(event); | 173 | post(event); |
173 | } | 174 | } |
174 | 175 | ... | ... |
... | @@ -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 { |
... | @@ -42,238 +44,244 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -42,238 +44,244 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
42 | protected Set<OpenFlowSwitchListener> ofEventListener = | 44 | protected Set<OpenFlowSwitchListener> ofEventListener = |
43 | new HashSet<>(); | 45 | new HashSet<>(); |
44 | 46 | ||
45 | - protected List<PacketListener> ofPacketListener = | 47 | + protected List<PacketListener> ofPacketListener = |
46 | - new ArrayList<>(); | 48 | + new ArrayList<>(); |
47 | - | 49 | + |
48 | - private final Controller ctrl = new Controller(); | 50 | + private final Controller ctrl = new Controller(); |
49 | - | 51 | + |
50 | - @Activate | 52 | + @Activate |
51 | - public void activate() { | 53 | + public void activate() { |
52 | - ctrl.start(agent); | 54 | + ctrl.start(agent); |
53 | - } | 55 | + } |
54 | - | 56 | + |
55 | - @Deactivate | 57 | + @Deactivate |
56 | - public void deactivate() { | 58 | + public void deactivate() { |
57 | - ctrl.stop(); | 59 | + ctrl.stop(); |
58 | - } | 60 | + } |
59 | - | 61 | + |
60 | - @Override | 62 | + @Override |
61 | - public Iterable<OpenFlowSwitch> getSwitches() { | 63 | + public Iterable<OpenFlowSwitch> getSwitches() { |
62 | - return connectedSwitches.values(); | 64 | + return connectedSwitches.values(); |
63 | - } | 65 | + } |
64 | - | 66 | + |
65 | - @Override | 67 | + @Override |
66 | - public Iterable<OpenFlowSwitch> getMasterSwitches() { | 68 | + public Iterable<OpenFlowSwitch> getMasterSwitches() { |
67 | - return activeMasterSwitches.values(); | 69 | + return activeMasterSwitches.values(); |
68 | - } | 70 | + } |
69 | - | 71 | + |
70 | - @Override | 72 | + @Override |
71 | - public Iterable<OpenFlowSwitch> getEqualSwitches() { | 73 | + public Iterable<OpenFlowSwitch> getEqualSwitches() { |
72 | - return activeEqualSwitches.values(); | 74 | + return activeEqualSwitches.values(); |
73 | - } | 75 | + } |
74 | - | 76 | + |
75 | - @Override | 77 | + @Override |
76 | - public OpenFlowSwitch getSwitch(Dpid dpid) { | 78 | + public OpenFlowSwitch getSwitch(Dpid dpid) { |
77 | - return connectedSwitches.get(dpid); | 79 | + return connectedSwitches.get(dpid); |
78 | - } | 80 | + } |
79 | - | 81 | + |
80 | - @Override | 82 | + @Override |
81 | - public OpenFlowSwitch getMasterSwitch(Dpid dpid) { | 83 | + public OpenFlowSwitch getMasterSwitch(Dpid dpid) { |
82 | - return activeMasterSwitches.get(dpid); | 84 | + return activeMasterSwitches.get(dpid); |
83 | - } | 85 | + } |
84 | - | 86 | + |
85 | - @Override | 87 | + @Override |
86 | - public OpenFlowSwitch getEqualSwitch(Dpid dpid) { | 88 | + public OpenFlowSwitch getEqualSwitch(Dpid dpid) { |
87 | - return activeEqualSwitches.get(dpid); | 89 | + return activeEqualSwitches.get(dpid); |
88 | - } | 90 | + } |
89 | - | 91 | + |
90 | - @Override | 92 | + @Override |
91 | - public void addListener(OpenFlowSwitchListener listener) { | 93 | + public void addListener(OpenFlowSwitchListener listener) { |
92 | - if (!ofEventListener.contains(listener)) { | 94 | + if (!ofEventListener.contains(listener)) { |
93 | - this.ofEventListener.add(listener); | 95 | + this.ofEventListener.add(listener); |
94 | - } | 96 | + } |
95 | - } | 97 | + } |
96 | - | 98 | + |
97 | - @Override | 99 | + @Override |
98 | - public void removeListener(OpenFlowSwitchListener listener) { | 100 | + public void removeListener(OpenFlowSwitchListener listener) { |
99 | - this.ofEventListener.remove(listener); | 101 | + this.ofEventListener.remove(listener); |
100 | - } | 102 | + } |
101 | - | 103 | + |
102 | - @Override | 104 | + @Override |
103 | - public void addPacketListener(int priority, PacketListener listener) { | 105 | + public void addPacketListener(int priority, PacketListener listener) { |
104 | - ofPacketListener.add(priority, listener); | 106 | + ofPacketListener.add(priority, listener); |
105 | - } | 107 | + } |
106 | - | 108 | + |
107 | - @Override | 109 | + @Override |
108 | - public void removePacketListener(PacketListener listener) { | 110 | + public void removePacketListener(PacketListener listener) { |
109 | - ofPacketListener.remove(listener); | 111 | + ofPacketListener.remove(listener); |
110 | - } | 112 | + } |
111 | - | 113 | + |
112 | - @Override | 114 | + @Override |
113 | - public void write(Dpid dpid, OFMessage msg) { | 115 | + public void write(Dpid dpid, OFMessage msg) { |
114 | - this.getSwitch(dpid).sendMsg(msg); | 116 | + this.getSwitch(dpid).sendMsg(msg); |
115 | - } | 117 | + } |
116 | - | 118 | + |
117 | - @Override | 119 | + @Override |
118 | - public void processPacket(Dpid dpid, OFMessage msg) { | 120 | + public void processPacket(Dpid dpid, OFMessage msg) { |
119 | - switch (msg.getType()) { | 121 | + switch (msg.getType()) { |
120 | - case PORT_STATUS: | 122 | + case PORT_STATUS: |
121 | - for (OpenFlowSwitchListener l : ofEventListener) { | 123 | + for (OpenFlowSwitchListener l : ofEventListener) { |
122 | - l.portChanged(dpid, (OFPortStatus) msg); | 124 | + l.portChanged(dpid, (OFPortStatus) msg); |
123 | - } | 125 | + } |
124 | - break; | 126 | + break; |
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 |
129 | - } | 131 | + .packetContextFromPacketIn(this.getSwitch(dpid), |
130 | - break; | 132 | + (OFPacketIn) msg)); |
131 | - default: | 133 | + } |
132 | - log.warn("Handling message type {} not yet implemented", msg.getType()); | 134 | + break; |
133 | - } | 135 | + default: |
134 | - } | 136 | + log.warn("Handling message type {} not yet implemented {}", |
135 | - | 137 | + msg.getType(), msg); |
136 | - @Override | 138 | + } |
137 | - public void setRole(Dpid dpid, RoleState role) { | 139 | + } |
138 | - getSwitch(dpid).setRole(role); | 140 | + |
139 | - } | 141 | + @Override |
140 | - | 142 | + public void setRole(Dpid dpid, RoleState role) { |
141 | - /** | 143 | + getSwitch(dpid).setRole(role); |
142 | - * Implementation of an OpenFlow Agent which is responsible for | 144 | + } |
143 | - * keeping track of connected switches and the state in which | 145 | + |
144 | - * they are. | 146 | + /** |
145 | - */ | 147 | + * Implementation of an OpenFlow Agent which is responsible for |
146 | - public class OpenFlowSwitchAgent implements OpenFlowAgent { | 148 | + * keeping track of connected switches and the state in which |
147 | - | 149 | + * they are. |
148 | - private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class); | 150 | + */ |
149 | - private final Lock switchLock = new ReentrantLock(); | 151 | + public class OpenFlowSwitchAgent implements OpenFlowAgent { |
150 | - | 152 | + |
151 | - @Override | 153 | + private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class); |
152 | - public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) { | 154 | + private final Lock switchLock = new ReentrantLock(); |
153 | - if (connectedSwitches.get(dpid) != null) { | 155 | + |
154 | - log.error("Trying to add connectedSwitch but found a previous " | 156 | + @Override |
155 | - + "value for dpid: {}", dpid); | 157 | + public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) { |
156 | - return false; | 158 | + if (connectedSwitches.get(dpid) != null) { |
157 | - } else { | 159 | + log.error("Trying to add connectedSwitch but found a previous " |
158 | - log.error("Added switch {}", dpid); | 160 | + + "value for dpid: {}", dpid); |
159 | - connectedSwitches.put(dpid, sw); | 161 | + return false; |
160 | - for (OpenFlowSwitchListener l : ofEventListener) { | 162 | + } else { |
161 | - l.switchAdded(dpid); | 163 | + log.error("Added switch {}", dpid); |
162 | - } | 164 | + connectedSwitches.put(dpid, sw); |
163 | - return true; | 165 | + for (OpenFlowSwitchListener l : ofEventListener) { |
164 | - } | 166 | + l.switchAdded(dpid); |
165 | - } | 167 | + } |
166 | - | 168 | + return true; |
167 | - @Override | 169 | + } |
168 | - public boolean validActivation(Dpid dpid) { | 170 | + } |
169 | - if (connectedSwitches.get(dpid) == null) { | 171 | + |
170 | - log.error("Trying to activate switch but is not in " | 172 | + @Override |
171 | - + "connected switches: dpid {}. Aborting ..", | 173 | + public boolean validActivation(Dpid dpid) { |
172 | - dpid); | 174 | + if (connectedSwitches.get(dpid) == null) { |
173 | - return false; | 175 | + log.error("Trying to activate switch but is not in " |
174 | - } | 176 | + + "connected switches: dpid {}. Aborting ..", |
175 | - if (activeMasterSwitches.get(dpid) != null || | 177 | + dpid); |
176 | - activeEqualSwitches.get(dpid) != null) { | 178 | + return false; |
177 | - log.error("Trying to activate switch but it is already " | 179 | + } |
178 | - + "activated: dpid {}. Found in activeMaster: {} " | 180 | + if (activeMasterSwitches.get(dpid) != null || |
179 | - + "Found in activeEqual: {}. Aborting ..", new Object[]{ | 181 | + activeEqualSwitches.get(dpid) != null) { |
180 | - dpid, | 182 | + log.error("Trying to activate switch but it is already " |
181 | - (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y', | 183 | + + "activated: dpid {}. Found in activeMaster: {} " |
182 | - (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'}); | 184 | + + "Found in activeEqual: {}. Aborting ..", new Object[]{ |
183 | - return false; | 185 | + dpid, |
184 | - } | 186 | + (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y', |
185 | - return true; | 187 | + (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'}); |
186 | - } | 188 | + return false; |
187 | - | 189 | + } |
188 | - | 190 | + return true; |
189 | - @Override | 191 | + } |
190 | - public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) { | 192 | + |
191 | - switchLock.lock(); | 193 | + |
192 | - try { | 194 | + @Override |
193 | - if (!validActivation(dpid)) { | 195 | + public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) { |
194 | - return false; | 196 | + switchLock.lock(); |
195 | - } | 197 | + try { |
196 | - activeMasterSwitches.put(dpid, sw); | 198 | + if (!validActivation(dpid)) { |
197 | - return true; | 199 | + return false; |
198 | - } finally { | 200 | + } |
199 | - switchLock.unlock(); | 201 | + activeMasterSwitches.put(dpid, sw); |
200 | - } | 202 | + return true; |
201 | - } | 203 | + } finally { |
202 | - | 204 | + switchLock.unlock(); |
203 | - @Override | 205 | + } |
204 | - public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) { | 206 | + } |
205 | - switchLock.lock(); | 207 | + |
206 | - try { | 208 | + @Override |
207 | - if (!validActivation(dpid)) { | 209 | + public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) { |
208 | - return false; | 210 | + switchLock.lock(); |
209 | - } | 211 | + try { |
210 | - activeEqualSwitches.put(dpid, sw); | 212 | + if (!validActivation(dpid)) { |
211 | - log.info("Added Activated EQUAL Switch {}", dpid); | 213 | + return false; |
212 | - return true; | 214 | + } |
213 | - } finally { | 215 | + activeEqualSwitches.put(dpid, sw); |
214 | - switchLock.unlock(); | 216 | + log.info("Added Activated EQUAL Switch {}", dpid); |
215 | - } | 217 | + return true; |
216 | - } | 218 | + } finally { |
217 | - | 219 | + switchLock.unlock(); |
218 | - @Override | 220 | + } |
219 | - public void transitionToMasterSwitch(Dpid dpid) { | 221 | + } |
220 | - switchLock.lock(); | 222 | + |
221 | - try { | 223 | + @Override |
222 | - if (activeMasterSwitches.containsKey(dpid)) { | 224 | + public void transitionToMasterSwitch(Dpid dpid) { |
223 | - return; | 225 | + switchLock.lock(); |
224 | - } | 226 | + try { |
225 | - OpenFlowSwitch sw = activeEqualSwitches.remove(dpid); | 227 | + if (activeMasterSwitches.containsKey(dpid)) { |
226 | - if (sw == null) { | 228 | + return; |
227 | - log.error("Transition to master called on sw {}, but switch " | 229 | + } |
228 | - + "was not found in controller-cache", dpid); | 230 | + OpenFlowSwitch sw = activeEqualSwitches.remove(dpid); |
229 | - return; | 231 | + if (sw == null) { |
230 | - } | 232 | + sw = getSwitch(dpid); |
231 | - log.info("Transitioned switch {} to MASTER", dpid); | 233 | + if (sw == null) { |
232 | - activeMasterSwitches.put(dpid, sw); | 234 | + log.error("Transition to master called on sw {}, but switch " |
233 | - } finally { | 235 | + + "was not found in controller-cache", dpid); |
234 | - switchLock.unlock(); | 236 | + return; |
235 | - } | 237 | + } |
236 | - } | 238 | + } |
237 | - | 239 | + log.info("Transitioned switch {} to MASTER", dpid); |
238 | - | 240 | + activeMasterSwitches.put(dpid, sw); |
239 | - @Override | 241 | + } finally { |
240 | - public void transitionToEqualSwitch(Dpid dpid) { | 242 | + switchLock.unlock(); |
241 | - switchLock.lock(); | 243 | + } |
242 | - try { | 244 | + } |
243 | - if (activeEqualSwitches.containsKey(dpid)) { | 245 | + |
244 | - return; | 246 | + |
245 | - } | 247 | + @Override |
246 | - OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); | 248 | + public void transitionToEqualSwitch(Dpid dpid) { |
247 | - if (sw == null) { | 249 | + switchLock.lock(); |
248 | - log.error("Transition to equal called on sw {}, but switch " | 250 | + try { |
249 | - + "was not found in controller-cache", dpid); | 251 | + if (activeEqualSwitches.containsKey(dpid)) { |
250 | - return; | 252 | + return; |
251 | - } | 253 | + } |
252 | - log.info("Transitioned switch {} to EQUAL", dpid); | 254 | + OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); |
253 | - activeEqualSwitches.put(dpid, sw); | 255 | + if (sw == null) { |
254 | - } finally { | 256 | + log.error("Transition to equal called on sw {}, but switch " |
255 | - switchLock.unlock(); | 257 | + + "was not found in controller-cache", dpid); |
256 | - } | 258 | + return; |
257 | - | 259 | + } |
258 | - } | 260 | + log.info("Transitioned switch {} to EQUAL", dpid); |
259 | - | 261 | + activeEqualSwitches.put(dpid, sw); |
260 | - @Override | 262 | + } finally { |
261 | - public void removeConnectedSwitch(Dpid dpid) { | 263 | + switchLock.unlock(); |
262 | - connectedSwitches.remove(dpid); | 264 | + } |
263 | - OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); | 265 | + |
264 | - if (sw == null) { | 266 | + } |
265 | - sw = activeEqualSwitches.remove(dpid); | 267 | + |
266 | - } | 268 | + @Override |
267 | - for (OpenFlowSwitchListener l : ofEventListener) { | 269 | + public void removeConnectedSwitch(Dpid dpid) { |
268 | - l.switchRemoved(dpid); | 270 | + connectedSwitches.remove(dpid); |
269 | - } | 271 | + OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); |
270 | - } | 272 | + if (sw == null) { |
271 | - | 273 | + sw = activeEqualSwitches.remove(dpid); |
272 | - @Override | 274 | + } |
273 | - public void processMessage(Dpid dpid, OFMessage m) { | 275 | + for (OpenFlowSwitchListener l : ofEventListener) { |
274 | - processPacket(dpid, m); | 276 | + l.switchRemoved(dpid); |
275 | - } | 277 | + } |
276 | - } | 278 | + } |
279 | + | ||
280 | + @Override | ||
281 | + public void processMessage(Dpid dpid, OFMessage m) { | ||
282 | + processPacket(dpid, m); | ||
283 | + } | ||
284 | + } | ||
277 | 285 | ||
278 | 286 | ||
279 | } | 287 | } | ... | ... |
... | @@ -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 | ... | ... |
... | @@ -61,6 +61,14 @@ | ... | @@ -61,6 +61,14 @@ |
61 | <version>18.0</version> | 61 | <version>18.0</version> |
62 | </dependency> | 62 | </dependency> |
63 | 63 | ||
64 | + <dependency> | ||
65 | + <groupId>io.netty</groupId> | ||
66 | + <artifactId>netty</artifactId> | ||
67 | + <version>3.9.0.Final</version> | ||
68 | + </dependency> | ||
69 | + | ||
70 | + | ||
71 | + | ||
64 | <dependency> | 72 | <dependency> |
65 | <groupId>com.google.guava</groupId> | 73 | <groupId>com.google.guava</groupId> |
66 | <artifactId>guava-testlib</artifactId> | 74 | <artifactId>guava-testlib</artifactId> | ... | ... |
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 | +} |
-
Please register or login to post a comment