Added javadocs and simplified the reactive fwd app in attempt to find the glitch; no dice
Showing
7 changed files
with
120 additions
and
84 deletions
... | @@ -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 | -} |
... | @@ -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 & NB APIs. | 29 | * Provides a basic implementation of the packet SB & 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; | ... | ... |
-
Please register or login to post a comment