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