blob: 8c518d7bb5bcd971cf5c470ab9e49fc313e84a2d [file] [log] [blame]
Jonathan Hart8f6dc092014-04-18 15:56:43 -07001package net.onrc.onos.apps.sdnip;
Jonathan Hart1912afc2013-10-11 12:02:44 +13002
3import java.io.IOException;
4import java.util.ArrayList;
5import java.util.Collections;
6import java.util.Comparator;
7import java.util.HashMap;
8import java.util.List;
9import java.util.Map;
10
11import net.floodlightcontroller.core.IFloodlightProviderService;
12import net.floodlightcontroller.core.IOFSwitch;
13
14import org.openflow.protocol.OFFlowMod;
15import org.openflow.protocol.OFMessage;
16import org.openflow.protocol.OFPort;
17import org.openflow.util.HexString;
18import org.slf4j.Logger;
19import org.slf4j.LoggerFactory;
20
21public class FlowCache {
Ray Milkeyec838942014-04-09 11:28:43 -070022 private static final Logger log = LoggerFactory.getLogger(FlowCache.class);
Jonathan Hart1912afc2013-10-11 12:02:44 +130023
Jonathan Hart938a0152014-04-07 18:27:31 -070024 private final IFloodlightProviderService floodlightProvider;
Jonathan Hart1912afc2013-10-11 12:02:44 +130025
Jonathan Hart938a0152014-04-07 18:27:31 -070026 private final Map<Long, List<OFFlowMod>> flowCacheMap;
Jonathan Hart1912afc2013-10-11 12:02:44 +130027
Ray Milkey5d406012014-04-08 14:44:41 -070028 private final Comparator<OFFlowMod> cookieComparator =
Jonathan Hart938a0152014-04-07 18:27:31 -070029 new Comparator<OFFlowMod>() {
Ray Milkey269ffb92014-04-03 14:43:30 -070030 @Override
31 public int compare(OFFlowMod fm1, OFFlowMod fm2) {
32 long difference = fm2.getCookie() - fm1.getCookie();
Jonathan Hart1912afc2013-10-11 12:02:44 +130033
Ray Milkey269ffb92014-04-03 14:43:30 -070034 if (difference > 0) {
35 return 1;
36 } else if (difference < 0) {
37 return -1;
38 } else {
39 return 0;
40 }
41 }
42 };
43
44 public FlowCache(IFloodlightProviderService floodlightProvider) {
45 this.floodlightProvider = floodlightProvider;
46
Jonathan Hart938a0152014-04-07 18:27:31 -070047 flowCacheMap = new HashMap<Long, List<OFFlowMod>>();
Ray Milkey269ffb92014-04-03 14:43:30 -070048 }
49
Jonathan Hart938a0152014-04-07 18:27:31 -070050 public void write(long dpid, OFFlowMod flowMod) {
51 synchronized (this) {
52 List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(1);
53 flowModList.add(flowMod);
54 write(dpid, flowModList);
55 }
Ray Milkey269ffb92014-04-03 14:43:30 -070056 }
57
Jonathan Hart938a0152014-04-07 18:27:31 -070058 public void write(long dpid, List<OFFlowMod> flowMods) {
59 synchronized (this) {
60 ensureCacheForSwitch(dpid);
Ray Milkey5d406012014-04-08 14:44:41 -070061
Jonathan Hart938a0152014-04-07 18:27:31 -070062 List<OFFlowMod> clones = new ArrayList<OFFlowMod>(flowMods.size());
Ray Milkey5d406012014-04-08 14:44:41 -070063
Jonathan Hart938a0152014-04-07 18:27:31 -070064 // Somehow the OFFlowMods we get passed in will change later on.
65 // No idea how this happens, but we can just clone to prevent problems
66 try {
67 for (OFFlowMod fm : flowMods) {
68 clones.add(fm.clone());
69 }
70 } catch (CloneNotSupportedException e) {
71 log.debug("Clone exception", e);
Ray Milkey269ffb92014-04-03 14:43:30 -070072 }
Ray Milkey5d406012014-04-08 14:44:41 -070073
Jonathan Hart938a0152014-04-07 18:27:31 -070074 flowCacheMap.get(dpid).addAll(clones);
Ray Milkey5d406012014-04-08 14:44:41 -070075
Jonathan Hart938a0152014-04-07 18:27:31 -070076 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
Ray Milkey5d406012014-04-08 14:44:41 -070077
Jonathan Hart938a0152014-04-07 18:27:31 -070078 if (sw == null) {
79 log.debug("Switch not found when writing flow mods");
80 return;
81 }
Ray Milkey5d406012014-04-08 14:44:41 -070082
Jonathan Hart938a0152014-04-07 18:27:31 -070083 List<OFMessage> msgList = new ArrayList<OFMessage>(clones.size());
84 msgList.addAll(clones);
Ray Milkey5d406012014-04-08 14:44:41 -070085
Jonathan Hart938a0152014-04-07 18:27:31 -070086 try {
87 sw.write(msgList, null);
88 } catch (IOException e) {
89 log.error("Error writing to switch", e);
90 }
Ray Milkey269ffb92014-04-03 14:43:30 -070091 }
92 }
93
Jonathan Hart938a0152014-04-07 18:27:31 -070094 public void delete(long dpid, OFFlowMod flowMod) {
95 synchronized (this) {
96 List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(1);
97 flowModList.add(flowMod);
98 delete(dpid, flowModList);
99 }
100 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700101
Jonathan Hart938a0152014-04-07 18:27:31 -0700102 public void delete(long dpid, List<OFFlowMod> flowMods) {
103 synchronized (this) {
104 ensureCacheForSwitch(dpid);
Ray Milkey5d406012014-04-08 14:44:41 -0700105
Jonathan Hart938a0152014-04-07 18:27:31 -0700106 // Remove the flow mods from the cache first before we alter them
107 flowCacheMap.get(dpid).removeAll(flowMods);
Ray Milkey5d406012014-04-08 14:44:41 -0700108
Jonathan Hart938a0152014-04-07 18:27:31 -0700109 // Alter the original flow mods to make them delete flow mods
110 for (OFFlowMod fm : flowMods) {
111 fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT)
112 .setOutPort(OFPort.OFPP_NONE)
113 .setLengthU(OFFlowMod.MINIMUM_LENGTH);
Ray Milkey5d406012014-04-08 14:44:41 -0700114
Jonathan Hart938a0152014-04-07 18:27:31 -0700115 fm.getActions().clear();
116 }
Ray Milkey5d406012014-04-08 14:44:41 -0700117
Jonathan Hart938a0152014-04-07 18:27:31 -0700118 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
119 if (sw == null) {
120 log.debug("Switch not found when writing flow mods");
121 return;
122 }
Ray Milkey5d406012014-04-08 14:44:41 -0700123
Jonathan Hart938a0152014-04-07 18:27:31 -0700124 List<OFMessage> msgList = new ArrayList<OFMessage>(flowMods.size());
125 msgList.addAll(flowMods);
Ray Milkey5d406012014-04-08 14:44:41 -0700126
Jonathan Hart938a0152014-04-07 18:27:31 -0700127 try {
128 sw.write(msgList, null);
129 } catch (IOException e) {
130 log.error("Error writing to switch", e);
131 }
132 }
133 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700134
Jonathan Hart938a0152014-04-07 18:27:31 -0700135 public void switchConnected(IOFSwitch sw) {
136 synchronized (this) {
137 log.debug("Switch connected: {}", sw);
Ray Milkey5d406012014-04-08 14:44:41 -0700138
Jonathan Hart938a0152014-04-07 18:27:31 -0700139 ensureCacheForSwitch(sw.getId());
Ray Milkey5d406012014-04-08 14:44:41 -0700140
Jonathan Hart938a0152014-04-07 18:27:31 -0700141 List<OFFlowMod> flowMods = flowCacheMap.get(sw.getId());
Ray Milkey5d406012014-04-08 14:44:41 -0700142
Jonathan Hart938a0152014-04-07 18:27:31 -0700143 Collections.sort(flowMods, cookieComparator);
Ray Milkey5d406012014-04-08 14:44:41 -0700144
Jonathan Hart938a0152014-04-07 18:27:31 -0700145 sw.clearAllFlowMods();
Ray Milkey5d406012014-04-08 14:44:41 -0700146
Jonathan Hart938a0152014-04-07 18:27:31 -0700147 List<OFMessage> messages = new ArrayList<OFMessage>(flowMods.size());
148 messages.addAll(flowMods);
Ray Milkey5d406012014-04-08 14:44:41 -0700149
Jonathan Hart938a0152014-04-07 18:27:31 -0700150 try {
151 sw.write(messages, null);
152 } catch (IOException e) {
153 log.error("Failure writing flow mods to switch {}",
154 HexString.toHexString(sw.getId()));
155 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700156 }
157 }
158
159 private void ensureCacheForSwitch(long dpid) {
Jonathan Hart938a0152014-04-07 18:27:31 -0700160 if (!flowCacheMap.containsKey(dpid)) {
161 flowCacheMap.put(dpid, new ArrayList<OFFlowMod>());
Ray Milkey269ffb92014-04-03 14:43:30 -0700162 }
163 }
Jonathan Hart1912afc2013-10-11 12:02:44 +1300164}