blob: df7a408995cb65c1df80e6edc9beb6e9110cee51 [file] [log] [blame]
alshabib030111e2014-09-15 15:56:42 -07001package org.onlab.onos.fwd;
2
3import org.apache.felix.scr.annotations.Activate;
4import org.apache.felix.scr.annotations.Component;
5import org.apache.felix.scr.annotations.Deactivate;
6import org.apache.felix.scr.annotations.Reference;
7import org.apache.felix.scr.annotations.ReferenceCardinality;
tomc370ebd2014-09-16 01:25:21 -07008import org.onlab.onos.net.Host;
9import org.onlab.onos.net.HostId;
10import org.onlab.onos.net.Path;
11import org.onlab.onos.net.PortNumber;
alshabib7b2748f2014-09-16 20:21:11 -070012import org.onlab.onos.net.flow.DefaultFlowRule;
13import org.onlab.onos.net.flow.DefaultTrafficSelector;
14import org.onlab.onos.net.flow.DefaultTrafficTreatment;
15import org.onlab.onos.net.flow.FlowRule;
16import org.onlab.onos.net.flow.FlowRuleService;
17import org.onlab.onos.net.flow.TrafficSelector;
18import org.onlab.onos.net.flow.TrafficTreatment;
19import org.onlab.onos.net.flow.criteria.Criteria;
alshabib55a55d92014-09-16 11:59:31 -070020import org.onlab.onos.net.flow.instructions.Instructions;
alshabib8aef1ad2014-09-15 17:47:31 -070021import org.onlab.onos.net.host.HostService;
tomc370ebd2014-09-16 01:25:21 -070022import org.onlab.onos.net.packet.InboundPacket;
23import org.onlab.onos.net.packet.PacketContext;
alshabib030111e2014-09-15 15:56:42 -070024import org.onlab.onos.net.packet.PacketProcessor;
25import org.onlab.onos.net.packet.PacketService;
26import org.onlab.onos.net.topology.TopologyService;
alshabib7b2748f2014-09-16 20:21:11 -070027import org.onlab.packet.Ethernet;
tomc370ebd2014-09-16 01:25:21 -070028import org.slf4j.Logger;
alshabib030111e2014-09-15 15:56:42 -070029
tom642b2262014-09-17 13:52:55 -070030import java.util.Set;
31
32import static org.slf4j.LoggerFactory.getLogger;
33
tomc370ebd2014-09-16 01:25:21 -070034/**
35 * Sample reactive forwarding application.
36 */
37@Component(immediate = true)
alshabib030111e2014-09-15 15:56:42 -070038public class ReactiveForwarding {
39
tomc370ebd2014-09-16 01:25:21 -070040 private final Logger log = getLogger(getClass());
41
alshabib030111e2014-09-15 15:56:42 -070042 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
43 protected TopologyService topologyService;
44
45 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
46 protected PacketService packetService;
47
alshabib8aef1ad2014-09-15 17:47:31 -070048 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 protected HostService hostService;
50
alshabib7b2748f2014-09-16 20:21:11 -070051 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
52 protected FlowRuleService flowRuleService;
53
tomc370ebd2014-09-16 01:25:21 -070054 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
alshabib030111e2014-09-15 15:56:42 -070055
56 @Activate
57 public void activate() {
alshabib030111e2014-09-15 15:56:42 -070058 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1);
tomc370ebd2014-09-16 01:25:21 -070059 log.info("Started");
alshabib030111e2014-09-15 15:56:42 -070060 }
61
62 @Deactivate
63 public void deactivate() {
64 packetService.removeProcessor(processor);
65 processor = null;
tomc370ebd2014-09-16 01:25:21 -070066 log.info("Stopped");
alshabib030111e2014-09-15 15:56:42 -070067 }
tomc370ebd2014-09-16 01:25:21 -070068
69
70 /**
71 * Packet processor responsible for forwarding packets along their paths.
72 */
73 private class ReactivePacketProcessor implements PacketProcessor {
74
75 @Override
76 public void process(PacketContext context) {
tomdc95b8a2014-09-17 08:07:26 -070077 // Stop processing if the packet has been handled, since we
78 // can't do any more to it.
alshabib7b2748f2014-09-16 20:21:11 -070079 if (context.isHandled()) {
80 return;
81 }
tomdc95b8a2014-09-17 08:07:26 -070082
tomc370ebd2014-09-16 01:25:21 -070083 InboundPacket pkt = context.inPacket();
tom642b2262014-09-17 13:52:55 -070084 Ethernet ethPkt = pkt.parsed();
85 HostId id = HostId.hostId(ethPkt.getDestinationMAC());
tomc370ebd2014-09-16 01:25:21 -070086
87 // Do we know who this is for? If not, flood and bail.
88 Host dst = hostService.getHost(id);
89 if (dst == null) {
90 flood(context);
91 return;
92 }
93
94 // Are we on an edge switch that our destination is on? If so,
95 // simply forward out to the destination and bail.
96 if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) {
alshabib7b2748f2014-09-16 20:21:11 -070097 installRule(context, dst.location().port());
tomc370ebd2014-09-16 01:25:21 -070098 return;
99 }
100
101 // Otherwise, get a set of paths that lead from here to the
102 // destination edge switch.
103 Set<Path> paths = topologyService.getPaths(topologyService.currentTopology(),
tom642b2262014-09-17 13:52:55 -0700104 pkt.receivedFrom().deviceId(),
105 dst.location().deviceId());
tomc370ebd2014-09-16 01:25:21 -0700106 if (paths.isEmpty()) {
107 // If there are no paths, flood and bail.
108 flood(context);
109 return;
110 }
111
112 // Otherwise, pick a path that does not lead back to where we
113 // came from; if no such path, flood and bail.
114 Path path = pickForwardPath(paths, pkt.receivedFrom().port());
115 if (path == null) {
tom642b2262014-09-17 13:52:55 -0700116 log.warn("Doh... don't know where to go... {} -> {} received on {}",
117 ethPkt.getSourceMAC(), ethPkt.getDestinationMAC(),
118 pkt.receivedFrom().port());
tomc370ebd2014-09-16 01:25:21 -0700119 flood(context);
120 return;
121 }
122
123 // Otherwise forward and be done with it.
alshabib7b2748f2014-09-16 20:21:11 -0700124 installRule(context, path.src().port());
tomc370ebd2014-09-16 01:25:21 -0700125 }
126 }
127
128 // Selects a path from the given set that does not lead back to the
129 // specified port.
130 private Path pickForwardPath(Set<Path> paths, PortNumber notToPort) {
131 for (Path path : paths) {
132 if (!path.src().port().equals(notToPort)) {
133 return path;
134 }
135 }
136 return null;
137 }
138
tom642b2262014-09-17 13:52:55 -0700139 // Floods the specified packet if permissible.
tomc370ebd2014-09-16 01:25:21 -0700140 private void flood(PacketContext context) {
tomdc95b8a2014-09-17 08:07:26 -0700141 if (topologyService.isBroadcastPoint(topologyService.currentTopology(),
tom642b2262014-09-17 13:52:55 -0700142 context.inPacket().receivedFrom())) {
143 packetOut(context, PortNumber.FLOOD);
tomc370ebd2014-09-16 01:25:21 -0700144 } else {
145 context.block();
146 }
147 }
148
tom642b2262014-09-17 13:52:55 -0700149 // Sends a packet out the specified port.
150 private void packetOut(PacketContext context, PortNumber portNumber) {
151 context.treatmentBuilder().add(Instructions.createOutput(portNumber));
alshabib7b2748f2014-09-16 20:21:11 -0700152 context.send();
153 }
154
155 // Install a rule forwarding the packet to the specified port.
156 private void installRule(PacketContext context, PortNumber portNumber) {
tom642b2262014-09-17 13:52:55 -0700157 // We don't yet support bufferids in the flowservice so packet out first.
158 packetOut(context, portNumber);
alshabib7b2748f2014-09-16 20:21:11 -0700159
tom642b2262014-09-17 13:52:55 -0700160 // Install the flow rule to handle this type of message from now on.
alshabib7b2748f2014-09-16 20:21:11 -0700161 Ethernet inPkt = context.inPacket().parsed();
162 TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
163 builder.add(Criteria.matchEthType(inPkt.getEtherType()))
tom642b2262014-09-17 13:52:55 -0700164 .add(Criteria.matchEthSrc(inPkt.getSourceMAC()))
165 .add(Criteria.matchEthDst(inPkt.getDestinationMAC()))
166 .add(Criteria.matchInPort(context.inPacket().receivedFrom().port()));
alshabib7b2748f2014-09-16 20:21:11 -0700167
168 TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder();
169 treat.add(Instructions.createOutput(portNumber));
170
171 FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
tom642b2262014-09-17 13:52:55 -0700172 builder.build(), treat.build());
alshabib7b2748f2014-09-16 20:21:11 -0700173
174 flowRuleService.applyFlowRules(f);
tomc370ebd2014-09-16 01:25:21 -0700175 }
176
alshabib030111e2014-09-15 15:56:42 -0700177}
178
tomc370ebd2014-09-16 01:25:21 -0700179