blob: fded98fe6011be59aef673743fbf41d9ccb77711 [file] [log] [blame]
toma9a77c22014-10-03 17:05:20 -07001package org.onlab.onos.ifwd;
2
Brian O'Connor8731d2d2014-10-06 16:18:43 -07003import static org.slf4j.LoggerFactory.getLogger;
4
toma9a77c22014-10-03 17:05:20 -07005import org.apache.felix.scr.annotations.Activate;
6import org.apache.felix.scr.annotations.Component;
7import org.apache.felix.scr.annotations.Deactivate;
8import org.apache.felix.scr.annotations.Reference;
9import org.apache.felix.scr.annotations.ReferenceCardinality;
toma9a77c22014-10-03 17:05:20 -070010import org.onlab.onos.net.Host;
11import org.onlab.onos.net.HostId;
12import org.onlab.onos.net.PortNumber;
13import org.onlab.onos.net.flow.DefaultTrafficSelector;
14import org.onlab.onos.net.flow.DefaultTrafficTreatment;
15import org.onlab.onos.net.flow.TrafficSelector;
16import org.onlab.onos.net.flow.TrafficTreatment;
17import org.onlab.onos.net.host.HostService;
18import org.onlab.onos.net.intent.HostToHostIntent;
19import org.onlab.onos.net.intent.IntentId;
20import org.onlab.onos.net.intent.IntentService;
Brian O'Connor958d3812014-10-03 19:46:23 -070021import org.onlab.onos.net.packet.DefaultOutboundPacket;
toma9a77c22014-10-03 17:05:20 -070022import org.onlab.onos.net.packet.InboundPacket;
Brian O'Connor958d3812014-10-03 19:46:23 -070023import org.onlab.onos.net.packet.OutboundPacket;
toma9a77c22014-10-03 17:05:20 -070024import org.onlab.onos.net.packet.PacketContext;
25import org.onlab.onos.net.packet.PacketProcessor;
26import org.onlab.onos.net.packet.PacketService;
27import org.onlab.onos.net.topology.TopologyService;
28import org.onlab.packet.Ethernet;
29import org.slf4j.Logger;
30
toma9a77c22014-10-03 17:05:20 -070031/**
32 * WORK-IN-PROGRESS: Sample reactive forwarding application using intent framework.
33 */
34@Component(immediate = true)
35public class IntentReactiveForwarding {
36
toma9a77c22014-10-03 17:05:20 -070037 private final Logger log = getLogger(getClass());
38
39 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
40 protected TopologyService topologyService;
41
42 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
43 protected PacketService packetService;
44
45 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
46 protected IntentService intentService;
47
48 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 protected HostService hostService;
50
51 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
52
Brian O'Connor8731d2d2014-10-06 16:18:43 -070053 private static long intentId = 0x123000;
toma9a77c22014-10-03 17:05:20 -070054
55 @Activate
56 public void activate() {
toma9a77c22014-10-03 17:05:20 -070057 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
tom0511a522014-10-04 12:06:02 -070058 log.info("Started");
toma9a77c22014-10-03 17:05:20 -070059 }
60
61 @Deactivate
62 public void deactivate() {
63 packetService.removeProcessor(processor);
64 processor = null;
65 log.info("Stopped");
66 }
67
toma9a77c22014-10-03 17:05:20 -070068 /**
69 * Packet processor responsible for forwarding packets along their paths.
70 */
71 private class ReactivePacketProcessor implements PacketProcessor {
72
73 @Override
74 public void process(PacketContext context) {
75 // Stop processing if the packet has been handled, since we
76 // can't do any more to it.
77 if (context.isHandled()) {
78 return;
79 }
80
81 InboundPacket pkt = context.inPacket();
82 Ethernet ethPkt = pkt.parsed();
83
84 HostId srcId = HostId.hostId(ethPkt.getSourceMAC());
85 HostId dstId = HostId.hostId(ethPkt.getDestinationMAC());
86
87 // Do we know who this is for? If not, flood and bail.
88 Host dst = hostService.getHost(dstId);
89 if (dst == null) {
90 flood(context);
91 return;
92 }
93
94 // Otherwise forward and be done with it.
95 setUpConnectivity(context, srcId, dstId);
Brian O'Connor958d3812014-10-03 19:46:23 -070096 forwardPacketToDst(context, dst);
toma9a77c22014-10-03 17:05:20 -070097 }
98 }
99
100 // Floods the specified packet if permissible.
101 private void flood(PacketContext context) {
102 if (topologyService.isBroadcastPoint(topologyService.currentTopology(),
103 context.inPacket().receivedFrom())) {
104 packetOut(context, PortNumber.FLOOD);
105 } else {
106 context.block();
107 }
108 }
109
110 // Sends a packet out the specified port.
111 private void packetOut(PacketContext context, PortNumber portNumber) {
112 context.treatmentBuilder().setOutput(portNumber);
113 context.send();
114 }
115
Brian O'Connor958d3812014-10-03 19:46:23 -0700116 private void forwardPacketToDst(PacketContext context, Host dst) {
117 TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(dst.location().port()).build();
118 OutboundPacket packet = new DefaultOutboundPacket(dst.location().deviceId(),
tom0511a522014-10-04 12:06:02 -0700119 treatment, context.inPacket().unparsed());
Brian O'Connor958d3812014-10-03 19:46:23 -0700120 packetService.emit(packet);
121 log.info("sending packet: {}", packet);
122 }
123
toma9a77c22014-10-03 17:05:20 -0700124 // Install a rule forwarding the packet to the specified port.
125 private void setUpConnectivity(PacketContext context, HostId srcId, HostId dstId) {
126 TrafficSelector selector = DefaultTrafficSelector.builder().build();
127 TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
128
129 HostToHostIntent intent =
130 new HostToHostIntent(new IntentId(intentId++), srcId, dstId,
131 selector, treatment);
132
133 intentService.submit(intent);
134 }
135
136}