blob: 145224b416397ce8d005725678842a34450da22f [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
Ray Milkey269ffb92014-04-03 14:43:30 -070024 private IFloodlightProviderService floodlightProvider;
Jonathan Hart1912afc2013-10-11 12:02:44 +130025
Ray Milkey269ffb92014-04-03 14:43:30 -070026 private Map<Long, List<OFFlowMod>> flowCache;
Jonathan Hart1912afc2013-10-11 12:02:44 +130027
Ray Milkey269ffb92014-04-03 14:43:30 -070028 private Comparator<OFFlowMod> cookieComparator = new Comparator<OFFlowMod>() {
29 @Override
30 public int compare(OFFlowMod fm1, OFFlowMod fm2) {
31 long difference = fm2.getCookie() - fm1.getCookie();
Jonathan Hart1912afc2013-10-11 12:02:44 +130032
Ray Milkey269ffb92014-04-03 14:43:30 -070033 if (difference > 0) {
34 return 1;
35 } else if (difference < 0) {
36 return -1;
37 } else {
38 return 0;
39 }
40 }
41 };
42
43 public FlowCache(IFloodlightProviderService floodlightProvider) {
44 this.floodlightProvider = floodlightProvider;
45
46 flowCache = new HashMap<Long, List<OFFlowMod>>();
47 }
48
49 public synchronized void write(long dpid, OFFlowMod flowMod) {
50 List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(1);
51 flowModList.add(flowMod);
52 write(dpid, flowModList);
53 }
54
55 public synchronized void write(long dpid, List<OFFlowMod> flowMods) {
56 ensureCacheForSwitch(dpid);
57
58 List<OFFlowMod> clones = new ArrayList<OFFlowMod>(flowMods.size());
59
60 //Somehow the OFFlowMods we get passed in will change later on.
61 //No idea how this happens, but we can just clone to prevent problems
62 try {
63 for (OFFlowMod fm : flowMods) {
64 clones.add(fm.clone());
65 }
66 } catch (CloneNotSupportedException e) {
67 log.debug("Clone exception", e);
68 }
69
70 flowCache.get(dpid).addAll(clones);
71
72 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
73
74 if (sw == null) {
75 log.debug("Switch not found when writing flow mods");
76 return;
77 }
78
79 List<OFMessage> msgList = new ArrayList<OFMessage>(clones.size());
80 msgList.addAll(clones);
81
82 try {
83 sw.write(msgList, null);
84 } catch (IOException e) {
85 log.error("Error writing to switch", e);
86 }
87
88
89 }
90
91 public synchronized void delete(long dpid, OFFlowMod flowMod) {
92 List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(1);
93 flowModList.add(flowMod);
94 delete(dpid, flowModList);
95 }
96
97 public synchronized void delete(long dpid, List<OFFlowMod> flowMods) {
98 ensureCacheForSwitch(dpid);
99
100 //Remove the flow mods from the cache first before we alter them
101 flowCache.get(dpid).removeAll(flowMods);
102
103 //Alter the original flow mods to make them delete flow mods
104 for (OFFlowMod fm : flowMods) {
105 fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT)
106 .setOutPort(OFPort.OFPP_NONE)
107 .setLengthU(OFFlowMod.MINIMUM_LENGTH);
108
109 fm.getActions().clear();
110 }
111
112 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
113 if (sw == null) {
114 log.debug("Switch not found when writing flow mods");
115 return;
116 }
117
118 List<OFMessage> msgList = new ArrayList<OFMessage>(flowMods.size());
119 msgList.addAll(flowMods);
120
121 try {
122 sw.write(msgList, null);
123 } catch (IOException e) {
124 log.error("Error writing to switch", e);
125 }
126 }
127
128 //TODO can the Prontos handle being sent all flow mods in one message?
129 public synchronized void switchConnected(IOFSwitch sw) {
130 log.debug("Switch connected: {}", sw);
131
132 ensureCacheForSwitch(sw.getId());
133
134 List<OFFlowMod> flowMods = flowCache.get(sw.getId());
135
136 Collections.sort(flowMods, cookieComparator);
137
138 sw.clearAllFlowMods();
139
140 List<OFMessage> messages = new ArrayList<OFMessage>(flowMods.size());
141 messages.addAll(flowMods);
142
143 try {
144 sw.write(messages, null);
145 } catch (IOException e) {
146 log.error("Failure writing flow mods to switch {}",
147 HexString.toHexString(sw.getId()));
148 }
149 }
150
151 private void ensureCacheForSwitch(long dpid) {
152 if (!flowCache.containsKey(dpid)) {
153 flowCache.put(dpid, new ArrayList<OFFlowMod>());
154 }
155 }
Jonathan Hart1912afc2013-10-11 12:02:44 +1300156}