blob: 90e319f3869a7bce2970fa35cf5c7b843d3d8b7c [file] [log] [blame]
Jonathan Hart1caaa932013-11-04 15:28:28 -08001package net.onrc.onos.ofcontroller.forwarding;
2
Jonathan Harte93aed42013-12-05 18:39:50 -08003import java.util.ArrayList;
4import java.util.Collection;
Jonathan Hart1caaa932013-11-04 15:28:28 -08005import java.util.Iterator;
Jonathan Harte93aed42013-12-05 18:39:50 -08006import java.util.List;
7import java.util.Map;
Jonathan Hart1caaa932013-11-04 15:28:28 -08008
9import net.floodlightcontroller.core.FloodlightContext;
10import net.floodlightcontroller.core.IFloodlightProviderService;
11import net.floodlightcontroller.core.IOFMessageListener;
12import net.floodlightcontroller.core.IOFSwitch;
Jonathan Harte93aed42013-12-05 18:39:50 -080013import net.floodlightcontroller.core.module.FloodlightModuleContext;
14import net.floodlightcontroller.core.module.IFloodlightModule;
15import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart1caaa932013-11-04 15:28:28 -080016import net.floodlightcontroller.packet.Ethernet;
17import net.floodlightcontroller.util.MACAddress;
Jonathan Hartdc3ad702013-11-14 11:34:59 -080018import net.onrc.onos.datagrid.IDatagridService;
Jonathan Hart1caaa932013-11-04 15:28:28 -080019import net.onrc.onos.ofcontroller.core.IDeviceStorage;
20import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
21import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
22import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
23import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
Jonathan Hart1caaa932013-11-04 15:28:28 -080024import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
25import net.onrc.onos.ofcontroller.topology.TopologyManager;
26import net.onrc.onos.ofcontroller.util.CallerId;
27import net.onrc.onos.ofcontroller.util.DataPath;
28import net.onrc.onos.ofcontroller.util.Dpid;
Jonathan Hart4fb16d82013-11-07 22:41:32 -080029import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
Jonathan Hart1caaa932013-11-04 15:28:28 -080030import net.onrc.onos.ofcontroller.util.FlowId;
31import net.onrc.onos.ofcontroller.util.FlowPath;
32import net.onrc.onos.ofcontroller.util.FlowPathType;
33import net.onrc.onos.ofcontroller.util.FlowPathUserState;
34import net.onrc.onos.ofcontroller.util.Port;
35import net.onrc.onos.ofcontroller.util.SwitchPort;
36
37import org.openflow.protocol.OFMessage;
38import org.openflow.protocol.OFPacketIn;
39import org.openflow.protocol.OFType;
40import org.openflow.util.HexString;
41import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
Jonathan Harte93aed42013-12-05 18:39:50 -080044public class Forwarding implements IOFMessageListener, IFloodlightModule {
Jonathan Hart1caaa932013-11-04 15:28:28 -080045 private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
46
47 private IFloodlightProviderService floodlightProvider;
48 private IFlowService flowService;
Jonathan Hartdc3ad702013-11-14 11:34:59 -080049 private IDatagridService datagridService;
Jonathan Hart1caaa932013-11-04 15:28:28 -080050
51 private IDeviceStorage deviceStorage;
52 private TopologyManager topologyService;
53
54 public Forwarding() {
55
56 }
57
Jonathan Harte93aed42013-12-05 18:39:50 -080058 @Override
59 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
60 return null;
61 }
62
63 @Override
64 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
65 return null;
66 }
67
68 @Override
69 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
70 List<Class<? extends IFloodlightService>> dependencies =
71 new ArrayList<Class<? extends IFloodlightService>>();
72 dependencies.add(IFloodlightProviderService.class);
73 dependencies.add(IFlowService.class);
74 dependencies.add(IDatagridService.class);
75 return dependencies;
76 }
77
78 @Override
79 public void init(FloodlightModuleContext context) {
80 this.floodlightProvider =
81 context.getServiceImpl(IFloodlightProviderService.class);
82 this.flowService = context.getServiceImpl(IFlowService.class);
83 this.datagridService = context.getServiceImpl(IDatagridService.class);
Jonathan Hart1caaa932013-11-04 15:28:28 -080084
85 floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
86
87 deviceStorage = new DeviceStorageImpl();
88 deviceStorage.init("");
89 topologyService = new TopologyManager();
90 topologyService.init("");
91 }
92
Jonathan Harte93aed42013-12-05 18:39:50 -080093 @Override
94 public void startUp(FloodlightModuleContext context) {
Jonathan Hart1caaa932013-11-04 15:28:28 -080095 // no-op
96 }
97
98 @Override
99 public String getName() {
100 return "onosforwarding";
101 }
102
103 @Override
104 public boolean isCallbackOrderingPrereq(OFType type, String name) {
105 return (type == OFType.PACKET_IN) &&
106 (name.equals("devicemanager") || name.equals("proxyarpmanager"));
107 }
108
109 @Override
110 public boolean isCallbackOrderingPostreq(OFType type, String name) {
111 return false;
112 }
113
114 @Override
115 public Command receive(
116 IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
117
118 if (msg.getType() != OFType.PACKET_IN) {
119 return Command.CONTINUE;
120 }
121
122 OFPacketIn pi = (OFPacketIn) msg;
123
124 Ethernet eth = IFloodlightProviderService.bcStore.
125 get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
126
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800127 // We only want to handle unicast IPv4
128 if (eth.isBroadcast() || eth.isMulticast() ||
129 eth.getEtherType() != Ethernet.TYPE_IPv4) {
Jonathan Hart1caaa932013-11-04 15:28:28 -0800130 return Command.CONTINUE;
131 }
132
133 handlePacketIn(sw, pi, eth);
134
135 return Command.STOP;
136 }
137
138 private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
139 String destinationMac = HexString.toHexString(eth.getDestinationMACAddress());
140
141 IDeviceObject deviceObject = deviceStorage.getDeviceByMac(
142 destinationMac);
143
144 if (deviceObject == null) {
145 log.debug("No device entry found for {}", destinationMac);
146 return;
147 }
148
149 Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();
150 if (!ports.hasNext()) {
151 log.debug("No attachment point found for device {}", destinationMac);
152 return;
153 }
154 IPortObject portObject = ports.next();
155 short destinationPort = portObject.getNumber();
156 ISwitchObject switchObject = portObject.getSwitch();
157 long destinationDpid = HexString.toLong(switchObject.getDPID());
158
159 SwitchPort srcSwitchPort = new SwitchPort(
160 new Dpid(sw.getId()), new Port(pi.getInPort()));
161 SwitchPort dstSwitchPort = new SwitchPort(
162 new Dpid(destinationDpid), new Port(destinationPort));
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800163
164 MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
165 MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
Jonathan Hart1caaa932013-11-04 15:28:28 -0800166
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800167 if (flowExists(srcSwitchPort, srcMacAddress,
168 dstSwitchPort, dstMacAddress)) {
169 log.debug("Not adding flow because it already exists");
170
171 // Don't do anything if the flow already exists
Jonathan Hart1caaa932013-11-04 15:28:28 -0800172 return;
173 }
174
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800175 log.debug("Adding new flow between {} at {} and {} at {}",
176 new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
177
Jonathan Hart1caaa932013-11-04 15:28:28 -0800178
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800179 DataPath dataPath = new DataPath();
180 dataPath.setSrcPort(srcSwitchPort);
181 dataPath.setDstPort(dstSwitchPort);
182
Jonathan Hart97099912013-11-14 13:40:16 -0800183 FlowId flowId = new FlowId(flowService.getNextFlowEntryId());
Jonathan Hart1caaa932013-11-04 15:28:28 -0800184 FlowPath flowPath = new FlowPath();
185 flowPath.setFlowId(flowId);
186 flowPath.setInstallerId(new CallerId("Forwarding"));
187 flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
188 flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800189 flowPath.setFlowEntryMatch(new FlowEntryMatch());
Jonathan Hart1caaa932013-11-04 15:28:28 -0800190 flowPath.flowEntryMatch().enableSrcMac(srcMacAddress);
191 flowPath.flowEntryMatch().enableDstMac(dstMacAddress);
192 // For now just forward IPv4 packets. This prevents accidentally
193 // other stuff like ARP.
194 flowPath.flowEntryMatch().enableEthernetFrameType(Ethernet.TYPE_IPv4);
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800195 flowPath.setDataPath(dataPath);
196
Jonathan Hart1caaa932013-11-04 15:28:28 -0800197 flowService.addFlow(flowPath, flowId);
Jonathan Hart1caaa932013-11-04 15:28:28 -0800198 }
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800199
200 private boolean flowExists(SwitchPort srcPort, MACAddress srcMac,
201 SwitchPort dstPort, MACAddress dstMac) {
202 for (FlowPath flow : datagridService.getAllFlows()) {
203 FlowEntryMatch match = flow.flowEntryMatch();
204 // TODO implement FlowEntryMatch.equals();
205 // This is painful to do properly without support in the FlowEntryMatch
206 boolean same = true;
207 if (!match.srcMac().equals(srcMac) ||
208 !match.dstMac().equals(dstMac)) {
209 same = false;
210 }
211 if (!flow.dataPath().srcPort().equals(srcPort) ||
212 !flow.dataPath().dstPort().equals(dstPort)) {
213 same = false;
214 }
215
216 if (same) {
217 log.debug("found flow entry that's the same {}-{}:::{}-{}",
218 new Object[] {srcPort, srcMac, dstPort, dstMac});
219 return true;
220 }
221 }
222
223 return false;
224 }
Jonathan Hart1caaa932013-11-04 15:28:28 -0800225
226}