blob: 98427bbb9f428a18bf540e3a3dd63b27c06c8330 [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 Dasbc594a42014-09-25 20:13:50 -070075import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070076import org.projectfloodlight.openflow.types.IPv4Address;
77import org.slf4j.Logger;
78import org.slf4j.LoggerFactory;
79
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070080public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070081 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070082
83 private static final Logger log = LoggerFactory
84 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070085
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -070086 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070087 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070088 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070089 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070090
91 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070092 private ArpHandler arpHandler;
93 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070094 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070095 private IThreadPoolService threadPool;
96 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -070097 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -070098 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070099 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700100
Sangho Shinfbc572c2014-10-02 16:37:05 -0700101 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700102 private HashMap<String, LinkData> linksDown;
103 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700104 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shin15273b62014-10-16 22:22:05 -0700105 private HashMap<Integer, HashMap<String, PolicyRouteInfo>> stitchInfo;
106 private HashMap<Integer, HashMap<String, Integer>> tunnelGroupMap;
Sangho Shinbce900e2014-10-07 17:13:23 -0700107
108 private int numOfEvents = 0;
109 private int numOfEventProcess = 0;
110 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700111 private long matchActionId = 0L;
Sangho Shin23f898d2014-10-13 16:54:00 -0700112 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700113 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700114
Sangho Shin2f263692014-09-15 14:09:41 -0700115 @Override
116 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
117 // TODO Auto-generated method stub
118 return null;
119 }
120
121 @Override
122 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
123 // TODO Auto-generated method stub
124 return null;
125 }
126
127 @Override
128 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
129 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
130
131 l.add(IFloodlightProviderService.class);
132 l.add(IConfigInfoService.class);
133 l.add(ITopologyService.class);
134 l.add(IPacketService.class);
135 l.add(IFlowPusherService.class);
136 l.add(ITopologyService.class);
137
138 return l;
139
140 }
141
142 @Override
143 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700144 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700145 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700146 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700147 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700148 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700149 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700150 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700151 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700152 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700153 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700154 linksDown = new HashMap<String, LinkData>();
155 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700156 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700157 stitchInfo = new HashMap<Integer, HashMap<String, PolicyRouteInfo>>();
158 packetService = context.getServiceImpl(IPacketService.class);
159 tunnelGroupMap = new HashMap<Integer, HashMap<String, Integer>>();
Sangho Shin2f263692014-09-15 14:09:41 -0700160
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700161 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700162 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700163
Sangho Shin99918bd2014-10-08 15:52:35 -0700164
Sangho Shin2f263692014-09-15 14:09:41 -0700165 }
166
167 @Override
168 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700169 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700170
Sangho Shinc8d2f592014-09-30 16:53:57 -0700171 discoveryTask = new SingletonTask(ses, new Runnable() {
172 @Override
173 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700174 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700175 }
176 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700177
178 linkAddTask = new SingletonTask(ses, new Runnable() {
179 @Override
180 public void run() {
181 delayedAddLink();
182 }
183 });
184
Sangho Shin15273b62014-10-16 22:22:05 -0700185 testTask = new SingletonTask(ses, new Runnable() {
186 @Override
187 public void run() {
188 runTest();
189 }
190 });
191
192 // policy routing test task
193 //testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700194 }
195
Sangho Shin15273b62014-10-16 22:22:05 -0700196
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700197 @Override
198 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700199 if (payload.getEtherType() == Ethernet.TYPE_ARP)
200 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700201 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700202 addPacket((IPv4) payload.getPayload());
203 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
204 icmpHandler.processPacketIn(sw, inPort, payload);
205 else
206 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700207 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700208 else {
209 log.debug("{}", payload.toString());
210 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700211 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700212
Sangho Shin2f263692014-09-15 14:09:41 -0700213 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700214 * Update ARP Cache using ARP packets It is used to set destination MAC
215 * address to forward packets to known hosts. But, it will be replace with
216 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700217 *
Sangho Shin2f263692014-09-15 14:09:41 -0700218 * @param arp APR packets to use for updating ARP entries
219 */
220 public void updateArpCache(ARP arp) {
221
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700222 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
223 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700224 // TODO: Need to check the duplication
225 arpEntries.add(arpEntry);
226 }
227
228 /**
229 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700230 *
Sangho Shin2f263692014-09-15 14:09:41 -0700231 * @param destinationAddress IP address to get MAC address
232 * @return MAC Address to given IP address
233 */
234 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
235
236 // Can't we get the host IP address from the TopologyService ??
237
238 Iterator<ArpEntry> iterator = arpEntries.iterator();
239
240 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
241 byte[] ipAddressInByte = ipAddress.getBytes();
242
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700243 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700244 ArpEntry arpEntry = iterator.next();
245 byte[] address = arpEntry.targetIpAddress;
246
247 IPv4Address a = IPv4Address.of(address);
248 IPv4Address b = IPv4Address.of(ipAddressInByte);
249
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700250 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700251 log.debug("Found an arp entry");
252 return arpEntry.targetMacAddress;
253 }
254 }
255
256 return null;
257 }
258
Sangho Shineb083032014-09-22 16:11:34 -0700259 /**
260 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700261 *
Sangho Shineb083032014-09-22 16:11:34 -0700262 * @param destinationAddress
263 * @param sw
264 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700265 *
Sangho Shineb083032014-09-22 16:11:34 -0700266 */
267 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
268 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
269 }
Sangho Shin2f263692014-09-15 14:09:41 -0700270
271 /**
272 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700273 *
Sangho Shin2f263692014-09-15 14:09:41 -0700274 */
275 private class ArpEntry {
276
277 byte[] targetMacAddress;
278 byte[] targetIpAddress;
279
280 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
281 this.targetMacAddress = macAddress;
282 this.targetIpAddress = ipAddress;
283 }
Sangho Shin2f263692014-09-15 14:09:41 -0700284 }
Sangho Shineb083032014-09-22 16:11:34 -0700285
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700286 /**
287 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700288 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700289 * @param topologyEvents the generated Topology Events
290 * @see TopologyEvents
291 */
292 public void topologyEvents(TopologyEvents topologyEvents)
293 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700294 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700295 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700296 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700297
Sangho Shin23f898d2014-10-13 16:54:00 -0700298 /**
299 * Process the multiple topology events with some delay (100MS at most for now)
300 *
301 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700302 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700303 numOfEventProcess ++;
304
Sangho Shin51625342014-10-17 09:30:48 -0700305 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
306 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
307 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
308 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
309 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
310 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
311 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700312
Sangho Shin5be3e532014-10-03 17:20:58 -0700313 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700314 // We should handle the events in the order of when they happen
315 // TODO: We need to simulate the final results of multiple events
316 // and shoot only the final state.
317 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
318 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700319
Sangho Shin5be3e532014-10-03 17:20:58 -0700320 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700321
322 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
323 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
324 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
325 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
326 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
327 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
328 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
329
330 linkEntriesAddedAll.addAll(linkEntriesAdded);
331 portEntriesAddedAll.addAll(portEntriesAdded);
332 portEntriesRemovedAll.addAll(portEntriesRemoved);
333 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
334 switchAddedAll.addAll(switchAdded);
335 switchRemovedAll.addAll(switchRemoved);
336 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700337 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700338
339 if (!portEntriesRemoved.isEmpty()) {
340 processPortRemoval(portEntriesRemoved);
341 }
342
343 if (!linkEntriesRemoved.isEmpty()) {
344 processLinkRemoval(linkEntriesRemoved);
345 }
346
347 if (!switchRemoved.isEmpty()) {
348 processSwitchRemoved(switchRemoved);
349 }
350
351 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700352 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700353 }
354
355 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700356 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700357 }
358
359 if (!portEntriesAdded.isEmpty()) {
360 processPortAdd(portEntriesAdded);
361 }
362
363 if (!switchAdded.isEmpty()) {
364 processSwitchAdd(switchAdded);
365 }
Sangho Shin51625342014-10-17 09:30:48 -0700366
367 /*
Saurav Das82e62972014-10-16 14:53:57 -0700368 linkEntriesAdded.clear();
369 portEntriesAdded.clear();
370 portEntriesRemoved.clear();
371 linkEntriesRemoved.clear();
372 switchAdded.clear();
373 switchRemoved.clear();
374 mastershipRemoved.clear();
Sangho Shin51625342014-10-17 09:30:48 -0700375 */
Sangho Shinbce900e2014-10-07 17:13:23 -0700376 }
377
Sangho Shin23f898d2014-10-13 16:54:00 -0700378 // TODO: 100ms is enough to check both mastership removed events
379 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700380 if (!mastershipRemovedAll.isEmpty()) {
381 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700382 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700383 }
384 else {
385 HashMap<String, MastershipData> mastershipToRemove =
386 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700387 for (MastershipData ms: mastershipRemovedAll) {
388 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700389 // TODO: check ALL ports of the switch are dead ..
390 if (port.getDpid().equals(ms.getDpid())) {
391 mastershipToRemove.put(ms.getDpid().toString(), ms);
392 }
393 }
394 log.debug("Swtich {} is really down.", ms.getDpid());
395 }
396 processMastershipRemoved(mastershipToRemove.values());
397 }
398 }
399
Sangho Shinbce900e2014-10-07 17:13:23 -0700400 log.debug("num events {}, num of process {}, "
401 + "num of Population {}", numOfEvents, numOfEventProcess,
402 numOfPopulation);
403 }
404
405 /**
Sangho Shin23f898d2014-10-13 16:54:00 -0700406 * Add the link immediately
407 * The function is scheduled when link add event happens and called
408 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
409 */
410 private void delayedAddLink() {
411
412 processLinkAdd(linksToAdd.values(), true);
413
414 }
415
416 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700417 * Process the SwitchAdded events from topologyMananger.
418 * It does nothing. When a switch is added, then link will be added too.
419 * LinkAdded event will handle process all re-computation.
420 *
421 * @param switchAdded
422 */
423 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
424
425 }
426
427 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700428 * Remove all ports connected to the switch removed
429 *
430 * @param mastershipRemoved master switch info removed
431 */
432 private void processMastershipRemoved(Collection<MastershipData>
433 mastershipRemoved) {
434 for (MastershipData mastership: mastershipRemoved) {
435 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
436 for (Link link: sw.getOutgoingLinks()) {
437 Port dstPort = link.getDstPort();
438 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
439 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700440 if (dstSw != null) {
441 dstSw.removePortFromGroups(dstPort.getNumber());
442 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
443 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700444 }
Sangho Shin61535402014-10-01 11:37:14 -0700445 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700446
447 linksToAdd.clear();
448 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700449 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700450
Sangho Shinbce900e2014-10-07 17:13:23 -0700451 /**
452 * Remove all ports connected to the switch removed
453 *
454 * @param switchRemoved Switch removed
455 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700456 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700457 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700458 }
459
Sangho Shin61535402014-10-01 11:37:14 -0700460 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700461 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700462 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700463 * @param portEntries
464 */
465 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700466 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700467 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700468 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700469
Sangho Shinfbc572c2014-10-02 16:37:05 -0700470 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700471 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700472 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700473 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700474 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700475 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700476 }
477 }
478
479 /**
480 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700481 * If the link to add was removed before, then we just schedule the add link
482 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700483 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700484 * @param linkEntries
485 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700486 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700487
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700488 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700489
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700490 SwitchPort srcPort = link.getSrc();
491 SwitchPort dstPort = link.getDst();
492
Sangho Shin23f898d2014-10-13 16:54:00 -0700493 String key = srcPort.getDpid().toString() +
494 dstPort.getDpid().toString();
495 if (!delayed) {
496 if (linksDown.containsKey(key)) {
497 linksToAdd.put(key, link);
498 linksDown.remove(key);
499 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
500 log.debug("Add link {} with 5 sec delay", link);
501 // TODO: What if we have multiple events of add link:
502 // one is new link add, the other one is link up for
503 // broken link? ECMPSPG function cannot deal with it for now
504 return;
505 }
506 }
507 else {
508 if (linksDown.containsKey(key)) {
509 linksToAdd.remove(key);
510 log.debug("Do not add the link {}: it is down again!", link);
511 return;
512 }
513 }
514
Sangho Shinfbc572c2014-10-02 16:37:05 -0700515 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700516 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700517 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700518 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700519
Sangho Shin815af0c2014-10-10 13:05:45 -0700520 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700521 continue;
522
523 srcSw.addPortToGroups(srcPort.getPortNumber());
524 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700525
Sangho Shin15273b62014-10-16 22:22:05 -0700526 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
527 // link);
528 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
529 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700530
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700531 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700532 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700533 }
534
535 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700536 * Check if all links are gone b/w the two switches. If all links are gone,
537 * then we need to recalculate the path. Otherwise, just report link failure
538 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700539 *
Sangho Shin61535402014-10-01 11:37:14 -0700540 * @param linkEntries
541 */
542 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700543 boolean recomputationRequired = false;
544
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700545 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700546 SwitchPort srcPort = link.getSrc();
547 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700548
Sangho Shinfbc572c2014-10-02 16:37:05 -0700549 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700550 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700551 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700552 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700553 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700554 /* If this link is not between two switches, ignore it */
555 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700556
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700557 srcSw.removePortFromGroups(srcPort.getPortNumber());
558 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700559 log.debug("Remove port {} from switch {}", srcPort, srcSw);
560 log.debug("Remove port {} from switch {}", dstPort, dstSw);
561
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700562 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
563 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700564 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700565 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700566 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700567 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700568 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700569 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700570
571 String key = link.getSrc().getDpid().toString()+
572 link.getDst().getDpid().toString();
573 if (!linksDown.containsKey(key)) {
574 linksDown.put(key, link);
575 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700576 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700577
578 if (recomputationRequired)
579 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700580 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700581
Sangho Shin61535402014-10-01 11:37:14 -0700582 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700583 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700584 *
Sangho Shin61535402014-10-01 11:37:14 -0700585 * @param portEntries
586 */
587 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700588 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700589 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700590
Sangho Shinfbc572c2014-10-02 16:37:05 -0700591 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700592 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700593 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700594 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700595 log.debug("Remove port {} from switch {}", port, dpid);
596 }
Sangho Shin61535402014-10-01 11:37:14 -0700597 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700598 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700599
600 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700601 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700602 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700603 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700604 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700605 private void populateEcmpRoutingRules(boolean modified) {
606 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700607 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700608 for (Switch sw : switches) {
609 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700610 graphs.put(sw, ecmpSPG);
611 //log.debug("ECMPShortestPathGraph is computed for switch {}",
612 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700613 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700614 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700615 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700616 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700617
Sangho Shin99918bd2014-10-08 15:52:35 -0700618 /**
619 * populate routing rules to forward packets from the switch given to
620 * all other switches.
621 *
622 * @param sw source switch
623 * @param ecmpSPG shortest path from the the source switch to all others
624 * @param modified modification flag
625 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700626 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700627 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700628
Sangho Shinfbc572c2014-10-02 16:37:05 -0700629 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
630 ecmpSPG.getAllLearnedSwitchesAndVia();
631 for (Integer itrIdx : switchVia.keySet()) {
632 //log.debug("ECMPShortestPathGraph:Switches learned in "
633 // + "Iteration{} from switch {}:",
634 // itrIdx,
635 // HexString.toHexString(sw.getDpid().value()));
636 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
637 switchVia.get(itrIdx);
638 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700639 //log.debug("ECMPShortestPathGraph:****switch {} via:",
640 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700641 String destSw = sw.getDpid().toString();
642 List<String> fwdToSw = new ArrayList<String>();
643
Sangho Shinfbc572c2014-10-02 16:37:05 -0700644 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700645 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700646 if (via.isEmpty()) {
647 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700648 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700649 else {
650 fwdToSw.add(via.get(0).toString());
651 }
Sangho Shin43cee112014-09-25 16:43:34 -0700652 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700653 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700654 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700655
656 // Send Barrier Message and make sure all rules are set
657 // before we set the rules to next routers
658 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
659 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700660 if (sw13 != null) {
661 try {
662 OFBarrierReplyFuture replyFuture = sw13.sendBarrier();
663 replyFuture.get(10, TimeUnit.SECONDS);
664 } catch (IOException e) {
665 e.printStackTrace();
666 } catch (InterruptedException | ExecutionException | TimeoutException e) {
667 log.error("Barrier message not received for sw: {}", sw.getDpid());
668 e.printStackTrace();
669 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700670 }
671 }
672
673 }
674
675
Sangho Shin99918bd2014-10-08 15:52:35 -0700676 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700677 * This class is used only for link recovery optimization in
678 * modifyEcmpRoutingRules() function.
Sangho Shin99918bd2014-10-08 15:52:35 -0700679 * TODO: please remove if the optimization is not used at all
Sangho Shinbce900e2014-10-07 17:13:23 -0700680 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700681 private class SwitchPair {
682 private Switch src;
683 private Switch dst;
684
685 public SwitchPair(Switch src, Switch dst) {
686 this.src = src;
687 this.dst = dst;
688 }
689
690 public Switch getSource() {
691 return src;
692 }
693
694 public Switch getDestination() {
695 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700696 }
Sangho Shin43cee112014-09-25 16:43:34 -0700697 }
698
699 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700700 * Modify the routing rules for the lost links
701 * - Recompute the path if the link failed is included in the path
702 * (including src and dest).
703 *
704 * @param newLink
705 */
706 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
707
708 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700709 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700710
711 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
712 Switch rootSw = ecmpSPG.getRootSwitch();
713 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
714 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
715 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
716 for (Switch destSw: p.keySet()) {
717 ArrayList<Path> path = p.get(destSw);
718 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700719 boolean found = false;
720 for (SwitchPair pair: linksToRecompute) {
721 if (pair.getSource().getDpid() == rootSw.getDpid() &&
722 pair.getSource().getDpid() == destSw.getDpid()) {
723 found = true;
724 }
725 }
726 if (!found) {
727 linksToRecompute.add(new SwitchPair(rootSw, destSw));
728 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700729 }
730 }
731 }
732 }
733
734 // Recompute the path for the specific route
735 for (SwitchPair pair: linksToRecompute) {
736
737 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
Sangho Shin99918bd2014-10-08 15:52:35 -0700738 // We need the following function for optimization
Sangho Shinfbc572c2014-10-02 16:37:05 -0700739 //ECMPShortestPathGraph ecmpSPG =
740 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
741 ECMPShortestPathGraph ecmpSPG =
742 new ECMPShortestPathGraph(pair.getSource());
Sangho Shin5be3e532014-10-03 17:20:58 -0700743 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700744 }
745 }
746
747 /**
748 * Check if the path is affected from the link removed
749 *
750 * @param path Path to check
751 * @param linkRemoved link removed
752 * @return true if the path contains the link removed
753 */
754 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
755
756 for (Path ppp: path) {
757 // TODO: need to check if this is a bidirectional or
758 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700759 for (LinkData link: ppp) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700760 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
761 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
762 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700763 }
764 }
765
766 return false;
767 }
768
769 /**
770 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700771 * Set routing rules in targetSw {forward packets to fwdToSw switches in
772 * order to send packets to destSw} - If the target switch is an edge router
773 * and final destnation switch is also an edge router, then set IP
774 * forwarding rules to subnets - If only the target switch is an edge
775 * router, then set IP forwarding rule to the transit router loopback IP
776 * address - If the target is a transit router, then just set the MPLS
777 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700778 *
Sangho Shin43cee112014-09-25 16:43:34 -0700779 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700780 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700781 * @param fwdToSw next hop switches
782 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700783 private void setRoutingRule(Switch targetSw, String destSw,
784 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700785
Sangho Shin43cee112014-09-25 16:43:34 -0700786 if (fwdToSw.isEmpty()) {
787 fwdToSw.add(destSw);
788 }
789
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700790 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700791 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
792 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700793 // We assume that there is at least one transit router b/w edge
794 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700795 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
796 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700797 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700798 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700799
Sangho Shin43cee112014-09-25 16:43:34 -0700800 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700801 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
802 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700803 // Edge router can be a transit router
804 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700805 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700806 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700807 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700808 // We assume that there is at least one transit router b/w edge
809 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700810 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
811 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700812 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
813 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700814 // Edge router can be a transit router
815 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700816 }
817 // if it is a transit router, then set rules in the MPLS table
818 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700819 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700820 }
821
822 }
823
Sangho Shinfbc572c2014-10-02 16:37:05 -0700824 /**
825 * Set IP forwarding rule to the gateway of each subnet of switches
826 *
827 * @param targetSw Switch to set rules
828 * @param subnets subnet information
829 * @param mplsLabel destination MPLS label
830 * @param fwdToSw router to forward packets to
831 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700832 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700833 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700834
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700835 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700836 new ArrayList<MatchActionOperationEntry>();
837
838 try {
839 JSONArray arry = new JSONArray(subnets);
840 for (int i = 0; i < arry.length(); i++) {
841 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700842 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
843 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700844 }
845 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700846 e.printStackTrace();
847 }
848
849 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700850 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700851 getSwId(targetSw.getDpid().toString()));
852
Sangho Shin721ca042014-10-09 13:03:40 -0700853 if (sw13 != null) {
854 try {
855 sw13.pushFlows(entries);
856 } catch (IOException e) {
857 e.printStackTrace();
858 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700859 }
860 }
861
862 }
863
Sangho Shin43cee112014-09-25 16:43:34 -0700864 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700865 * Check if the switch is the edge router or not.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700866 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700867 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700868 * @return true if it is an edge router, otherwise false
869 */
870 private boolean IsEdgeRouter(String dpid) {
871
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700872 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700873 String dpidStr = sw.getDpid().toString();
874 if (dpid.equals(dpidStr)) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700875 /*
Sangho Shin43cee112014-09-25 16:43:34 -0700876 String subnetInfo = sw.getStringAttribute("subnets");
877 if (subnetInfo == null || subnetInfo.equals("[]")) {
878 return false;
879 }
880 else
881 return true;
Sangho Shinbce900e2014-10-07 17:13:23 -0700882 */
883 String isEdge = sw.getStringAttribute("isEdgeRouter");
884 if (isEdge != null) {
885 if (isEdge.equals("true"))
886 return true;
887 else
888 return false;
889 }
Sangho Shin43cee112014-09-25 16:43:34 -0700890 }
891 }
892
893 return false;
894 }
895
896 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700897 * Set IP forwarding rule - If the destination is the next hop, then do not
898 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
899 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700900 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700901 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700902 * @param subnetIp Match IP address
903 * @param mplsLabel MPLS label of final destination router
904 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700905 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700906 */
907 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700908 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
909 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700910
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700911 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700912 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700913 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700914
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700915 // If destination SW is the same as the fwd SW, then do not push MPLS
916 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700917 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700918 PushMplsAction pushMplsAction = new PushMplsAction();
919 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
920 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700921 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700922
Sangho Shin62ce5c12014-10-08 16:24:40 -0700923 //actions.add(pushMplsAction);
924 //actions.add(copyTtlOutAction);
925 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700926 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700927 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700928 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700929 else {
930 String fwdToSw = fwdToSws.get(0);
931 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
932 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
933 actions.add(decTtlAction);
934 }
935 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700936 SetMplsIdAction setIdAction = new SetMplsIdAction(
937 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700938 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700939 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700940
Sangho Shin62ce5c12014-10-08 16:24:40 -0700941 //actions.add(pushMplsAction);
942 //actions.add(copyTtlOutAction);
943 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700944 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700945 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700946 }
947 }
Sangho Shin43cee112014-09-25 16:43:34 -0700948
Sangho Shin43cee112014-09-25 16:43:34 -0700949 for (String fwdSw : fwdToSws) {
950 groupAction.addSwitch(new Dpid(fwdSw));
951 }
952 actions.add(groupAction);
953
Sangho Shin99918bd2014-10-08 15:52:35 -0700954 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700955 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700956
Sangho Shin5be3e532014-10-03 17:20:58 -0700957 Operator operator = null;
958 if (modified)
959 operator = Operator.MODIFY;
960 else
961 operator = Operator.ADD;
962
Sangho Shin43cee112014-09-25 16:43:34 -0700963 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700964 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700965
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700966 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700967 getSwId(sw.getDpid().toString()));
968
Sangho Shin5be3e532014-10-03 17:20:58 -0700969 if (sw13 != null) {
970 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700971 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700972 if (entries != null)
973 entries.add(maEntry);
974 else
975 sw13.pushFlow(maEntry);
976 } catch (IOException e) {
977 e.printStackTrace();
978 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700979 }
980
Sangho Shin43cee112014-09-25 16:43:34 -0700981 }
982
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700983 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700984 * Set MPLS forwarding rules to MPLS table
985 * </p>
986 * If the destination is the same as the next hop to forward packets then,
987 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
988 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
989 * TTL of the another MPLS header.
990 * If the next hop is not the destination, just forward packets to next
991 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700992 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700993 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700994 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700995 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700996 * */
Sangho Shin5be3e532014-10-03 17:20:58 -0700997 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
998 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -0700999
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001000 if (fwdSws.isEmpty())
1001 return;
Sangho Shin43cee112014-09-25 16:43:34 -07001002
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001003 Collection<MatchActionOperationEntry> maEntries =
1004 new ArrayList<MatchActionOperationEntry>();
1005 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -07001006
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001007 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
1008 // One rule for Bos = 1
1009 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
1010 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001011
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001012 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
1013 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
1014 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
1015
1016 actions.add(copyTtlInAction);
1017 actions.add(popAction);
1018 actions.add(decNwTtlAction);
1019
1020 GroupAction groupAction = new GroupAction();
1021 groupAction.addSwitch(new Dpid(fwdSw1));
1022 actions.add(groupAction);
1023
1024 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
1025 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1026 Operator operator = Operator.ADD;
1027 MatchActionOperationEntry maEntry =
1028 new MatchActionOperationEntry(operator, matchAction);
1029 maEntries.add(maEntry);
1030
1031 // One rule for Bos = 0
Sangho Shin23f898d2014-10-13 16:54:00 -07001032 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001033 List<Action> actionsBos = new ArrayList<Action>();
Sangho Shin15273b62014-10-16 22:22:05 -07001034 PopMplsAction popActionBos = new PopMplsAction(EthType.MPLS_UNICAST);
1035 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1036
1037 actionsBos.add(copyTtlInAction);
1038 actionsBos.add(popActionBos);
1039 actionsBos.add(decMplsTtlAction);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001040 actionsBos.add(groupAction);
1041
1042 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
1043 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
1044 MatchActionOperationEntry maEntryBos =
1045 new MatchActionOperationEntry(operator, matchActionBos);
1046 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001047 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001048 else {
1049 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
1050 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -07001051
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001052 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1053 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -07001054
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001055 GroupAction groupAction = new GroupAction();
1056 for (String fwdSw : fwdSws)
1057 groupAction.addSwitch(new Dpid(fwdSw));
1058 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -07001059
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001060 MatchAction matchAction = new MatchAction(new MatchActionId(
1061 matchActionId++),
1062 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1063 Operator operator = Operator.ADD;
1064 MatchActionOperationEntry maEntry =
1065 new MatchActionOperationEntry(operator, matchAction);
1066 maEntries.add(maEntry);
Sangho Shine2e9bcd2014-10-13 15:14:18 -07001067
1068 // BoS = 1
1069 MplsMatch mplsMatchBoS = new MplsMatch(Integer.parseInt(mplsLabel), true);
1070 List<Action> actionsBoS = new ArrayList<Action>();
1071
1072 DecMplsTtlAction decMplsTtlActionBoS = new DecMplsTtlAction(1);
1073 actionsBoS.add(decMplsTtlActionBoS);
1074
1075 GroupAction groupActionBoS = new GroupAction();
1076 for (String fwdSw : fwdSws)
1077 groupActionBoS.addSwitch(new Dpid(fwdSw));
1078 actionsBoS.add(groupActionBoS);
1079
1080 MatchAction matchActionBos = new MatchAction(new MatchActionId(
1081 matchActionId++),
1082 new SwitchPort((long) 0, (short) 0), mplsMatchBoS, actionsBoS);
1083 MatchActionOperationEntry maEntryBoS =
1084 new MatchActionOperationEntry(operator, matchActionBos);
1085 maEntries.add(maEntryBoS);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001086 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001087 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001088 getSwId(sw.getDpid().toString()));
1089
Sangho Shin5be3e532014-10-03 17:20:58 -07001090 if (sw13 != null) {
1091 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001092 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001093 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001094 } catch (IOException e) {
1095 e.printStackTrace();
1096 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001097 }
Sangho Shin43cee112014-09-25 16:43:34 -07001098 }
1099
Sangho Shin15273b62014-10-16 22:22:05 -07001100 /**
1101 * Create a tunnel for policy routing
1102 * It delivers the node IDs of tunnels to driver.
1103 * Split the node IDs if number of IDs exceeds the limit for stitching.
1104 *
1105 * @param tunnelId Node IDs for the tunnel
1106 * @param Ids tunnel ID
1107 */
1108 public boolean createTunnel(int tunnelId, List<String> Ids) {
1109
1110 if (tunnelId < 0) {
1111 log.debug("Tunnel ID should be posivtive integer.");
1112 return false;
1113 }
1114
1115 if (Ids.isEmpty() || Ids.size() < 2) {
1116 log.debug("Wrong tunnel information");
1117 return false;
1118 }
1119
1120 HashMap<String, PolicyRouteInfo> stitchingRule = getStitchingRule(Ids);
1121 stitchInfo.put(Integer.valueOf(tunnelId), stitchingRule);
1122 if (stitchingRule == null) {
1123 log.debug("Failed to get the policy rule.");
1124 return false;
1125 }
1126 HashMap<String, Integer> switchGroupPair = new HashMap<String, Integer>();
1127 for (String targetDpid: stitchingRule.keySet()) {
1128 PolicyRouteInfo route = stitchingRule.get(targetDpid);
1129
1130 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
1131 getSwId(targetDpid.toString()));
1132
1133 if (targetSw == null) {
1134 log.debug("Switch {} is gone.", targetDpid);
1135 return false;
1136 }
1137
1138 NeighborSet ns = new NeighborSet();
1139 for (Dpid dpid: route.getFwdSwDpid())
1140 ns.addDpid(dpid);
1141
1142 printTunnelInfo(targetSw, tunnelId, route.getRoute(), ns);
1143 int groupId = targetSw.createTunnel(tunnelId, route.getRoute(), ns);
1144 switchGroupPair.put(targetDpid.toString(), groupId);
1145
1146 }
1147
1148 tunnelGroupMap.put(Integer.valueOf(tunnelId), switchGroupPair);
1149
1150 return true;
1151 }
1152
1153 /**
1154 * Set policy table for policy routing
1155 *
1156 * @param sw
1157 * @param mplsLabel
1158 */
Sangho Shin51625342014-10-17 09:30:48 -07001159 public void setPolicyTable(MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001160 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
1161 Short srcTcpPort, Short dstTcpPort, int tid) {
1162
1163 HashMap<String, PolicyRouteInfo> routeInfo = stitchInfo.get(Integer.valueOf(tid));
1164 HashMap<String, Integer> switchGroupPair = tunnelGroupMap.get(Integer.valueOf(tid));
1165 for (String srcDpid: routeInfo.keySet()) {
1166
1167 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1168
1169 if (srcMac != null)
1170 packetBuilder.setSrcMac(srcMac);
1171 if (dstMac != null)
1172 packetBuilder.setDstMac(dstMac);
1173 if (etherType != null) {
1174 packetBuilder.setEtherType(etherType);
1175 }
1176 if (srcIp != null) {
1177 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1178 }
1179 if (dstIp != null) {
1180 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1181 }
1182 if (ipProto != null) {
1183 packetBuilder.setIpProto(ipProto);
1184 }
1185 if (srcTcpPort > 0) {
1186 packetBuilder.setSrcTcpPort(srcTcpPort);
1187 }
1188 if (dstTcpPort > 0) {
1189 packetBuilder.setDstTcpPort(dstTcpPort);
1190 }
1191 PacketMatch policyMatch = packetBuilder.build();
1192
1193 List<Action> actions = new ArrayList<>();
1194 GroupAction groupAction = new GroupAction();
1195 int gropuId = switchGroupPair.get(srcDpid);
1196 groupAction.setGroupId(gropuId);
1197 actions.add(groupAction);
1198
1199 MatchAction matchAction = new MatchAction(new MatchActionId(
1200 matchActionId++),
1201 new SwitchPort((long) 0, (short) 0), policyMatch, actions);
1202 MatchActionOperationEntry maEntry =
1203 new MatchActionOperationEntry(Operator.ADD, matchAction);
1204
1205 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1206 getSwId(srcDpid));
1207
1208 if (sw13 != null) {
1209 printMatchActionOperationEntry(sw13, maEntry);
1210 try {
1211 sw13.pushFlow(maEntry);
1212 } catch (IOException e) {
1213 e.printStackTrace();
1214 }
1215 }
1216 }
1217 }
1218
1219 /**
1220 * Get the forwarding Switch DPIDs to send packets to a node
1221 *
1222 * @param srcSw source switch
1223 * @param nodeId destination node Id
1224 * @return list of switch DPID to forward packets to
1225 */
1226
1227 private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
1228
1229 List<Dpid> fwdSws = new ArrayList<Dpid>();
1230 Switch destSw = null;
1231
1232 destSw = getSwitchFromNodeId(nodeId);
1233
1234 if (destSw == null) {
1235 log.debug("Cannot find the switch with ID {}", nodeId);
1236 return null;
1237 }
1238
1239 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1240
1241 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1242 ecmpSPG.getAllLearnedSwitchesAndVia();
1243 for (Integer itrIdx : switchVia.keySet()) {
1244 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1245 switchVia.get(itrIdx);
1246 for (Switch targetSw : swViaMap.keySet()) {
1247 String destSwDpid = destSw.getDpid().toString();
1248 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1249 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1250 if (via.isEmpty()) {
1251 fwdSws.add(destSw.getDpid());
1252 }
1253 else {
1254 fwdSws.add(via.get(0));
1255 }
1256 }
1257 }
1258 }
1259 }
1260
1261 return fwdSws;
1262 }
1263
1264 /**
1265 * Get switch for the node Id specified
1266 *
1267 * @param nodeId node ID for switch
1268 * @return Switch
1269 */
1270 private Switch getSwitchFromNodeId(String nodeId) {
1271
1272 for (Switch sw : mutableTopology.getSwitches()) {
1273 String id = sw.getStringAttribute("nodeSid");
1274 if (id.equals(nodeId)) {
1275 return sw;
1276 }
1277 }
1278
1279 return null;
1280 }
1281
1282 /**
1283 * Convert a string DPID to its Switch Id (integer)
1284 *
1285 * @param dpid
1286 * @return
1287 */
1288 private long getSwId(String dpid) {
1289
1290 long swId = 0;
1291
1292 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1293 if (swIdHexStr != null)
1294 swId = Integer.decode(swIdHexStr);
1295
1296 return swId;
1297 }
1298
1299 private void runTest() {
1300
1301 String[] routeArray = {"101", "102", "103", "104", "105", "108", "110"};
1302 List<String> routeList = new ArrayList<String>();
1303 for (int i = 0; i < routeArray.length; i++)
1304 routeList.add(routeArray[i]);
1305
1306 if (createTunnel(1, routeList)) {
1307 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1308 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1309
1310 this.setPolicyTable(null, null, Ethernet.TYPE_IPV4, srcIp, dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 1);
1311 }
1312 else {
1313 testTask.reschedule(5, TimeUnit.SECONDS);
1314 }
1315 }
1316
1317 private void runTest1() {
1318
1319 String dpid1 = "00:00:00:00:00:00:00:01";
1320 String dpid2 = "00:00:00:00:00:00:00:0a";
1321 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1322 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1323
1324 if (srcSw == null || dstSw == null) {
1325 testTask.reschedule(1, TimeUnit.SECONDS);
1326 log.debug("Switch is gone. Reschedule the test");
1327 return;
1328 }
1329
1330 String[] routeArray = {"101", "102", "105", "108", "110"};
1331 List<String> routeList = new ArrayList<String>();
1332 for (int i = 0; i < routeArray.length; i++)
1333 routeList.add(routeArray[i]);
1334
1335 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1336
1337 log.debug("Test set is {}", routeList.toString());
1338 log.debug("Result set is {}", optimizedRoute.toString());
1339
1340
1341 }
1342
1343 /**
1344 * Optimize the mpls label
1345 * The feature will be used only for policy of "avoid a specific switch".
1346 * Check route to each router in route backward.
1347 * If there is only one route to the router and the routers are included in
1348 * the route, remove the id from the path.
1349 * A-B-C-D-E => A-B-C-D-E -> A-E
1350 * | | => A-B-H-I -> A-I
1351 * F-G-H-I => A-D-I -> A-D-I
1352 */
1353 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
1354
1355 List<String> optimizedPath = new ArrayList<String>();
1356 optimizedPath.addAll(route);
1357 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1358
1359 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
1360 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
1361 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
1362 for (Switch s: p.keySet()) {
1363 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
1364 ArrayList<Path> ecmpPaths = p.get(s);
1365 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
1366 for (Path path: ecmpPaths) {
1367 for (LinkData link: path) {
1368 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
1369 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
1370 if (optimizedPath.contains(srcId)) {
1371 optimizedPath.remove(srcId);
1372 }
1373 if (optimizedPath.contains(dstId)) {
1374 optimizedPath.remove(dstId);
1375 }
1376 }
1377 }
1378 }
1379 }
1380 }
1381 }
1382
1383 return optimizedPath;
1384
1385 }
1386
1387
1388 class PolicyRouteInfo {
1389
1390 String srcSwDpid;
1391 List<Dpid> fwdSwDpids;
1392 List<String> route;
1393
1394 PolicyRouteInfo() {
1395 fwdSwDpids = new ArrayList<Dpid>();
1396 route = new ArrayList<String>();
1397 }
1398
1399 void setSrcDpid(String dpid) {
1400 this.srcSwDpid = dpid;
1401 }
1402
1403 void setFwdSwDpid(List<Dpid> dpid) {
1404 this.fwdSwDpids = dpid;
1405 }
1406
1407 void addRoute(String id) {
1408 route.add(id);
1409 }
1410
1411 void setRoute(List<String> r) {
1412 this.route = r;
1413 }
1414
1415 String getSrcSwDpid() {
1416 return this.srcSwDpid;
1417 }
1418
1419 List<Dpid> getFwdSwDpid() {
1420 return this.fwdSwDpids;
1421 }
1422
1423 List<String> getRoute() {
1424 return this.route;
1425 }
1426 }
1427
1428
1429 /**
1430 *
1431 *
1432 * @param srcSw
1433 * @param dstSw
1434 * @param route
1435 * @return
1436 */
1437 private HashMap<String, PolicyRouteInfo> getStitchingRule(List<String> route) {
1438
1439 if (route.isEmpty() || route.size() < 2)
1440 return null;
1441
1442 HashMap<String, PolicyRouteInfo> rules = new HashMap<String, PolicyRouteInfo>();
1443
1444 Switch srcSw = this.getSwitchFromNodeId(route.get(0));
1445 String srcDpid = srcSw.getDpid().toString();
1446
1447 if (route.size() <= MAX_NUM_LABELS+1) {
1448 PolicyRouteInfo info = new PolicyRouteInfo();
1449 info.setSrcDpid(srcSw.getDpid().toString());
1450 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, route.get(1));
1451 info.setFwdSwDpid(fwdSwDpids);
1452 route.remove(0);
1453 info.setRoute(route);
1454 rules.put(srcDpid, info);
1455 return rules;
1456 }
1457
1458 int i = 0;
1459 PolicyRouteInfo routeInfo = new PolicyRouteInfo();
1460 String prevNodeId = null;
1461 boolean checkNeighbor = true;
1462
1463 for (String nodeId: route) {
1464 if (i == 0) {
1465 routeInfo.setSrcDpid(srcDpid);
1466 srcSw = getSwitchFromNodeId(nodeId);
1467 i++;
1468 }
1469 else if (i == 1) {
1470 if (checkNeighbor) {
1471 // Check if next node is the neighbor SW of the source SW
1472 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
1473 if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
1474 log.debug("There is no route from node {} to node {}", srcSw.getDpid(), nodeId);
1475 return null;
1476 }
1477 // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
1478 boolean match = false;
1479 for (Dpid dpid: fwdSwDpids) {
1480 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1481 List<Dpid> fwdSws = new ArrayList<Dpid>();
1482 fwdSws.add(dpid);
1483 routeInfo.setFwdSwDpid(fwdSws);
1484 match = true;
1485 break;
1486 }
1487 }
1488 if (!match) {
1489 routeInfo.addRoute(nodeId);
1490 routeInfo.setFwdSwDpid(fwdSwDpids);
1491 i++;
1492 }
1493
1494 checkNeighbor = false;
1495 }
1496 else {
1497 routeInfo.addRoute(nodeId);
1498 i++;
1499 }
1500 }
1501 else {
1502 routeInfo.addRoute(nodeId);
1503 i++;
1504 }
1505
1506 if (i == MAX_NUM_LABELS+1) {
1507 rules.put(srcDpid, routeInfo);
1508 routeInfo = new PolicyRouteInfo();
1509 srcSw = getSwitchFromNodeId(nodeId);
1510 srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
1511 routeInfo.setSrcDpid(srcDpid);
1512 i = 1;
1513 checkNeighbor = true;
1514 }
1515 }
1516
1517 if (i < MAX_NUM_LABELS+1) {
1518 rules.put(srcDpid, routeInfo);
1519 }
1520
1521 return rules;
1522 }
1523
1524 /**
1525 * print tunnel info - used only for debugging.
1526 * @param targetSw
1527 *
1528 * @param fwdSwDpids
1529 * @param ids
1530 * @param tunnelId
1531 */
1532 private void printTunnelInfo(IOF13Switch targetSw, int tunnelId,
1533 List<String> ids, NeighborSet ns) {
1534 StringBuilder logStr = new StringBuilder("In switch " +
1535 targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
1536 for (String id: ids)
1537 logStr.append(id + "-");
1538 logStr.append(" output to ");
1539 for (Dpid dpid: ns.getDpids())
1540 logStr.append(dpid + " - ");
1541
1542 log.debug(logStr.toString());
1543
1544 }
1545
1546
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001547
Sangho Shin43cee112014-09-25 16:43:34 -07001548 /**
1549 * Debugging function to print out the Match Action Entry
Sangho Shin15273b62014-10-16 22:22:05 -07001550 * @param sw13
Sangho Shinfbc572c2014-10-02 16:37:05 -07001551 *
Sangho Shin43cee112014-09-25 16:43:34 -07001552 * @param maEntry
1553 */
Sangho Shin15273b62014-10-16 22:22:05 -07001554 private void printMatchActionOperationEntry(
1555 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -07001556
Sangho Shin15273b62014-10-16 22:22:05 -07001557 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001558
1559 MatchAction ma = maEntry.getTarget();
1560 Match m = ma.getMatch();
1561 List<Action> actions = ma.getActions();
1562
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001563 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -07001564 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001565 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -07001566 logStr.append(ip.toString());
1567 logStr.append(" then ");
1568 }
1569 else if (m instanceof MplsMatch) {
1570 logStr.append("If the MPLS label matches with ");
1571 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1572 logStr.append(mplsLabel);
1573 logStr.append(" then ");
1574 }
Sangho Shin15273b62014-10-16 22:22:05 -07001575 else if (m instanceof PacketMatch) {
1576 GroupAction ga = (GroupAction)actions.get(0);
1577 logStr.append("if the policy match is XXX then go to group " +
1578 ga.getGroupId());
1579 log.debug(logStr.toString());
1580 return;
1581 }
Sangho Shin43cee112014-09-25 16:43:34 -07001582
1583 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001584 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -07001585 if (action instanceof CopyTtlInAction) {
1586 logStr.append("copy ttl In, ");
1587 }
1588 else if (action instanceof CopyTtlOutAction) {
1589 logStr.append("copy ttl Out, ");
1590 }
1591 else if (action instanceof DecMplsTtlAction) {
1592 logStr.append("Dec MPLS TTL , ");
1593 }
1594 else if (action instanceof GroupAction) {
1595 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001596 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -07001597 logStr.append(dpids.toString() + ",");
1598
Sangho Shin43cee112014-09-25 16:43:34 -07001599 }
1600 else if (action instanceof PopMplsAction) {
1601 logStr.append("Pop MPLS label, ");
1602 }
1603 else if (action instanceof PushMplsAction) {
1604 logStr.append("Push MPLS label, ");
1605 }
1606 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001607 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -07001608 logStr.append("Set MPLS ID as " + id + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001609 }
1610 }
1611
1612 log.debug(logStr.toString());
1613
Sangho Shineb083032014-09-22 16:11:34 -07001614 }
1615
1616 /**
1617 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001618 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001619 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001620 * @return MPLS label for the switch
1621 */
1622
Sangho Shin43cee112014-09-25 16:43:34 -07001623 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001624
1625 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001626 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001627 String dpidStr = sw.getDpid().toString();
1628 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001629 mplsLabel = sw.getStringAttribute("nodeSid");
1630 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001631 }
1632 }
1633
Sangho Shineb083032014-09-22 16:11:34 -07001634 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001635 }
1636
Sangho Shineb083032014-09-22 16:11:34 -07001637 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001638 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001639 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001640 * @param addr - subnet address to match
1641 * @param addr1 - IP address to check
1642 * @return true if the IP address matches to the subnet, otherwise false
1643 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001644 public boolean netMatch(String addr, String addr1) { // addr is subnet
1645 // address and addr1 is
1646 // ip address. Function
1647 // will return true, if
1648 // addr1 is within
1649 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001650
1651 String[] parts = addr.split("/");
1652 String ip = parts[0];
1653 int prefix;
1654
1655 if (parts.length < 2) {
1656 prefix = 0;
1657 } else {
1658 prefix = Integer.parseInt(parts[1]);
1659 }
1660
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001661 Inet4Address a = null;
1662 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001663 try {
1664 a = (Inet4Address) InetAddress.getByName(ip);
1665 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001666 } catch (UnknownHostException e) {
1667 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001668
1669 byte[] b = a.getAddress();
1670 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001671 ((b[1] & 0xFF) << 16) |
1672 ((b[2] & 0xFF) << 8) |
1673 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001674
1675 byte[] b1 = a1.getAddress();
1676 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001677 ((b1[1] & 0xFF) << 16) |
1678 ((b1[2] & 0xFF) << 8) |
1679 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001680
1681 int mask = ~((1 << (32 - prefix)) - 1);
1682
1683 if ((ipInt & mask) == (ipInt1 & mask)) {
1684 return true;
1685 }
1686 else {
1687 return false;
1688 }
1689 }
Sangho Shineb083032014-09-22 16:11:34 -07001690
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001691 /**
1692 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001693 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001694 * @param sw - Switch to add the rule
1695 * @param hostIpAddress Destination host IP address
1696 * @param hostMacAddress Destination host MAC address
1697 */
Sangho Shineb083032014-09-22 16:11:34 -07001698 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1699 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1700
1701 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001702
Sangho Shin463bee52014-09-29 15:14:43 -07001703 /**
1704 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001705 *
Sangho Shin463bee52014-09-29 15:14:43 -07001706 * @param ipv4
1707 */
1708 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001709 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001710 }
1711
1712 /**
1713 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001714 *
Sangho Shin463bee52014-09-29 15:14:43 -07001715 * @param destIp Destination address of packets to retrieve
1716 */
1717 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1718
1719 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1720
Sangho Shin61535402014-10-01 11:37:14 -07001721 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001722 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001723 int dest = ip.getDestinationAddress();
1724 IPv4Address ip1 = IPv4Address.of(dest);
1725 IPv4Address ip2 = IPv4Address.of(destIp);
1726 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001727 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001728 }
1729 }
1730 }
1731
1732 return bufferedPackets;
1733 }
1734
Sangho Shin15273b62014-10-16 22:22:05 -07001735
1736
Sangho Shin2f263692014-09-15 14:09:41 -07001737}