blob: 686bee0a781c10d1ca83121bc814b04d85528eef [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;
Jonathan Hartdc3ad702013-11-14 11:34:59 -080011import net.onrc.onos.datagrid.IDatagridService;
Jonathan Hart1caaa932013-11-04 15:28:28 -080012import net.onrc.onos.ofcontroller.core.IDeviceStorage;
13import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
14import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
15import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
16import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
Jonathan Hart1caaa932013-11-04 15:28:28 -080017import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
18import net.onrc.onos.ofcontroller.topology.TopologyManager;
19import net.onrc.onos.ofcontroller.util.CallerId;
20import net.onrc.onos.ofcontroller.util.DataPath;
21import net.onrc.onos.ofcontroller.util.Dpid;
Jonathan Hart4fb16d82013-11-07 22:41:32 -080022import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
Jonathan Hart1caaa932013-11-04 15:28:28 -080023import net.onrc.onos.ofcontroller.util.FlowId;
24import net.onrc.onos.ofcontroller.util.FlowPath;
25import net.onrc.onos.ofcontroller.util.FlowPathType;
26import net.onrc.onos.ofcontroller.util.FlowPathUserState;
27import net.onrc.onos.ofcontroller.util.Port;
28import net.onrc.onos.ofcontroller.util.SwitchPort;
29
30import org.openflow.protocol.OFMessage;
31import org.openflow.protocol.OFPacketIn;
32import org.openflow.protocol.OFType;
33import org.openflow.util.HexString;
34import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37public class Forwarding implements IOFMessageListener {
38 private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
39
40 private IFloodlightProviderService floodlightProvider;
41 private IFlowService flowService;
Jonathan Hartdc3ad702013-11-14 11:34:59 -080042 private IDatagridService datagridService;
Jonathan Hart1caaa932013-11-04 15:28:28 -080043
44 private IDeviceStorage deviceStorage;
45 private TopologyManager topologyService;
46
47 public Forwarding() {
48
49 }
50
51 public void init(IFloodlightProviderService floodlightProvider,
Jonathan Hartdc3ad702013-11-14 11:34:59 -080052 IFlowService flowService, IDatagridService datagridService) {
Jonathan Hart1caaa932013-11-04 15:28:28 -080053 this.floodlightProvider = floodlightProvider;
54 this.flowService = flowService;
Jonathan Hartdc3ad702013-11-14 11:34:59 -080055 this.datagridService = datagridService;
Jonathan Hart1caaa932013-11-04 15:28:28 -080056
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));
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800134
135 MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
136 MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
Jonathan Hart1caaa932013-11-04 15:28:28 -0800137
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800138 if (flowExists(srcSwitchPort, srcMacAddress,
139 dstSwitchPort, dstMacAddress)) {
140 log.debug("Not adding flow because it already exists");
141
142 // Don't do anything if the flow already exists
Jonathan Hart1caaa932013-11-04 15:28:28 -0800143 return;
144 }
145
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800146 log.debug("Adding new flow between {} at {} and {} at {}",
147 new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
148
Jonathan Hart1caaa932013-11-04 15:28:28 -0800149
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800150 DataPath dataPath = new DataPath();
151 dataPath.setSrcPort(srcSwitchPort);
152 dataPath.setDstPort(dstSwitchPort);
153
Jonathan Hart97099912013-11-14 13:40:16 -0800154 FlowId flowId = new FlowId(flowService.getNextFlowEntryId());
Jonathan Hart1caaa932013-11-04 15:28:28 -0800155 FlowPath flowPath = new FlowPath();
156 flowPath.setFlowId(flowId);
157 flowPath.setInstallerId(new CallerId("Forwarding"));
158 flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
159 flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800160 flowPath.setFlowEntryMatch(new FlowEntryMatch());
Jonathan Hart1caaa932013-11-04 15:28:28 -0800161 flowPath.flowEntryMatch().enableSrcMac(srcMacAddress);
162 flowPath.flowEntryMatch().enableDstMac(dstMacAddress);
163 // For now just forward IPv4 packets. This prevents accidentally
164 // other stuff like ARP.
165 flowPath.flowEntryMatch().enableEthernetFrameType(Ethernet.TYPE_IPv4);
Jonathan Hart4fb16d82013-11-07 22:41:32 -0800166 flowPath.setDataPath(dataPath);
167
Jonathan Hart1caaa932013-11-04 15:28:28 -0800168 flowService.addFlow(flowPath, flowId);
Jonathan Hart1caaa932013-11-04 15:28:28 -0800169 }
Jonathan Hartdc3ad702013-11-14 11:34:59 -0800170
171 private boolean flowExists(SwitchPort srcPort, MACAddress srcMac,
172 SwitchPort dstPort, MACAddress dstMac) {
173 for (FlowPath flow : datagridService.getAllFlows()) {
174 FlowEntryMatch match = flow.flowEntryMatch();
175 // TODO implement FlowEntryMatch.equals();
176 // This is painful to do properly without support in the FlowEntryMatch
177 boolean same = true;
178 if (!match.srcMac().equals(srcMac) ||
179 !match.dstMac().equals(dstMac)) {
180 same = false;
181 }
182 if (!flow.dataPath().srcPort().equals(srcPort) ||
183 !flow.dataPath().dstPort().equals(dstPort)) {
184 same = false;
185 }
186
187 if (same) {
188 log.debug("found flow entry that's the same {}-{}:::{}-{}",
189 new Object[] {srcPort, srcMac, dstPort, dstMac});
190 return true;
191 }
192 }
193
194 return false;
195 }
Jonathan Hart1caaa932013-11-04 15:28:28 -0800196
197}