blob: 8f5296461ee0518bbd3c3141017636a592fc2636 [file] [log] [blame]
Sangho Shin2f263692014-09-15 14:09:41 -07001package net.onrc.onos.apps.segmentrouting;
2
Sangho Shin9c0f4c32014-09-26 16:02:38 -07003import java.io.IOException;
Sangho Shin1aa93542014-09-22 09:49:44 -07004import java.net.Inet4Address;
5import java.net.InetAddress;
6import java.net.UnknownHostException;
Sangho Shin2f263692014-09-15 14:09:41 -07007import java.util.ArrayList;
8import java.util.Collection;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -07009import java.util.HashMap;
Sangho Shin5be3e532014-10-03 17:20:58 -070010import java.util.HashSet;
Sangho Shin2f263692014-09-15 14:09:41 -070011import java.util.Iterator;
12import java.util.List;
13import java.util.Map;
Sangho Shin5be3e532014-10-03 17:20:58 -070014import java.util.Set;
Sangho Shin61535402014-10-01 11:37:14 -070015import java.util.concurrent.ConcurrentLinkedQueue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070016import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070017import java.util.concurrent.ScheduledExecutorService;
18import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070019import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070020
21import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070022import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070023import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070024import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070025import net.floodlightcontroller.core.module.FloodlightModuleContext;
26import net.floodlightcontroller.core.module.FloodlightModuleException;
27import net.floodlightcontroller.core.module.IFloodlightModule;
28import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070029import net.floodlightcontroller.core.util.SingletonTask;
30import net.floodlightcontroller.threadpool.IThreadPoolService;
Sangho Shin15273b62014-10-16 22:22:05 -070031import net.floodlightcontroller.util.MACAddress;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070032import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070033import net.onrc.onos.api.packet.IPacketService;
34import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070035import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070036import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070037import net.onrc.onos.core.matchaction.MatchAction;
38import net.onrc.onos.core.matchaction.MatchActionId;
39import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070040import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070041import net.onrc.onos.core.matchaction.action.Action;
42import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
43import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
44import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
45import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
46import net.onrc.onos.core.matchaction.action.GroupAction;
47import net.onrc.onos.core.matchaction.action.PopMplsAction;
48import net.onrc.onos.core.matchaction.action.PushMplsAction;
49import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070050import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070051import net.onrc.onos.core.matchaction.match.Match;
52import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070053import net.onrc.onos.core.matchaction.match.PacketMatch;
54import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070055import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070056import net.onrc.onos.core.packet.Ethernet;
57import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070058import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070059import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070060import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070061import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070062import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070063import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070064import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070065import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070066import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070067import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070068import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070069import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070070import net.onrc.onos.core.util.IPv4Net;
71import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070072
Sangho Shin43cee112014-09-25 16:43:34 -070073import org.json.JSONArray;
74import org.json.JSONException;
Saurav Dasa962a692014-10-17 14:52:38 -070075import org.projectfloodlight.openflow.protocol.OFBarrierReply;
Saurav Dasbc594a42014-09-25 20:13:50 -070076import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070077import org.projectfloodlight.openflow.types.IPv4Address;
78import org.slf4j.Logger;
79import org.slf4j.LoggerFactory;
80
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070081public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070082 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070083
84 private static final Logger log = LoggerFactory
85 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070086
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -070087 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070088 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070089 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070090 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070091
92 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070093 private ArpHandler arpHandler;
94 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070095 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070096 private IThreadPoolService threadPool;
97 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -070098 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -070099 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700100 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700101
Sangho Shinfbc572c2014-10-02 16:37:05 -0700102 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700103 private HashMap<String, LinkData> linksDown;
104 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700105 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shin15273b62014-10-16 22:22:05 -0700106 private HashMap<Integer, HashMap<String, PolicyRouteInfo>> stitchInfo;
107 private HashMap<Integer, HashMap<String, Integer>> tunnelGroupMap;
Sangho Shinbce900e2014-10-07 17:13:23 -0700108
109 private int numOfEvents = 0;
110 private int numOfEventProcess = 0;
111 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700112 private long matchActionId = 0L;
Sangho Shin23f898d2014-10-13 16:54:00 -0700113 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700114 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700115
Sangho Shin2f263692014-09-15 14:09:41 -0700116 @Override
117 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
118 // TODO Auto-generated method stub
119 return null;
120 }
121
122 @Override
123 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
124 // TODO Auto-generated method stub
125 return null;
126 }
127
128 @Override
129 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
130 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
131
132 l.add(IFloodlightProviderService.class);
133 l.add(IConfigInfoService.class);
134 l.add(ITopologyService.class);
135 l.add(IPacketService.class);
136 l.add(IFlowPusherService.class);
137 l.add(ITopologyService.class);
138
139 return l;
140
141 }
142
143 @Override
144 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700145 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700146 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700147 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700148 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700149 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700150 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700151 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700152 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700153 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700154 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700155 linksDown = new HashMap<String, LinkData>();
156 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700157 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700158 stitchInfo = new HashMap<Integer, HashMap<String, PolicyRouteInfo>>();
159 packetService = context.getServiceImpl(IPacketService.class);
160 tunnelGroupMap = new HashMap<Integer, HashMap<String, Integer>>();
Sangho Shin2f263692014-09-15 14:09:41 -0700161
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700162 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700163 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700164
Sangho Shin99918bd2014-10-08 15:52:35 -0700165
Sangho Shin2f263692014-09-15 14:09:41 -0700166 }
167
168 @Override
169 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700170 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700171
Sangho Shinc8d2f592014-09-30 16:53:57 -0700172 discoveryTask = new SingletonTask(ses, new Runnable() {
173 @Override
174 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700175 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700176 }
177 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700178
179 linkAddTask = new SingletonTask(ses, new Runnable() {
180 @Override
181 public void run() {
182 delayedAddLink();
183 }
184 });
185
Sangho Shin15273b62014-10-16 22:22:05 -0700186 testTask = new SingletonTask(ses, new Runnable() {
187 @Override
188 public void run() {
189 runTest();
190 }
191 });
192
193 // policy routing test task
194 //testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700195 }
196
Sangho Shin15273b62014-10-16 22:22:05 -0700197
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700198 @Override
199 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700200 if (payload.getEtherType() == Ethernet.TYPE_ARP)
201 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700202 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700203 addPacket((IPv4) payload.getPayload());
204 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
205 icmpHandler.processPacketIn(sw, inPort, payload);
206 else
207 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700208 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700209 else {
210 log.debug("{}", payload.toString());
211 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700212 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700213
Sangho Shin2f263692014-09-15 14:09:41 -0700214 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700215 * Update ARP Cache using ARP packets It is used to set destination MAC
216 * address to forward packets to known hosts. But, it will be replace with
217 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700218 *
Sangho Shin2f263692014-09-15 14:09:41 -0700219 * @param arp APR packets to use for updating ARP entries
220 */
221 public void updateArpCache(ARP arp) {
222
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700223 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
224 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700225 // TODO: Need to check the duplication
226 arpEntries.add(arpEntry);
227 }
228
229 /**
230 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700231 *
Sangho Shin2f263692014-09-15 14:09:41 -0700232 * @param destinationAddress IP address to get MAC address
233 * @return MAC Address to given IP address
234 */
235 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
236
237 // Can't we get the host IP address from the TopologyService ??
238
239 Iterator<ArpEntry> iterator = arpEntries.iterator();
240
241 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
242 byte[] ipAddressInByte = ipAddress.getBytes();
243
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700244 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700245 ArpEntry arpEntry = iterator.next();
246 byte[] address = arpEntry.targetIpAddress;
247
248 IPv4Address a = IPv4Address.of(address);
249 IPv4Address b = IPv4Address.of(ipAddressInByte);
250
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700251 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700252 log.debug("Found an arp entry");
253 return arpEntry.targetMacAddress;
254 }
255 }
256
257 return null;
258 }
259
Sangho Shineb083032014-09-22 16:11:34 -0700260 /**
261 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700262 *
Sangho Shineb083032014-09-22 16:11:34 -0700263 * @param destinationAddress
264 * @param sw
265 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700266 *
Sangho Shineb083032014-09-22 16:11:34 -0700267 */
268 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
269 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
270 }
Sangho Shin2f263692014-09-15 14:09:41 -0700271
272 /**
273 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700274 *
Sangho Shin2f263692014-09-15 14:09:41 -0700275 */
276 private class ArpEntry {
277
278 byte[] targetMacAddress;
279 byte[] targetIpAddress;
280
281 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
282 this.targetMacAddress = macAddress;
283 this.targetIpAddress = ipAddress;
284 }
Sangho Shin2f263692014-09-15 14:09:41 -0700285 }
Sangho Shineb083032014-09-22 16:11:34 -0700286
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700287 /**
288 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700289 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700290 * @param topologyEvents the generated Topology Events
291 * @see TopologyEvents
292 */
293 public void topologyEvents(TopologyEvents topologyEvents)
294 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700295 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700296 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700297 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700298
Sangho Shin23f898d2014-10-13 16:54:00 -0700299 /**
300 * Process the multiple topology events with some delay (100MS at most for now)
301 *
302 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700303 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700304 numOfEventProcess ++;
305
Sangho Shin51625342014-10-17 09:30:48 -0700306 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
307 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
308 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
309 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
310 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
311 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
312 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700313
Sangho Shin5be3e532014-10-03 17:20:58 -0700314 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700315 // We should handle the events in the order of when they happen
316 // TODO: We need to simulate the final results of multiple events
317 // and shoot only the final state.
318 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
319 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700320
Sangho Shin5be3e532014-10-03 17:20:58 -0700321 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700322
323 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
324 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
325 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
326 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
327 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
328 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
329 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
330
331 linkEntriesAddedAll.addAll(linkEntriesAdded);
332 portEntriesAddedAll.addAll(portEntriesAdded);
333 portEntriesRemovedAll.addAll(portEntriesRemoved);
334 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
335 switchAddedAll.addAll(switchAdded);
336 switchRemovedAll.addAll(switchRemoved);
337 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700338 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700339
340 if (!portEntriesRemoved.isEmpty()) {
341 processPortRemoval(portEntriesRemoved);
342 }
343
344 if (!linkEntriesRemoved.isEmpty()) {
345 processLinkRemoval(linkEntriesRemoved);
346 }
347
348 if (!switchRemoved.isEmpty()) {
349 processSwitchRemoved(switchRemoved);
350 }
351
352 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700353 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700354 }
355
356 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700357 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700358 }
359
360 if (!portEntriesAdded.isEmpty()) {
361 processPortAdd(portEntriesAdded);
362 }
363
364 if (!switchAdded.isEmpty()) {
365 processSwitchAdd(switchAdded);
366 }
Sangho Shin51625342014-10-17 09:30:48 -0700367
Sangho Shinbce900e2014-10-07 17:13:23 -0700368 }
369
Sangho Shin23f898d2014-10-13 16:54:00 -0700370 // TODO: 100ms is enough to check both mastership removed events
371 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700372 if (!mastershipRemovedAll.isEmpty()) {
373 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700374 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700375 }
376 else {
377 HashMap<String, MastershipData> mastershipToRemove =
378 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700379 for (MastershipData ms: mastershipRemovedAll) {
380 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700381 // TODO: check ALL ports of the switch are dead ..
382 if (port.getDpid().equals(ms.getDpid())) {
383 mastershipToRemove.put(ms.getDpid().toString(), ms);
384 }
385 }
386 log.debug("Swtich {} is really down.", ms.getDpid());
387 }
388 processMastershipRemoved(mastershipToRemove.values());
389 }
390 }
391
Sangho Shinbce900e2014-10-07 17:13:23 -0700392 log.debug("num events {}, num of process {}, "
393 + "num of Population {}", numOfEvents, numOfEventProcess,
394 numOfPopulation);
395 }
396
397 /**
Sangho Shin23f898d2014-10-13 16:54:00 -0700398 * Add the link immediately
399 * The function is scheduled when link add event happens and called
400 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
401 */
402 private void delayedAddLink() {
403
404 processLinkAdd(linksToAdd.values(), true);
405
406 }
407
408 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700409 * Process the SwitchAdded events from topologyMananger.
410 * It does nothing. When a switch is added, then link will be added too.
411 * LinkAdded event will handle process all re-computation.
412 *
413 * @param switchAdded
414 */
415 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
416
417 }
418
419 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700420 * Remove all ports connected to the switch removed
421 *
422 * @param mastershipRemoved master switch info removed
423 */
424 private void processMastershipRemoved(Collection<MastershipData>
425 mastershipRemoved) {
426 for (MastershipData mastership: mastershipRemoved) {
427 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
428 for (Link link: sw.getOutgoingLinks()) {
429 Port dstPort = link.getDstPort();
430 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
431 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700432 if (dstSw != null) {
433 dstSw.removePortFromGroups(dstPort.getNumber());
434 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
435 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700436 }
Sangho Shin61535402014-10-01 11:37:14 -0700437 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700438
439 linksToAdd.clear();
440 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700441 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700442
Sangho Shinbce900e2014-10-07 17:13:23 -0700443 /**
444 * Remove all ports connected to the switch removed
445 *
446 * @param switchRemoved Switch removed
447 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700448 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700449 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700450 }
451
Sangho Shin61535402014-10-01 11:37:14 -0700452 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700453 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700454 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700455 * @param portEntries
456 */
457 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700458 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700459 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700460 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700461
Sangho Shinfbc572c2014-10-02 16:37:05 -0700462 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700463 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700464 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700465 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700466 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700467 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700468 }
469 }
470
471 /**
472 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700473 * If the link to add was removed before, then we just schedule the add link
474 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700475 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700476 * @param linkEntries
477 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700478 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700479
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700480 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700481
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700482 SwitchPort srcPort = link.getSrc();
483 SwitchPort dstPort = link.getDst();
484
Sangho Shin23f898d2014-10-13 16:54:00 -0700485 String key = srcPort.getDpid().toString() +
486 dstPort.getDpid().toString();
487 if (!delayed) {
488 if (linksDown.containsKey(key)) {
489 linksToAdd.put(key, link);
490 linksDown.remove(key);
491 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
492 log.debug("Add link {} with 5 sec delay", link);
493 // TODO: What if we have multiple events of add link:
494 // one is new link add, the other one is link up for
495 // broken link? ECMPSPG function cannot deal with it for now
496 return;
497 }
498 }
499 else {
500 if (linksDown.containsKey(key)) {
501 linksToAdd.remove(key);
502 log.debug("Do not add the link {}: it is down again!", link);
503 return;
504 }
505 }
506
Sangho Shinfbc572c2014-10-02 16:37:05 -0700507 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700508 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700509 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700510 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700511
Sangho Shin815af0c2014-10-10 13:05:45 -0700512 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700513 continue;
514
515 srcSw.addPortToGroups(srcPort.getPortNumber());
516 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700517
Sangho Shin15273b62014-10-16 22:22:05 -0700518 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
519 // link);
520 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
521 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700522
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700523 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700524 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700525 }
526
527 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700528 * Check if all links are gone b/w the two switches. If all links are gone,
529 * then we need to recalculate the path. Otherwise, just report link failure
530 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700531 *
Sangho Shin61535402014-10-01 11:37:14 -0700532 * @param linkEntries
533 */
534 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700535 boolean recomputationRequired = false;
536
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700537 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700538 SwitchPort srcPort = link.getSrc();
539 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700540
Sangho Shinfbc572c2014-10-02 16:37:05 -0700541 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700542 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700543 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700544 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700545 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700546 /* If this link is not between two switches, ignore it */
547 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700548
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700549 srcSw.removePortFromGroups(srcPort.getPortNumber());
550 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700551 log.debug("Remove port {} from switch {}", srcPort, srcSw);
552 log.debug("Remove port {} from switch {}", dstPort, dstSw);
553
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700554 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
555 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700556 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700557 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700558 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700559 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700560 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700561 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700562
563 String key = link.getSrc().getDpid().toString()+
564 link.getDst().getDpid().toString();
565 if (!linksDown.containsKey(key)) {
566 linksDown.put(key, link);
567 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700568 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700569
570 if (recomputationRequired)
571 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700572 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700573
Sangho Shin61535402014-10-01 11:37:14 -0700574 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700575 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700576 *
Sangho Shin61535402014-10-01 11:37:14 -0700577 * @param portEntries
578 */
579 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700580 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700581 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700582
Sangho Shinfbc572c2014-10-02 16:37:05 -0700583 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700584 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700585 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700586 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700587 log.debug("Remove port {} from switch {}", port, dpid);
588 }
Sangho Shin61535402014-10-01 11:37:14 -0700589 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700590 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700591
592 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700593 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700594 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700595 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700596 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700597 private void populateEcmpRoutingRules(boolean modified) {
598 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700599 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700600 for (Switch sw : switches) {
601 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700602 graphs.put(sw, ecmpSPG);
603 //log.debug("ECMPShortestPathGraph is computed for switch {}",
604 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700605 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700606 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700607 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700608 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700609
Sangho Shin99918bd2014-10-08 15:52:35 -0700610 /**
611 * populate routing rules to forward packets from the switch given to
612 * all other switches.
613 *
614 * @param sw source switch
615 * @param ecmpSPG shortest path from the the source switch to all others
616 * @param modified modification flag
617 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700618 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700619 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700620
Sangho Shinfbc572c2014-10-02 16:37:05 -0700621 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
622 ecmpSPG.getAllLearnedSwitchesAndVia();
623 for (Integer itrIdx : switchVia.keySet()) {
624 //log.debug("ECMPShortestPathGraph:Switches learned in "
625 // + "Iteration{} from switch {}:",
626 // itrIdx,
627 // HexString.toHexString(sw.getDpid().value()));
628 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
629 switchVia.get(itrIdx);
630 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700631 //log.debug("ECMPShortestPathGraph:****switch {} via:",
632 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700633 String destSw = sw.getDpid().toString();
634 List<String> fwdToSw = new ArrayList<String>();
635
Sangho Shinfbc572c2014-10-02 16:37:05 -0700636 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700637 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700638 if (via.isEmpty()) {
639 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700640 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700641 else {
642 fwdToSw.add(via.get(0).toString());
643 }
Sangho Shin43cee112014-09-25 16:43:34 -0700644 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700645 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700646 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700647
648 // Send Barrier Message and make sure all rules are set
649 // before we set the rules to next routers
Saurav Dasa962a692014-10-17 14:52:38 -0700650 // TODO: barriers to all switches in this update stage
Sangho Shinfbc572c2014-10-02 16:37:05 -0700651 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
652 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700653 if (sw13 != null) {
Saurav Dasa962a692014-10-17 14:52:38 -0700654 OFBarrierReplyFuture replyFuture = null;
Sangho Shin5be3e532014-10-03 17:20:58 -0700655 try {
Saurav Dasa962a692014-10-17 14:52:38 -0700656 replyFuture = sw13.sendBarrier();
Sangho Shin5be3e532014-10-03 17:20:58 -0700657 } catch (IOException e) {
Saurav Dasa962a692014-10-17 14:52:38 -0700658 log.error("Error sending barrier request to switch {}",
659 sw13.getId(), e.getCause());
Sangho Shin5be3e532014-10-03 17:20:58 -0700660 }
Saurav Dasa962a692014-10-17 14:52:38 -0700661 OFBarrierReply br = null;
662 try {
663 br = replyFuture.get(2, TimeUnit.SECONDS);
664 } catch (TimeoutException | InterruptedException | ExecutionException e) {
665 // XXX for some reason these exceptions are not being thrown
666 }
667 if (br == null) {
668 log.warn("Did not receive barrier-reply from {}", sw13.getId());
669 // XXX take corrective action
670 }
671
Sangho Shinfbc572c2014-10-02 16:37:05 -0700672 }
673 }
674
675 }
676
677
Sangho Shin99918bd2014-10-08 15:52:35 -0700678 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700679 * This class is used only for link recovery optimization in
680 * modifyEcmpRoutingRules() function.
Sangho Shin99918bd2014-10-08 15:52:35 -0700681 * TODO: please remove if the optimization is not used at all
Sangho Shinbce900e2014-10-07 17:13:23 -0700682 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700683 private class SwitchPair {
684 private Switch src;
685 private Switch dst;
686
687 public SwitchPair(Switch src, Switch dst) {
688 this.src = src;
689 this.dst = dst;
690 }
691
692 public Switch getSource() {
693 return src;
694 }
695
696 public Switch getDestination() {
697 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700698 }
Sangho Shin43cee112014-09-25 16:43:34 -0700699 }
700
701 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700702 * Modify the routing rules for the lost links
703 * - Recompute the path if the link failed is included in the path
704 * (including src and dest).
705 *
706 * @param newLink
707 */
708 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
709
710 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700711 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700712
713 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
714 Switch rootSw = ecmpSPG.getRootSwitch();
715 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
716 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
717 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
718 for (Switch destSw: p.keySet()) {
719 ArrayList<Path> path = p.get(destSw);
720 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700721 boolean found = false;
722 for (SwitchPair pair: linksToRecompute) {
723 if (pair.getSource().getDpid() == rootSw.getDpid() &&
724 pair.getSource().getDpid() == destSw.getDpid()) {
725 found = true;
726 }
727 }
728 if (!found) {
729 linksToRecompute.add(new SwitchPair(rootSw, destSw));
730 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700731 }
732 }
733 }
734 }
735
736 // Recompute the path for the specific route
737 for (SwitchPair pair: linksToRecompute) {
738
739 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
Sangho Shin99918bd2014-10-08 15:52:35 -0700740 // We need the following function for optimization
Sangho Shinfbc572c2014-10-02 16:37:05 -0700741 //ECMPShortestPathGraph ecmpSPG =
742 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
743 ECMPShortestPathGraph ecmpSPG =
744 new ECMPShortestPathGraph(pair.getSource());
Sangho Shin5be3e532014-10-03 17:20:58 -0700745 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700746 }
747 }
748
749 /**
750 * Check if the path is affected from the link removed
751 *
752 * @param path Path to check
753 * @param linkRemoved link removed
754 * @return true if the path contains the link removed
755 */
756 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
757
758 for (Path ppp: path) {
759 // TODO: need to check if this is a bidirectional or
760 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700761 for (LinkData link: ppp) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700762 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
763 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
764 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700765 }
766 }
767
768 return false;
769 }
770
771 /**
772 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700773 * Set routing rules in targetSw {forward packets to fwdToSw switches in
774 * order to send packets to destSw} - If the target switch is an edge router
775 * and final destnation switch is also an edge router, then set IP
776 * forwarding rules to subnets - If only the target switch is an edge
777 * router, then set IP forwarding rule to the transit router loopback IP
778 * address - If the target is a transit router, then just set the MPLS
779 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700780 *
Sangho Shin43cee112014-09-25 16:43:34 -0700781 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700782 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700783 * @param fwdToSw next hop switches
784 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700785 private void setRoutingRule(Switch targetSw, String destSw,
786 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700787
Sangho Shin43cee112014-09-25 16:43:34 -0700788 if (fwdToSw.isEmpty()) {
789 fwdToSw.add(destSw);
790 }
791
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700792 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700793 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
794 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700795 // We assume that there is at least one transit router b/w edge
796 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700797 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
798 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700799 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700800 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700801
Sangho Shin43cee112014-09-25 16:43:34 -0700802 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700803 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
804 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700805 // Edge router can be a transit router
806 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700807 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700808 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700809 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700810 // We assume that there is at least one transit router b/w edge
811 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700812 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
813 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700814 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
815 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700816 // Edge router can be a transit router
817 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700818 }
819 // if it is a transit router, then set rules in the MPLS table
820 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700821 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700822 }
823
824 }
825
Sangho Shinfbc572c2014-10-02 16:37:05 -0700826 /**
827 * Set IP forwarding rule to the gateway of each subnet of switches
828 *
829 * @param targetSw Switch to set rules
830 * @param subnets subnet information
831 * @param mplsLabel destination MPLS label
832 * @param fwdToSw router to forward packets to
833 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700834 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700835 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700836
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700837 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700838 new ArrayList<MatchActionOperationEntry>();
839
840 try {
841 JSONArray arry = new JSONArray(subnets);
842 for (int i = 0; i < arry.length(); i++) {
843 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700844 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
845 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700846 }
847 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700848 e.printStackTrace();
849 }
850
851 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700852 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700853 getSwId(targetSw.getDpid().toString()));
854
Sangho Shin721ca042014-10-09 13:03:40 -0700855 if (sw13 != null) {
856 try {
857 sw13.pushFlows(entries);
858 } catch (IOException e) {
859 e.printStackTrace();
860 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700861 }
862 }
863
864 }
865
Sangho Shin43cee112014-09-25 16:43:34 -0700866 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700867 * Check if the switch is the edge router or not.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700868 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700869 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700870 * @return true if it is an edge router, otherwise false
871 */
872 private boolean IsEdgeRouter(String dpid) {
873
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700874 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700875 String dpidStr = sw.getDpid().toString();
876 if (dpid.equals(dpidStr)) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700877 /*
Sangho Shin43cee112014-09-25 16:43:34 -0700878 String subnetInfo = sw.getStringAttribute("subnets");
879 if (subnetInfo == null || subnetInfo.equals("[]")) {
880 return false;
881 }
882 else
883 return true;
Sangho Shinbce900e2014-10-07 17:13:23 -0700884 */
885 String isEdge = sw.getStringAttribute("isEdgeRouter");
886 if (isEdge != null) {
887 if (isEdge.equals("true"))
888 return true;
889 else
890 return false;
891 }
Sangho Shin43cee112014-09-25 16:43:34 -0700892 }
893 }
894
895 return false;
896 }
897
898 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700899 * Set IP forwarding rule - If the destination is the next hop, then do not
900 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
901 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700902 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700903 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700904 * @param subnetIp Match IP address
905 * @param mplsLabel MPLS label of final destination router
906 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700907 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700908 */
909 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700910 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
911 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700912
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700913 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700914 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700915 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700916
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700917 // If destination SW is the same as the fwd SW, then do not push MPLS
918 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700919 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700920 PushMplsAction pushMplsAction = new PushMplsAction();
921 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
922 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700923 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700924
Sangho Shin62ce5c12014-10-08 16:24:40 -0700925 //actions.add(pushMplsAction);
926 //actions.add(copyTtlOutAction);
927 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700928 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700929 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700930 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700931 else {
932 String fwdToSw = fwdToSws.get(0);
933 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
934 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
935 actions.add(decTtlAction);
936 }
937 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700938 SetMplsIdAction setIdAction = new SetMplsIdAction(
939 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700940 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700941 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700942
Sangho Shin62ce5c12014-10-08 16:24:40 -0700943 //actions.add(pushMplsAction);
944 //actions.add(copyTtlOutAction);
945 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700946 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700947 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700948 }
949 }
Sangho Shin43cee112014-09-25 16:43:34 -0700950
Sangho Shin43cee112014-09-25 16:43:34 -0700951 for (String fwdSw : fwdToSws) {
952 groupAction.addSwitch(new Dpid(fwdSw));
953 }
954 actions.add(groupAction);
955
Sangho Shin99918bd2014-10-08 15:52:35 -0700956 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700957 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700958
Sangho Shin5be3e532014-10-03 17:20:58 -0700959 Operator operator = null;
960 if (modified)
961 operator = Operator.MODIFY;
962 else
963 operator = Operator.ADD;
964
Sangho Shin43cee112014-09-25 16:43:34 -0700965 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700966 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700967
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700968 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700969 getSwId(sw.getDpid().toString()));
970
Sangho Shin5be3e532014-10-03 17:20:58 -0700971 if (sw13 != null) {
972 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700973 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700974 if (entries != null)
975 entries.add(maEntry);
976 else
977 sw13.pushFlow(maEntry);
978 } catch (IOException e) {
979 e.printStackTrace();
980 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700981 }
982
Sangho Shin43cee112014-09-25 16:43:34 -0700983 }
984
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700985 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700986 * Set MPLS forwarding rules to MPLS table
987 * </p>
988 * If the destination is the same as the next hop to forward packets then,
989 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
990 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
991 * TTL of the another MPLS header.
992 * If the next hop is not the destination, just forward packets to next
993 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700994 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700995 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700996 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700997 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700998 * */
Sangho Shin5be3e532014-10-03 17:20:58 -0700999 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
1000 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -07001001
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001002 if (fwdSws.isEmpty())
1003 return;
Sangho Shin43cee112014-09-25 16:43:34 -07001004
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001005 Collection<MatchActionOperationEntry> maEntries =
1006 new ArrayList<MatchActionOperationEntry>();
1007 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -07001008
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001009 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
1010 // One rule for Bos = 1
1011 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
1012 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001013
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001014 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
1015 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
1016 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
1017
1018 actions.add(copyTtlInAction);
1019 actions.add(popAction);
1020 actions.add(decNwTtlAction);
1021
1022 GroupAction groupAction = new GroupAction();
1023 groupAction.addSwitch(new Dpid(fwdSw1));
1024 actions.add(groupAction);
1025
1026 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
1027 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1028 Operator operator = Operator.ADD;
1029 MatchActionOperationEntry maEntry =
1030 new MatchActionOperationEntry(operator, matchAction);
1031 maEntries.add(maEntry);
1032
1033 // One rule for Bos = 0
Sangho Shin23f898d2014-10-13 16:54:00 -07001034 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001035 List<Action> actionsBos = new ArrayList<Action>();
Sangho Shin15273b62014-10-16 22:22:05 -07001036 PopMplsAction popActionBos = new PopMplsAction(EthType.MPLS_UNICAST);
1037 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1038
1039 actionsBos.add(copyTtlInAction);
1040 actionsBos.add(popActionBos);
1041 actionsBos.add(decMplsTtlAction);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001042 actionsBos.add(groupAction);
1043
1044 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
1045 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
1046 MatchActionOperationEntry maEntryBos =
1047 new MatchActionOperationEntry(operator, matchActionBos);
1048 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001049 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001050 else {
1051 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
1052 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -07001053
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001054 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1055 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -07001056
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001057 GroupAction groupAction = new GroupAction();
1058 for (String fwdSw : fwdSws)
1059 groupAction.addSwitch(new Dpid(fwdSw));
1060 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -07001061
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001062 MatchAction matchAction = new MatchAction(new MatchActionId(
1063 matchActionId++),
1064 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1065 Operator operator = Operator.ADD;
1066 MatchActionOperationEntry maEntry =
1067 new MatchActionOperationEntry(operator, matchAction);
1068 maEntries.add(maEntry);
Sangho Shine2e9bcd2014-10-13 15:14:18 -07001069
1070 // BoS = 1
1071 MplsMatch mplsMatchBoS = new MplsMatch(Integer.parseInt(mplsLabel), true);
1072 List<Action> actionsBoS = new ArrayList<Action>();
1073
1074 DecMplsTtlAction decMplsTtlActionBoS = new DecMplsTtlAction(1);
1075 actionsBoS.add(decMplsTtlActionBoS);
1076
1077 GroupAction groupActionBoS = new GroupAction();
1078 for (String fwdSw : fwdSws)
1079 groupActionBoS.addSwitch(new Dpid(fwdSw));
1080 actionsBoS.add(groupActionBoS);
1081
1082 MatchAction matchActionBos = new MatchAction(new MatchActionId(
1083 matchActionId++),
1084 new SwitchPort((long) 0, (short) 0), mplsMatchBoS, actionsBoS);
1085 MatchActionOperationEntry maEntryBoS =
1086 new MatchActionOperationEntry(operator, matchActionBos);
1087 maEntries.add(maEntryBoS);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001088 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001089 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001090 getSwId(sw.getDpid().toString()));
1091
Sangho Shin5be3e532014-10-03 17:20:58 -07001092 if (sw13 != null) {
1093 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001094 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001095 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001096 } catch (IOException e) {
1097 e.printStackTrace();
1098 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001099 }
Sangho Shin43cee112014-09-25 16:43:34 -07001100 }
1101
Sangho Shin15273b62014-10-16 22:22:05 -07001102 /**
1103 * Create a tunnel for policy routing
1104 * It delivers the node IDs of tunnels to driver.
1105 * Split the node IDs if number of IDs exceeds the limit for stitching.
1106 *
1107 * @param tunnelId Node IDs for the tunnel
1108 * @param Ids tunnel ID
1109 */
1110 public boolean createTunnel(int tunnelId, List<String> Ids) {
1111
1112 if (tunnelId < 0) {
1113 log.debug("Tunnel ID should be posivtive integer.");
1114 return false;
1115 }
1116
1117 if (Ids.isEmpty() || Ids.size() < 2) {
1118 log.debug("Wrong tunnel information");
1119 return false;
1120 }
1121
1122 HashMap<String, PolicyRouteInfo> stitchingRule = getStitchingRule(Ids);
1123 stitchInfo.put(Integer.valueOf(tunnelId), stitchingRule);
1124 if (stitchingRule == null) {
1125 log.debug("Failed to get the policy rule.");
1126 return false;
1127 }
1128 HashMap<String, Integer> switchGroupPair = new HashMap<String, Integer>();
1129 for (String targetDpid: stitchingRule.keySet()) {
1130 PolicyRouteInfo route = stitchingRule.get(targetDpid);
1131
1132 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
1133 getSwId(targetDpid.toString()));
1134
1135 if (targetSw == null) {
1136 log.debug("Switch {} is gone.", targetDpid);
1137 return false;
1138 }
1139
1140 NeighborSet ns = new NeighborSet();
1141 for (Dpid dpid: route.getFwdSwDpid())
1142 ns.addDpid(dpid);
1143
1144 printTunnelInfo(targetSw, tunnelId, route.getRoute(), ns);
1145 int groupId = targetSw.createTunnel(tunnelId, route.getRoute(), ns);
1146 switchGroupPair.put(targetDpid.toString(), groupId);
1147
1148 }
1149
1150 tunnelGroupMap.put(Integer.valueOf(tunnelId), switchGroupPair);
1151
1152 return true;
1153 }
1154
1155 /**
1156 * Set policy table for policy routing
1157 *
1158 * @param sw
1159 * @param mplsLabel
1160 */
Sangho Shin51625342014-10-17 09:30:48 -07001161 public void setPolicyTable(MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001162 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
1163 Short srcTcpPort, Short dstTcpPort, int tid) {
1164
1165 HashMap<String, PolicyRouteInfo> routeInfo = stitchInfo.get(Integer.valueOf(tid));
1166 HashMap<String, Integer> switchGroupPair = tunnelGroupMap.get(Integer.valueOf(tid));
1167 for (String srcDpid: routeInfo.keySet()) {
1168
1169 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1170
1171 if (srcMac != null)
1172 packetBuilder.setSrcMac(srcMac);
1173 if (dstMac != null)
1174 packetBuilder.setDstMac(dstMac);
1175 if (etherType != null) {
1176 packetBuilder.setEtherType(etherType);
1177 }
1178 if (srcIp != null) {
1179 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1180 }
1181 if (dstIp != null) {
1182 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1183 }
1184 if (ipProto != null) {
1185 packetBuilder.setIpProto(ipProto);
1186 }
1187 if (srcTcpPort > 0) {
1188 packetBuilder.setSrcTcpPort(srcTcpPort);
1189 }
1190 if (dstTcpPort > 0) {
1191 packetBuilder.setDstTcpPort(dstTcpPort);
1192 }
1193 PacketMatch policyMatch = packetBuilder.build();
1194
1195 List<Action> actions = new ArrayList<>();
1196 GroupAction groupAction = new GroupAction();
1197 int gropuId = switchGroupPair.get(srcDpid);
1198 groupAction.setGroupId(gropuId);
1199 actions.add(groupAction);
1200
1201 MatchAction matchAction = new MatchAction(new MatchActionId(
1202 matchActionId++),
1203 new SwitchPort((long) 0, (short) 0), policyMatch, actions);
1204 MatchActionOperationEntry maEntry =
1205 new MatchActionOperationEntry(Operator.ADD, matchAction);
1206
1207 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1208 getSwId(srcDpid));
1209
1210 if (sw13 != null) {
1211 printMatchActionOperationEntry(sw13, maEntry);
1212 try {
1213 sw13.pushFlow(maEntry);
1214 } catch (IOException e) {
1215 e.printStackTrace();
1216 }
1217 }
1218 }
1219 }
1220
1221 /**
1222 * Get the forwarding Switch DPIDs to send packets to a node
1223 *
1224 * @param srcSw source switch
1225 * @param nodeId destination node Id
1226 * @return list of switch DPID to forward packets to
1227 */
1228
1229 private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
1230
1231 List<Dpid> fwdSws = new ArrayList<Dpid>();
1232 Switch destSw = null;
1233
1234 destSw = getSwitchFromNodeId(nodeId);
1235
1236 if (destSw == null) {
1237 log.debug("Cannot find the switch with ID {}", nodeId);
1238 return null;
1239 }
1240
1241 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1242
1243 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1244 ecmpSPG.getAllLearnedSwitchesAndVia();
1245 for (Integer itrIdx : switchVia.keySet()) {
1246 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1247 switchVia.get(itrIdx);
1248 for (Switch targetSw : swViaMap.keySet()) {
1249 String destSwDpid = destSw.getDpid().toString();
1250 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1251 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1252 if (via.isEmpty()) {
1253 fwdSws.add(destSw.getDpid());
1254 }
1255 else {
1256 fwdSws.add(via.get(0));
1257 }
1258 }
1259 }
1260 }
1261 }
1262
1263 return fwdSws;
1264 }
1265
1266 /**
1267 * Get switch for the node Id specified
1268 *
1269 * @param nodeId node ID for switch
1270 * @return Switch
1271 */
1272 private Switch getSwitchFromNodeId(String nodeId) {
1273
1274 for (Switch sw : mutableTopology.getSwitches()) {
1275 String id = sw.getStringAttribute("nodeSid");
1276 if (id.equals(nodeId)) {
1277 return sw;
1278 }
1279 }
1280
1281 return null;
1282 }
1283
1284 /**
1285 * Convert a string DPID to its Switch Id (integer)
1286 *
1287 * @param dpid
1288 * @return
1289 */
1290 private long getSwId(String dpid) {
1291
1292 long swId = 0;
1293
1294 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1295 if (swIdHexStr != null)
1296 swId = Integer.decode(swIdHexStr);
1297
1298 return swId;
1299 }
1300
1301 private void runTest() {
1302
1303 String[] routeArray = {"101", "102", "103", "104", "105", "108", "110"};
1304 List<String> routeList = new ArrayList<String>();
1305 for (int i = 0; i < routeArray.length; i++)
1306 routeList.add(routeArray[i]);
1307
1308 if (createTunnel(1, routeList)) {
1309 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1310 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1311
1312 this.setPolicyTable(null, null, Ethernet.TYPE_IPV4, srcIp, dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 1);
1313 }
1314 else {
1315 testTask.reschedule(5, TimeUnit.SECONDS);
1316 }
1317 }
1318
1319 private void runTest1() {
1320
1321 String dpid1 = "00:00:00:00:00:00:00:01";
1322 String dpid2 = "00:00:00:00:00:00:00:0a";
1323 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1324 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1325
1326 if (srcSw == null || dstSw == null) {
1327 testTask.reschedule(1, TimeUnit.SECONDS);
1328 log.debug("Switch is gone. Reschedule the test");
1329 return;
1330 }
1331
1332 String[] routeArray = {"101", "102", "105", "108", "110"};
1333 List<String> routeList = new ArrayList<String>();
1334 for (int i = 0; i < routeArray.length; i++)
1335 routeList.add(routeArray[i]);
1336
1337 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1338
1339 log.debug("Test set is {}", routeList.toString());
1340 log.debug("Result set is {}", optimizedRoute.toString());
1341
1342
1343 }
1344
1345 /**
1346 * Optimize the mpls label
1347 * The feature will be used only for policy of "avoid a specific switch".
1348 * Check route to each router in route backward.
1349 * If there is only one route to the router and the routers are included in
1350 * the route, remove the id from the path.
1351 * A-B-C-D-E => A-B-C-D-E -> A-E
1352 * | | => A-B-H-I -> A-I
1353 * F-G-H-I => A-D-I -> A-D-I
1354 */
1355 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
1356
1357 List<String> optimizedPath = new ArrayList<String>();
1358 optimizedPath.addAll(route);
1359 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1360
1361 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
1362 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
1363 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
1364 for (Switch s: p.keySet()) {
1365 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
1366 ArrayList<Path> ecmpPaths = p.get(s);
1367 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
1368 for (Path path: ecmpPaths) {
1369 for (LinkData link: path) {
1370 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
1371 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
1372 if (optimizedPath.contains(srcId)) {
1373 optimizedPath.remove(srcId);
1374 }
1375 if (optimizedPath.contains(dstId)) {
1376 optimizedPath.remove(dstId);
1377 }
1378 }
1379 }
1380 }
1381 }
1382 }
1383 }
1384
1385 return optimizedPath;
1386
1387 }
1388
1389
1390 class PolicyRouteInfo {
1391
1392 String srcSwDpid;
1393 List<Dpid> fwdSwDpids;
1394 List<String> route;
1395
1396 PolicyRouteInfo() {
1397 fwdSwDpids = new ArrayList<Dpid>();
1398 route = new ArrayList<String>();
1399 }
1400
1401 void setSrcDpid(String dpid) {
1402 this.srcSwDpid = dpid;
1403 }
1404
1405 void setFwdSwDpid(List<Dpid> dpid) {
1406 this.fwdSwDpids = dpid;
1407 }
1408
1409 void addRoute(String id) {
1410 route.add(id);
1411 }
1412
1413 void setRoute(List<String> r) {
1414 this.route = r;
1415 }
1416
1417 String getSrcSwDpid() {
1418 return this.srcSwDpid;
1419 }
1420
1421 List<Dpid> getFwdSwDpid() {
1422 return this.fwdSwDpids;
1423 }
1424
1425 List<String> getRoute() {
1426 return this.route;
1427 }
1428 }
1429
1430
1431 /**
1432 *
1433 *
1434 * @param srcSw
1435 * @param dstSw
1436 * @param route
1437 * @return
1438 */
1439 private HashMap<String, PolicyRouteInfo> getStitchingRule(List<String> route) {
1440
1441 if (route.isEmpty() || route.size() < 2)
1442 return null;
1443
1444 HashMap<String, PolicyRouteInfo> rules = new HashMap<String, PolicyRouteInfo>();
1445
1446 Switch srcSw = this.getSwitchFromNodeId(route.get(0));
1447 String srcDpid = srcSw.getDpid().toString();
1448
1449 if (route.size() <= MAX_NUM_LABELS+1) {
1450 PolicyRouteInfo info = new PolicyRouteInfo();
1451 info.setSrcDpid(srcSw.getDpid().toString());
1452 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, route.get(1));
1453 info.setFwdSwDpid(fwdSwDpids);
1454 route.remove(0);
1455 info.setRoute(route);
1456 rules.put(srcDpid, info);
1457 return rules;
1458 }
1459
1460 int i = 0;
1461 PolicyRouteInfo routeInfo = new PolicyRouteInfo();
1462 String prevNodeId = null;
1463 boolean checkNeighbor = true;
1464
1465 for (String nodeId: route) {
1466 if (i == 0) {
1467 routeInfo.setSrcDpid(srcDpid);
1468 srcSw = getSwitchFromNodeId(nodeId);
1469 i++;
1470 }
1471 else if (i == 1) {
1472 if (checkNeighbor) {
1473 // Check if next node is the neighbor SW of the source SW
1474 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
1475 if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
1476 log.debug("There is no route from node {} to node {}", srcSw.getDpid(), nodeId);
1477 return null;
1478 }
1479 // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
1480 boolean match = false;
1481 for (Dpid dpid: fwdSwDpids) {
1482 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1483 List<Dpid> fwdSws = new ArrayList<Dpid>();
1484 fwdSws.add(dpid);
1485 routeInfo.setFwdSwDpid(fwdSws);
1486 match = true;
1487 break;
1488 }
1489 }
1490 if (!match) {
1491 routeInfo.addRoute(nodeId);
1492 routeInfo.setFwdSwDpid(fwdSwDpids);
1493 i++;
1494 }
1495
1496 checkNeighbor = false;
1497 }
1498 else {
1499 routeInfo.addRoute(nodeId);
1500 i++;
1501 }
1502 }
1503 else {
1504 routeInfo.addRoute(nodeId);
1505 i++;
1506 }
1507
1508 if (i == MAX_NUM_LABELS+1) {
1509 rules.put(srcDpid, routeInfo);
1510 routeInfo = new PolicyRouteInfo();
1511 srcSw = getSwitchFromNodeId(nodeId);
1512 srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
1513 routeInfo.setSrcDpid(srcDpid);
1514 i = 1;
1515 checkNeighbor = true;
1516 }
1517 }
1518
1519 if (i < MAX_NUM_LABELS+1) {
1520 rules.put(srcDpid, routeInfo);
1521 }
1522
1523 return rules;
1524 }
1525
1526 /**
1527 * print tunnel info - used only for debugging.
1528 * @param targetSw
1529 *
1530 * @param fwdSwDpids
1531 * @param ids
1532 * @param tunnelId
1533 */
1534 private void printTunnelInfo(IOF13Switch targetSw, int tunnelId,
1535 List<String> ids, NeighborSet ns) {
1536 StringBuilder logStr = new StringBuilder("In switch " +
1537 targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
1538 for (String id: ids)
1539 logStr.append(id + "-");
1540 logStr.append(" output to ");
1541 for (Dpid dpid: ns.getDpids())
1542 logStr.append(dpid + " - ");
1543
1544 log.debug(logStr.toString());
1545
1546 }
1547
1548
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001549
Sangho Shin43cee112014-09-25 16:43:34 -07001550 /**
1551 * Debugging function to print out the Match Action Entry
Sangho Shin15273b62014-10-16 22:22:05 -07001552 * @param sw13
Sangho Shinfbc572c2014-10-02 16:37:05 -07001553 *
Sangho Shin43cee112014-09-25 16:43:34 -07001554 * @param maEntry
1555 */
Sangho Shin15273b62014-10-16 22:22:05 -07001556 private void printMatchActionOperationEntry(
1557 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -07001558
Sangho Shin15273b62014-10-16 22:22:05 -07001559 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001560
1561 MatchAction ma = maEntry.getTarget();
1562 Match m = ma.getMatch();
1563 List<Action> actions = ma.getActions();
1564
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001565 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -07001566 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001567 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -07001568 logStr.append(ip.toString());
1569 logStr.append(" then ");
1570 }
1571 else if (m instanceof MplsMatch) {
1572 logStr.append("If the MPLS label matches with ");
1573 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1574 logStr.append(mplsLabel);
1575 logStr.append(" then ");
1576 }
Sangho Shin15273b62014-10-16 22:22:05 -07001577 else if (m instanceof PacketMatch) {
1578 GroupAction ga = (GroupAction)actions.get(0);
1579 logStr.append("if the policy match is XXX then go to group " +
1580 ga.getGroupId());
1581 log.debug(logStr.toString());
1582 return;
1583 }
Sangho Shin43cee112014-09-25 16:43:34 -07001584
1585 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001586 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -07001587 if (action instanceof CopyTtlInAction) {
1588 logStr.append("copy ttl In, ");
1589 }
1590 else if (action instanceof CopyTtlOutAction) {
1591 logStr.append("copy ttl Out, ");
1592 }
1593 else if (action instanceof DecMplsTtlAction) {
1594 logStr.append("Dec MPLS TTL , ");
1595 }
1596 else if (action instanceof GroupAction) {
1597 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001598 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -07001599 logStr.append(dpids.toString() + ",");
1600
Sangho Shin43cee112014-09-25 16:43:34 -07001601 }
1602 else if (action instanceof PopMplsAction) {
1603 logStr.append("Pop MPLS label, ");
1604 }
1605 else if (action instanceof PushMplsAction) {
1606 logStr.append("Push MPLS label, ");
1607 }
1608 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001609 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -07001610 logStr.append("Set MPLS ID as " + id + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001611 }
1612 }
1613
1614 log.debug(logStr.toString());
1615
Sangho Shineb083032014-09-22 16:11:34 -07001616 }
1617
1618 /**
1619 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001620 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001621 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001622 * @return MPLS label for the switch
1623 */
1624
Sangho Shin43cee112014-09-25 16:43:34 -07001625 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001626
1627 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001628 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001629 String dpidStr = sw.getDpid().toString();
1630 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001631 mplsLabel = sw.getStringAttribute("nodeSid");
1632 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001633 }
1634 }
1635
Sangho Shineb083032014-09-22 16:11:34 -07001636 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001637 }
1638
Sangho Shineb083032014-09-22 16:11:34 -07001639 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001640 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001641 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001642 * @param addr - subnet address to match
1643 * @param addr1 - IP address to check
1644 * @return true if the IP address matches to the subnet, otherwise false
1645 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001646 public boolean netMatch(String addr, String addr1) { // addr is subnet
1647 // address and addr1 is
1648 // ip address. Function
1649 // will return true, if
1650 // addr1 is within
1651 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001652
1653 String[] parts = addr.split("/");
1654 String ip = parts[0];
1655 int prefix;
1656
1657 if (parts.length < 2) {
1658 prefix = 0;
1659 } else {
1660 prefix = Integer.parseInt(parts[1]);
1661 }
1662
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001663 Inet4Address a = null;
1664 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001665 try {
1666 a = (Inet4Address) InetAddress.getByName(ip);
1667 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001668 } catch (UnknownHostException e) {
1669 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001670
1671 byte[] b = a.getAddress();
1672 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001673 ((b[1] & 0xFF) << 16) |
1674 ((b[2] & 0xFF) << 8) |
1675 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001676
1677 byte[] b1 = a1.getAddress();
1678 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001679 ((b1[1] & 0xFF) << 16) |
1680 ((b1[2] & 0xFF) << 8) |
1681 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001682
1683 int mask = ~((1 << (32 - prefix)) - 1);
1684
1685 if ((ipInt & mask) == (ipInt1 & mask)) {
1686 return true;
1687 }
1688 else {
1689 return false;
1690 }
1691 }
Sangho Shineb083032014-09-22 16:11:34 -07001692
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001693 /**
1694 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001695 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001696 * @param sw - Switch to add the rule
1697 * @param hostIpAddress Destination host IP address
1698 * @param hostMacAddress Destination host MAC address
1699 */
Sangho Shineb083032014-09-22 16:11:34 -07001700 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1701 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1702
1703 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001704
Sangho Shin463bee52014-09-29 15:14:43 -07001705 /**
1706 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001707 *
Sangho Shin463bee52014-09-29 15:14:43 -07001708 * @param ipv4
1709 */
1710 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001711 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001712 }
1713
1714 /**
1715 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001716 *
Sangho Shin463bee52014-09-29 15:14:43 -07001717 * @param destIp Destination address of packets to retrieve
1718 */
1719 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1720
1721 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1722
Sangho Shin61535402014-10-01 11:37:14 -07001723 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001724 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001725 int dest = ip.getDestinationAddress();
1726 IPv4Address ip1 = IPv4Address.of(dest);
1727 IPv4Address ip2 = IPv4Address.of(destIp);
1728 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001729 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001730 }
1731 }
1732 }
1733
1734 return bufferedPackets;
1735 }
1736
Sangho Shin15273b62014-10-16 22:22:05 -07001737
1738
Sangho Shin2f263692014-09-15 14:09:41 -07001739}