tom

Added javadocs and simplified the reactive fwd app in attempt to find the glitch; no dice

...@@ -5,14 +5,31 @@ import org.apache.felix.scr.annotations.Component; ...@@ -5,14 +5,31 @@ import org.apache.felix.scr.annotations.Component;
5 import org.apache.felix.scr.annotations.Deactivate; 5 import org.apache.felix.scr.annotations.Deactivate;
6 import org.apache.felix.scr.annotations.Reference; 6 import org.apache.felix.scr.annotations.Reference;
7 import org.apache.felix.scr.annotations.ReferenceCardinality; 7 import org.apache.felix.scr.annotations.ReferenceCardinality;
8 +import org.onlab.onos.net.Host;
9 +import org.onlab.onos.net.HostId;
10 +import org.onlab.onos.net.Path;
11 +import org.onlab.onos.net.PortNumber;
12 +import org.onlab.onos.net.flow.Instructions;
8 import org.onlab.onos.net.host.HostService; 13 import org.onlab.onos.net.host.HostService;
14 +import org.onlab.onos.net.packet.InboundPacket;
15 +import org.onlab.onos.net.packet.PacketContext;
9 import org.onlab.onos.net.packet.PacketProcessor; 16 import org.onlab.onos.net.packet.PacketProcessor;
10 import org.onlab.onos.net.packet.PacketService; 17 import org.onlab.onos.net.packet.PacketService;
11 import org.onlab.onos.net.topology.TopologyService; 18 import org.onlab.onos.net.topology.TopologyService;
19 +import org.slf4j.Logger;
12 20
13 -@Component 21 +import java.util.Set;
22 +
23 +import static org.slf4j.LoggerFactory.getLogger;
24 +
25 +/**
26 + * Sample reactive forwarding application.
27 + */
28 +@Component(immediate = true)
14 public class ReactiveForwarding { 29 public class ReactiveForwarding {
15 30
31 + private final Logger log = getLogger(getClass());
32 +
16 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 33 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
17 protected TopologyService topologyService; 34 protected TopologyService topologyService;
18 35
...@@ -22,18 +39,99 @@ public class ReactiveForwarding { ...@@ -22,18 +39,99 @@ public class ReactiveForwarding {
22 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 39 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
23 protected HostService hostService; 40 protected HostService hostService;
24 41
25 - private ReactivePacketProcessor processor; 42 + private ReactivePacketProcessor processor = new ReactivePacketProcessor();
26 43
27 @Activate 44 @Activate
28 public void activate() { 45 public void activate() {
29 - processor = new ReactivePacketProcessor(topologyService, hostService);
30 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1); 46 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1);
47 + log.info("Started");
31 } 48 }
32 49
33 @Deactivate 50 @Deactivate
34 public void deactivate() { 51 public void deactivate() {
35 packetService.removeProcessor(processor); 52 packetService.removeProcessor(processor);
36 processor = null; 53 processor = null;
54 + log.info("Stopped");
55 + }
56 +
57 +
58 + /**
59 + * Packet processor responsible for forwarding packets along their paths.
60 + */
61 + private class ReactivePacketProcessor implements PacketProcessor {
62 +
63 + @Override
64 + public void process(PacketContext context) {
65 + InboundPacket pkt = context.inPacket();
66 + HostId id = HostId.hostId(pkt.parsed().getDestinationMAC());
67 +
68 + // Do we know who this is for? If not, flood and bail.
69 + Host dst = hostService.getHost(id);
70 + if (dst == null) {
71 + flood(context);
72 + return;
73 + }
74 +
75 + // Are we on an edge switch that our destination is on? If so,
76 + // simply forward out to the destination and bail.
77 + if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) {
78 + forward(context, dst.location().port());
79 + return;
80 + }
81 +
82 + // Otherwise, get a set of paths that lead from here to the
83 + // destination edge switch.
84 + Set<Path> paths = topologyService.getPaths(topologyService.currentTopology(),
85 + context.inPacket().receivedFrom().deviceId(),
86 + dst.location().deviceId());
87 + if (paths.isEmpty()) {
88 + // If there are no paths, flood and bail.
89 + flood(context);
90 + return;
91 + }
92 +
93 + // Otherwise, pick a path that does not lead back to where we
94 + // came from; if no such path, flood and bail.
95 + Path path = pickForwardPath(paths, pkt.receivedFrom().port());
96 + if (path == null) {
97 + log.warn("Doh... don't know where to go...");
98 + flood(context);
99 + return;
100 + }
101 +
102 + // Otherwise forward and be done with it.
103 + forward(context, path.src().port());
104 + }
105 + }
106 +
107 + // Selects a path from the given set that does not lead back to the
108 + // specified port.
109 + private Path pickForwardPath(Set<Path> paths, PortNumber notToPort) {
110 + for (Path path : paths) {
111 + if (!path.src().port().equals(notToPort)) {
112 + return path;
113 + }
114 + }
115 + return null;
116 + }
117 +
118 + // Floods the specified packet.
119 + private void flood(PacketContext context) {
120 + boolean canBcast = topologyService.isBroadcastPoint(topologyService.currentTopology(),
121 + context.inPacket().receivedFrom());
122 + if (canBcast) {
123 + forward(context, PortNumber.FLOOD);
124 + } else {
125 + context.block();
126 + }
127 + }
128 +
129 + // Forwards the packet to the specified port.
130 + private void forward(PacketContext context, PortNumber portNumber) {
131 + context.treatmentBuilder().add(Instructions.createOutput(portNumber));
132 + context.send();
37 } 133 }
134 +
38 } 135 }
39 136
137 +
......
1 -package org.onlab.onos.fwd;
2 -
3 -import static org.slf4j.LoggerFactory.getLogger;
4 -
5 -import java.util.Set;
6 -
7 -import org.onlab.onos.net.Host;
8 -import org.onlab.onos.net.HostId;
9 -import org.onlab.onos.net.Path;
10 -import org.onlab.onos.net.PortNumber;
11 -import org.onlab.onos.net.flow.Instructions;
12 -import org.onlab.onos.net.host.HostService;
13 -import org.onlab.onos.net.packet.InboundPacket;
14 -import org.onlab.onos.net.packet.PacketContext;
15 -import org.onlab.onos.net.packet.PacketProcessor;
16 -import org.onlab.onos.net.topology.TopologyService;
17 -import org.onlab.packet.VLANID;
18 -import org.slf4j.Logger;
19 -
20 -public class ReactivePacketProcessor implements PacketProcessor {
21 -
22 - private final Logger log = getLogger(getClass());
23 - private final TopologyService topologyService;
24 - private final HostService hostService;
25 -
26 -
27 - public ReactivePacketProcessor(TopologyService topologyService, HostService hostService) {
28 - this.topologyService = topologyService;
29 - this.hostService = hostService;
30 - }
31 -
32 -
33 - @Override
34 - public void process(PacketContext context) {
35 - InboundPacket pkt = context.inPacket();
36 - HostId id = HostId.hostId(pkt.parsed().getDestinationMAC(), VLANID.vlanId((short) -1));
37 - Host dst = hostService.getHost(id);
38 - if (dst == null) {
39 - flood(context);
40 - return;
41 - }
42 -
43 - Set<Path> p = null;
44 - if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) {
45 - context.treatmentBuilder().add(Instructions.createOutput(dst.location().port()));
46 - context.send();
47 - return;
48 - } else {
49 - p = topologyService.getPaths(topologyService.currentTopology(),
50 - context.inPacket().receivedFrom().deviceId(), dst.location().deviceId());
51 - }
52 -
53 - if (p.isEmpty()) {
54 - flood(context);
55 - } else {
56 - Path p1 = p.iterator().next();
57 - context.treatmentBuilder().add(Instructions.createOutput(p1.src().port()));
58 - context.send();
59 - }
60 -
61 - }
62 -
63 - private void flood(PacketContext context) {
64 - boolean canBcast = topologyService.isBroadcastPoint(topologyService.currentTopology(),
65 - context.inPacket().receivedFrom());
66 - if (canBcast) {
67 - context.treatmentBuilder().add(Instructions.createOutput(PortNumber.FLOOD));
68 - context.send();
69 - } else {
70 - context.block();
71 - }
72 - }
73 -
74 -}
1 +/**
2 + * Trivial application that provides simple form of reactive forwarding.
3 + */
4 +package org.onlab.onos.fwd;
...\ No newline at end of file ...\ No newline at end of file
...@@ -42,10 +42,19 @@ public final class HostId extends ElementId { ...@@ -42,10 +42,19 @@ public final class HostId extends ElementId {
42 * @param vlanId vlan identifier 42 * @param vlanId vlan identifier
43 * @return host identifier 43 * @return host identifier
44 */ 44 */
45 - // FIXME: replace vlanId long with a rich data-type, e.g. VLanId or something like that
46 public static HostId hostId(MACAddress mac, VLANID vlanId) { 45 public static HostId hostId(MACAddress mac, VLANID vlanId) {
47 // FIXME: use more efficient means of encoding 46 // FIXME: use more efficient means of encoding
48 return hostId("nic" + ":" + mac + "/" + vlanId); 47 return hostId("nic" + ":" + mac + "/" + vlanId);
49 } 48 }
50 49
50 + /**
51 + * Creates a device id using the supplied MAC and default VLAN.
52 + *
53 + * @param mac mac address
54 + * @return host identifier
55 + */
56 + public static HostId hostId(MACAddress mac) {
57 + return hostId(mac, VLANID.vlanId(VLANID.UNTAGGED));
58 + }
59 +
51 } 60 }
......
...@@ -25,10 +25,8 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; ...@@ -25,10 +25,8 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry;
25 import org.onlab.onos.net.provider.AbstractProviderService; 25 import org.onlab.onos.net.provider.AbstractProviderService;
26 import org.slf4j.Logger; 26 import org.slf4j.Logger;
27 27
28 -
29 /** 28 /**
30 * Provides a basic implementation of the packet SB &amp; NB APIs. 29 * Provides a basic implementation of the packet SB &amp; NB APIs.
31 - *
32 */ 30 */
33 @Component(immediate = true) 31 @Component(immediate = true)
34 @Service 32 @Service
...@@ -43,7 +41,6 @@ implements PacketService, PacketProviderRegistry { ...@@ -43,7 +41,6 @@ implements PacketService, PacketProviderRegistry {
43 41
44 private final Map<Integer, PacketProcessor> processors = new TreeMap<>(); 42 private final Map<Integer, PacketProcessor> processors = new TreeMap<>();
45 43
46 -
47 @Activate 44 @Activate
48 public void activate() { 45 public void activate() {
49 log.info("Started"); 46 log.info("Started");
...@@ -62,19 +59,20 @@ implements PacketService, PacketProviderRegistry { ...@@ -62,19 +59,20 @@ implements PacketService, PacketProviderRegistry {
62 59
63 @Override 60 @Override
64 public void removeProcessor(PacketProcessor processor) { 61 public void removeProcessor(PacketProcessor processor) {
62 + checkNotNull(processor, "Processor cannot be null");
65 processors.values().remove(processor); 63 processors.values().remove(processor);
66 } 64 }
67 65
68 @Override 66 @Override
69 public void emit(OutboundPacket packet) { 67 public void emit(OutboundPacket packet) {
68 + checkNotNull(packet, "Packet cannot be null");
70 final Device device = deviceService.getDevice(packet.sendThrough()); 69 final Device device = deviceService.getDevice(packet.sendThrough());
71 final PacketProvider packetProvider = getProvider(device.providerId()); 70 final PacketProvider packetProvider = getProvider(device.providerId());
72 packetProvider.emit(packet); 71 packetProvider.emit(packet);
73 } 72 }
74 73
75 @Override 74 @Override
76 - protected PacketProviderService createProviderService( 75 + protected PacketProviderService createProviderService(PacketProvider provider) {
77 - PacketProvider provider) {
78 return new InternalPacketProviderService(provider); 76 return new InternalPacketProviderService(provider);
79 } 77 }
80 78
......
...@@ -366,7 +366,7 @@ ...@@ -366,7 +366,7 @@
366 <group> 366 <group>
367 <title>Sample Applications</title> 367 <title>Sample Applications</title>
368 <packages> 368 <packages>
369 - org.onlab.onos.tvue 369 + org.onlab.onos.tvue:org.onlab.onos.fwd
370 </packages> 370 </packages>
371 </group> 371 </group>
372 </groups> 372 </groups>
......
...@@ -3,6 +3,7 @@ package org.onlab.packet; ...@@ -3,6 +3,7 @@ package org.onlab.packet;
3 /** 3 /**
4 * Representation of a VLAN ID. 4 * Representation of a VLAN ID.
5 */ 5 */
6 +// FIXME: This will end-up looking like a constant; we should name it 'VlanId', 'IpAddress', 'MacAddress'.
6 public class VLANID { 7 public class VLANID {
7 8
8 private final short value; 9 private final short value;
......