blob: 5341e1d462b5aebb0d8653a6eaa4ba1197bd4557 [file] [log] [blame]
Jonathan Hart382623d2014-04-03 09:48:11 -07001package net.onrc.onos.apps.bgproute;
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 Milkey269ffb92014-04-03 14:43:30 -070022 private final static 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
Jonathan Hart938a0152014-04-07 18:27:31 -070028 private final Comparator<OFFlowMod> cookieComparator =
29 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);
61
62 List<OFFlowMod> clones = new ArrayList<OFFlowMod>(flowMods.size());
63
64 // 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 }
Jonathan Hart938a0152014-04-07 18:27:31 -070073
74 flowCacheMap.get(dpid).addAll(clones);
75
76 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
77
78 if (sw == null) {
79 log.debug("Switch not found when writing flow mods");
80 return;
81 }
82
83 List<OFMessage> msgList = new ArrayList<OFMessage>(clones.size());
84 msgList.addAll(clones);
85
86 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);
105
106 // Remove the flow mods from the cache first before we alter them
107 flowCacheMap.get(dpid).removeAll(flowMods);
108
109 // 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);
114
115 fm.getActions().clear();
116 }
117
118 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
119 if (sw == null) {
120 log.debug("Switch not found when writing flow mods");
121 return;
122 }
123
124 List<OFMessage> msgList = new ArrayList<OFMessage>(flowMods.size());
125 msgList.addAll(flowMods);
126
127 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);
138
139 ensureCacheForSwitch(sw.getId());
140
141 List<OFFlowMod> flowMods = flowCacheMap.get(sw.getId());
142
143 Collections.sort(flowMods, cookieComparator);
144
145 sw.clearAllFlowMods();
146
147 List<OFMessage> messages = new ArrayList<OFMessage>(flowMods.size());
148 messages.addAll(flowMods);
149
150 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}