blob: 81e66873003e21d1e106391b04dfa540b8fb6e5d [file] [log] [blame]
Jonathan Hart1caaa932013-11-04 15:28:28 -08001package net.onrc.onos.ofcontroller.forwarding;
2
3import java.util.Iterator;
4
5import net.floodlightcontroller.core.FloodlightContext;
6import net.floodlightcontroller.core.IFloodlightProviderService;
7import net.floodlightcontroller.core.IOFMessageListener;
8import net.floodlightcontroller.core.IOFSwitch;
9import net.floodlightcontroller.packet.Ethernet;
10import net.floodlightcontroller.util.MACAddress;
11import net.onrc.onos.ofcontroller.core.IDeviceStorage;
12import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
13import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
14import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
15import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
Jonathan Hart1caaa932013-11-04 15:28:28 -080016import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
17import net.onrc.onos.ofcontroller.topology.TopologyManager;
18import net.onrc.onos.ofcontroller.util.CallerId;
19import net.onrc.onos.ofcontroller.util.DataPath;
20import net.onrc.onos.ofcontroller.util.Dpid;
Jonathan Hart4fb16d82013-11-07 22:41:32 -080021import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
Jonathan Hart1caaa932013-11-04 15:28:28 -080022import net.onrc.onos.ofcontroller.util.FlowId;
23import net.onrc.onos.ofcontroller.util.FlowPath;
24import net.onrc.onos.ofcontroller.util.FlowPathType;
25import net.onrc.onos.ofcontroller.util.FlowPathUserState;
26import net.onrc.onos.ofcontroller.util.Port;
27import net.onrc.onos.ofcontroller.util.SwitchPort;
28
29import org.openflow.protocol.OFMessage;
30import org.openflow.protocol.OFPacketIn;
31import org.openflow.protocol.OFType;
32import org.openflow.util.HexString;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
36public class Forwarding implements IOFMessageListener {
37 private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
38
39 private IFloodlightProviderService floodlightProvider;
40 private IFlowService flowService;
41
42 private IDeviceStorage deviceStorage;
43 private TopologyManager topologyService;
44
Jonathan Hart4fb16d82013-11-07 22:41:32 -080045 // TODO Flow IDs should be globally managed
46 private long currentId = 1;
47
Jonathan Hart1caaa932013-11-04 15:28:28 -080048 public Forwarding() {
49
50 }
51
52 public void init(IFloodlightProviderService floodlightProvider,
53 IFlowService flowService) {
54 this.floodlightProvider = floodlightProvider;
55 this.flowService = flowService;
56
57 floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
58
59 deviceStorage = new DeviceStorageImpl();
60 deviceStorage.init("");
61 topologyService = new TopologyManager();
62 topologyService.init("");
63 }
64
65 public void startUp() {
66 // no-op
67 }
68
69 @Override
70 public String getName() {
71 return "onosforwarding";
72 }
73
74 @Override
75 public boolean isCallbackOrderingPrereq(OFType type, String name) {
76 return (type == OFType.PACKET_IN) &&
77 (name.equals("devicemanager") || name.equals("proxyarpmanager"));
78 }
79
80 @Override
81 public boolean isCallbackOrderingPostreq(OFType type, String name) {
82 return false;
83 }
84
85 @Override
86 public Command receive(
87 IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
88
89 if (msg.getType() != OFType.PACKET_IN) {
90 return Command.CONTINUE;
91 }
92
93 OFPacketIn pi = (OFPacketIn) msg;
94
95 Ethernet eth = IFloodlightProviderService.bcStore.
96 get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
97
Jonathan Hart4fb16d82013-11-07 22:41:32 -080098 // We only want to handle unicast IPv4
99 if (eth.isBroadcast() || eth.isMulticast() ||
100 eth.getEtherType() != Ethernet.TYPE_IPv4) {
Jonathan Hart1caaa932013-11-04 15:28:28 -0800101 return Command.CONTINUE;
102 }
103
104 handlePacketIn(sw, pi, eth);
105
106 return Command.STOP;
107 }
108
109 private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
110 String destinationMac = HexString.toHexString(eth.getDestinationMACAddress());
111
112 IDeviceObject deviceObject = deviceStorage.getDeviceByMac(
113 destinationMac);
114
115 if (deviceObject == null) {
116 log.debug("No device entry found for {}", destinationMac);
117 return;
118 }
119
120 Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();
121 if (!ports.hasNext()) {
122 log.debug("No attachment point found for device {}", destinationMac);
123 return;
124 }
125 IPortObject portObject = ports.next();
126 short destinationPort = portObject.getNumber();
127 ISwitchObject switchObject = portObject.getSwitch();
128 long destinationDpid = HexString.toLong(switchObject.getDPID());
129
130 SwitchPort srcSwitchPort = new SwitchPort(
131 new Dpid(sw.getId()), new Port(pi.getInPort()));
132 SwitchPort dstSwitchPort = new SwitchPort(
133 new Dpid(destinationDpid), new Port(destinationPort));
134 DataPath shortestPath =
135 topologyService.getDatabaseShortestPath(srcSwitchPort, dstSwitchPort);
136
137 if (shortestPath == null) {
138 log.debug("Shortest path not found between {} and {}",
139 srcSwitchPort, dstSwitchPort);
140 return;
141 }
142
143 MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
144 MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
145
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800146 DataPath dataPath = new DataPath();
147 dataPath.setSrcPort(srcSwitchPort);
148 dataPath.setDstPort(dstSwitchPort);
149
150 FlowId flowId = new FlowId(currentId++); //dummy flow ID
Jonathan Hart1caaa932013-11-04 15:28:28 -0800151 FlowPath flowPath = new FlowPath();
152 flowPath.setFlowId(flowId);
153 flowPath.setInstallerId(new CallerId("Forwarding"));
154 flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
155 flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800156 flowPath.setFlowEntryMatch(new FlowEntryMatch());
Jonathan Hart1caaa932013-11-04 15:28:28 -0800157 flowPath.flowEntryMatch().enableSrcMac(srcMacAddress);
158 flowPath.flowEntryMatch().enableDstMac(dstMacAddress);
159 // For now just forward IPv4 packets. This prevents accidentally
160 // other stuff like ARP.
161 flowPath.flowEntryMatch().enableEthernetFrameType(Ethernet.TYPE_IPv4);
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800162 flowPath.setDataPath(dataPath);
163
Jonathan Hart1caaa932013-11-04 15:28:28 -0800164 flowService.addFlow(flowPath, flowId);
Jonathan Hart1caaa932013-11-04 15:28:28 -0800165 }
166
167}