blob: 16f0ca25e324ecdecfce6d79b7a14378fd2ac88b [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;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070031import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070032import net.onrc.onos.api.packet.IPacketService;
33import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070034import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070035import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070036import net.onrc.onos.core.matchaction.MatchAction;
37import net.onrc.onos.core.matchaction.MatchActionId;
38import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070039import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070040import net.onrc.onos.core.matchaction.action.Action;
41import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
42import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
43import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
44import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
45import net.onrc.onos.core.matchaction.action.GroupAction;
46import net.onrc.onos.core.matchaction.action.PopMplsAction;
47import net.onrc.onos.core.matchaction.action.PushMplsAction;
48import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070049import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070050import net.onrc.onos.core.matchaction.match.Match;
51import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin2f263692014-09-15 14:09:41 -070052import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070053import net.onrc.onos.core.packet.Ethernet;
54import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070055import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070056import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070057import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070058import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070059import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070060import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070061import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070062import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070063import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070064import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070065import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070066import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070067import net.onrc.onos.core.util.IPv4Net;
68import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070069
Sangho Shin43cee112014-09-25 16:43:34 -070070import org.json.JSONArray;
71import org.json.JSONException;
Saurav Dasbc594a42014-09-25 20:13:50 -070072import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070073import org.projectfloodlight.openflow.types.IPv4Address;
74import org.slf4j.Logger;
75import org.slf4j.LoggerFactory;
76
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070077public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070078 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070079
80 private static final Logger log = LoggerFactory
81 .getLogger(SegmentRoutingManager.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070082 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070083 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070084 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070085 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070086
87 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070088 private ArpHandler arpHandler;
89 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070090 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070091 private IThreadPoolService threadPool;
92 private SingletonTask discoveryTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070093 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -070094
Sangho Shinfbc572c2014-10-02 16:37:05 -070095 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shinbce900e2014-10-07 17:13:23 -070096 //private HashSet<LinkData> topologyLinks;
Sangho Shin5be3e532014-10-03 17:20:58 -070097 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shinbce900e2014-10-07 17:13:23 -070098
99 private int numOfEvents = 0;
100 private int numOfEventProcess = 0;
101 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700102 private long matchActionId = 0L;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700103
Sangho Shin2f263692014-09-15 14:09:41 -0700104 @Override
105 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
106 // TODO Auto-generated method stub
107 return null;
108 }
109
110 @Override
111 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
112 // TODO Auto-generated method stub
113 return null;
114 }
115
116 @Override
117 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
118 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
119
120 l.add(IFloodlightProviderService.class);
121 l.add(IConfigInfoService.class);
122 l.add(ITopologyService.class);
123 l.add(IPacketService.class);
124 l.add(IFlowPusherService.class);
125 l.add(ITopologyService.class);
126
127 return l;
128
129 }
130
131 @Override
132 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700133 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700134 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700135 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700136 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700137 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700138 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700139 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700140 mutableTopology = topologyService.getTopology();
141 topologyService.addListener(this, false);
Sangho Shin61535402014-10-01 11:37:14 -0700142 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700143 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700144 //topologyLinks = new HashSet<LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700145 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin2f263692014-09-15 14:09:41 -0700146
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700147 this.packetService = context.getServiceImpl(IPacketService.class);
148 packetService.registerPacketListener(this);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700149
Sangho Shin99918bd2014-10-08 15:52:35 -0700150
Sangho Shin2f263692014-09-15 14:09:41 -0700151 }
152
153 @Override
154 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700155 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700156
Sangho Shinc8d2f592014-09-30 16:53:57 -0700157 discoveryTask = new SingletonTask(ses, new Runnable() {
158 @Override
159 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700160 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700161 }
162 });
Sangho Shin2f263692014-09-15 14:09:41 -0700163 }
164
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700165 @Override
166 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700167 if (payload.getEtherType() == Ethernet.TYPE_ARP)
168 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700169 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700170 addPacket((IPv4) payload.getPayload());
171 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
172 icmpHandler.processPacketIn(sw, inPort, payload);
173 else
174 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700175 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700176 else {
177 log.debug("{}", payload.toString());
178 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700179 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700180
Sangho Shin2f263692014-09-15 14:09:41 -0700181 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700182 * Update ARP Cache using ARP packets It is used to set destination MAC
183 * address to forward packets to known hosts. But, it will be replace with
184 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700185 *
Sangho Shin2f263692014-09-15 14:09:41 -0700186 * @param arp APR packets to use for updating ARP entries
187 */
188 public void updateArpCache(ARP arp) {
189
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700190 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
191 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700192 // TODO: Need to check the duplication
193 arpEntries.add(arpEntry);
194 }
195
196 /**
197 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700198 *
Sangho Shin2f263692014-09-15 14:09:41 -0700199 * @param destinationAddress IP address to get MAC address
200 * @return MAC Address to given IP address
201 */
202 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
203
204 // Can't we get the host IP address from the TopologyService ??
205
206 Iterator<ArpEntry> iterator = arpEntries.iterator();
207
208 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
209 byte[] ipAddressInByte = ipAddress.getBytes();
210
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700211 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700212 ArpEntry arpEntry = iterator.next();
213 byte[] address = arpEntry.targetIpAddress;
214
215 IPv4Address a = IPv4Address.of(address);
216 IPv4Address b = IPv4Address.of(ipAddressInByte);
217
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700218 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700219 log.debug("Found an arp entry");
220 return arpEntry.targetMacAddress;
221 }
222 }
223
224 return null;
225 }
226
Sangho Shineb083032014-09-22 16:11:34 -0700227 /**
228 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700229 *
Sangho Shineb083032014-09-22 16:11:34 -0700230 * @param destinationAddress
231 * @param sw
232 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700233 *
Sangho Shineb083032014-09-22 16:11:34 -0700234 */
235 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
236 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
237 }
Sangho Shin2f263692014-09-15 14:09:41 -0700238
239 /**
240 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700241 *
Sangho Shin2f263692014-09-15 14:09:41 -0700242 */
243 private class ArpEntry {
244
245 byte[] targetMacAddress;
246 byte[] targetIpAddress;
247
248 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
249 this.targetMacAddress = macAddress;
250 this.targetIpAddress = ipAddress;
251 }
Sangho Shin2f263692014-09-15 14:09:41 -0700252 }
Sangho Shineb083032014-09-22 16:11:34 -0700253
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700254 /**
255 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700256 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700257 * @param topologyEvents the generated Topology Events
258 * @see TopologyEvents
259 */
260 public void topologyEvents(TopologyEvents topologyEvents)
261 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700262 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700263 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700264 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700265
Sangho Shinc8d2f592014-09-30 16:53:57 -0700266
Sangho Shin5be3e532014-10-03 17:20:58 -0700267 private void handleTopologyChangeEvents() {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700268
Sangho Shinbce900e2014-10-07 17:13:23 -0700269 numOfEventProcess ++;
270
271 Collection<LinkData> linkEntriesAdded = new ArrayList<LinkData>();
272 Collection<PortData> portEntriesAdded = new ArrayList<PortData>();
273 Collection<PortData> portEntriesRemoved = new ArrayList<PortData>();
274 Collection<LinkData> linkEntriesRemoved = new ArrayList<LinkData>();
Sangho Shin99918bd2014-10-08 15:52:35 -0700275 Collection<SwitchData> switchAdded = new ArrayList<SwitchData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700276 Collection<SwitchData> switchRemoved = new ArrayList<SwitchData>();
277 Collection<MastershipData> mastershipRemoved = new ArrayList<MastershipData>();
278
Sangho Shin5be3e532014-10-03 17:20:58 -0700279 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700280 // We should handle the events in the order of when they happen
281 // TODO: We need to simulate the final results of multiple events
282 // and shoot only the final state.
283 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
284 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin5be3e532014-10-03 17:20:58 -0700285 TopologyEvents topologyEvents = topologyEventQueue.poll();
286
Sangho Shin99918bd2014-10-08 15:52:35 -0700287 linkEntriesAdded.addAll(topologyEvents.getAddedLinkDataEntries());
288 portEntriesAdded.addAll(topologyEvents.getAddedPortDataEntries());
289 portEntriesRemoved.addAll(topologyEvents.getRemovedPortDataEntries());
290 linkEntriesRemoved.addAll(topologyEvents.getRemovedLinkDataEntries());
291 switchAdded.addAll(topologyEvents.getAddedSwitchDataEntries());
292 switchRemoved.addAll(topologyEvents.getRemovedSwitchDataEntries());
293 mastershipRemoved.addAll(topologyEvents.getRemovedMastershipDataEntries());
Sangho Shinbce900e2014-10-07 17:13:23 -0700294 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700295
296 if (!portEntriesRemoved.isEmpty()) {
297 processPortRemoval(portEntriesRemoved);
298 }
299
300 if (!linkEntriesRemoved.isEmpty()) {
301 processLinkRemoval(linkEntriesRemoved);
302 }
303
304 if (!switchRemoved.isEmpty()) {
305 processSwitchRemoved(switchRemoved);
306 }
307
308 if (!mastershipRemoved.isEmpty()) {
309 processMastershipRemoved(mastershipRemoved);
310 }
311
312 if (!linkEntriesAdded.isEmpty()) {
313 processLinkAdd(linkEntriesAdded);
314 }
315
316 if (!portEntriesAdded.isEmpty()) {
317 processPortAdd(portEntriesAdded);
318 }
319
320 if (!switchAdded.isEmpty()) {
321 processSwitchAdd(switchAdded);
322 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700323 }
324
Sangho Shinbce900e2014-10-07 17:13:23 -0700325 log.debug("num events {}, num of process {}, "
326 + "num of Population {}", numOfEvents, numOfEventProcess,
327 numOfPopulation);
328 }
329
330 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700331 * Process the SwitchAdded events from topologyMananger.
332 * It does nothing. When a switch is added, then link will be added too.
333 * LinkAdded event will handle process all re-computation.
334 *
335 * @param switchAdded
336 */
337 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
338
339 }
340
341 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700342 * Remove all ports connected to the switch removed
343 *
344 * @param mastershipRemoved master switch info removed
345 */
346 private void processMastershipRemoved(Collection<MastershipData>
347 mastershipRemoved) {
348 for (MastershipData mastership: mastershipRemoved) {
349 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
350 for (Link link: sw.getOutgoingLinks()) {
351 Port dstPort = link.getDstPort();
352 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
353 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700354 if (dstSw != null) {
355 dstSw.removePortFromGroups(dstPort.getNumber());
356 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
357 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700358 }
Sangho Shin61535402014-10-01 11:37:14 -0700359 }
360 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700361
Sangho Shinbce900e2014-10-07 17:13:23 -0700362 /**
363 * Remove all ports connected to the switch removed
364 *
365 * @param switchRemoved Switch removed
366 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700367 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700368 //topologyLinks.clear();
369
370 for (SwitchData switchData: switchRemoved) {
371 Switch sw = mutableTopology.getSwitch(switchData.getDpid());
372 for (Link link: sw.getOutgoingLinks()) {
373 Port dstPort = link.getDstPort();
374 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
375 getSwId(dstPort.getDpid().toString()));
376 if (dstSw != null) {
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700377 dstSw.removePortFromGroups(dstPort.getNumber());
Sangho Shinbce900e2014-10-07 17:13:23 -0700378 log.debug("Switch {} is gone: remove port {}", sw.getDpid(), dstPort);
379 }
380 }
381 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700382 }
383
Sangho Shin61535402014-10-01 11:37:14 -0700384 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700385 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700386 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700387 * @param portEntries
388 */
389 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700390 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700391 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700392 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700393
Sangho Shinfbc572c2014-10-02 16:37:05 -0700394 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700395 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700396 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700397 sw.addPortToGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700398 log.debug("Add port {} to switch {}", port, dpid);
399 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700400 }
401 }
402
403 /**
404 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shinfbc572c2014-10-02 16:37:05 -0700405 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700406 * @param linkEntries
407 */
408 private void processLinkAdd(Collection<LinkData> linkEntries) {
409
Sangho Shinbce900e2014-10-07 17:13:23 -0700410 //boolean linkRecovered = false;
Sangho Shin5be3e532014-10-03 17:20:58 -0700411
Sangho Shin99918bd2014-10-08 15:52:35 -0700412 // TODO: How to determine this link was broken before and back now?
413 // We should go stateless as possible.
414 // If the link broken is up, we need to add the link with delay.
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700415 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700416
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700417 SwitchPort srcPort = link.getSrc();
418 SwitchPort dstPort = link.getDst();
419
Sangho Shinfbc572c2014-10-02 16:37:05 -0700420 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700421 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700422 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700423 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700424
Sangho Shin815af0c2014-10-10 13:05:45 -0700425 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700426 /* If this link is not between two switches, ignore it */
427 continue;
428
429 srcSw.addPortToGroups(srcPort.getPortNumber());
430 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700431
Sangho Shin815af0c2014-10-10 13:05:45 -0700432 log.debug("Add port {} to switch {}", srcPort, srcSw);
433 log.debug("Add port {} to switch {}", dstPort, dstSw);
434
Sangho Shinbce900e2014-10-07 17:13:23 -0700435 /*
Sangho Shin5be3e532014-10-03 17:20:58 -0700436 if (!topologyLinks.contains(link)) {
437 topologyLinks.add(link);
438 }
439 else {
440 linkRecovered = true;
441 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700442 */
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700443 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700444
445 //if (linkRecovered) {
446 // populateEcmpRoutingRules(false);
447 //}
448 //else {
449 populateEcmpRoutingRules(false);
450 //}
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700451 }
452
453 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700454 * Check if all links are gone b/w the two switches. If all links are gone,
455 * then we need to recalculate the path. Otherwise, just report link failure
456 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700457 *
Sangho Shin61535402014-10-01 11:37:14 -0700458 * @param linkEntries
459 */
460 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700461 boolean recomputationRequired = false;
462
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700463 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700464 SwitchPort srcPort = link.getSrc();
465 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700466
Sangho Shinfbc572c2014-10-02 16:37:05 -0700467 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700468 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700469 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700470 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700471 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700472 /* If this link is not between two switches, ignore it */
473 continue;
474 srcSw.removePortFromGroups(srcPort.getPortNumber());
475 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700476 log.debug("Remove port {} from switch {}", srcPort, srcSw);
477 log.debug("Remove port {} from switch {}", dstPort, dstSw);
478
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700479 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
480 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700481 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700482 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700483 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700484 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700485 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700486 }
487 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700488
489 if (recomputationRequired)
490 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700491 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700492
Sangho Shin61535402014-10-01 11:37:14 -0700493 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700494 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700495 *
Sangho Shin61535402014-10-01 11:37:14 -0700496 * @param portEntries
497 */
498 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700499 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700500 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700501
Sangho Shinfbc572c2014-10-02 16:37:05 -0700502 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700503 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700504 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700505 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700506 log.debug("Remove port {} from switch {}", port, dpid);
507 }
Sangho Shin61535402014-10-01 11:37:14 -0700508 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700509 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700510
511 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700512 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700513 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700514 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700515 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700516 private void populateEcmpRoutingRules(boolean modified) {
517 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700518 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700519 for (Switch sw : switches) {
520 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700521 graphs.put(sw, ecmpSPG);
522 //log.debug("ECMPShortestPathGraph is computed for switch {}",
523 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700524 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700525 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700526 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700527 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700528
Sangho Shin99918bd2014-10-08 15:52:35 -0700529 /**
530 * populate routing rules to forward packets from the switch given to
531 * all other switches.
532 *
533 * @param sw source switch
534 * @param ecmpSPG shortest path from the the source switch to all others
535 * @param modified modification flag
536 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700537 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700538 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700539
Sangho Shinfbc572c2014-10-02 16:37:05 -0700540 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
541 ecmpSPG.getAllLearnedSwitchesAndVia();
542 for (Integer itrIdx : switchVia.keySet()) {
543 //log.debug("ECMPShortestPathGraph:Switches learned in "
544 // + "Iteration{} from switch {}:",
545 // itrIdx,
546 // HexString.toHexString(sw.getDpid().value()));
547 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
548 switchVia.get(itrIdx);
549 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700550 //log.debug("ECMPShortestPathGraph:****switch {} via:",
551 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700552 String destSw = sw.getDpid().toString();
553 List<String> fwdToSw = new ArrayList<String>();
554
Sangho Shinfbc572c2014-10-02 16:37:05 -0700555 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700556 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700557 if (via.isEmpty()) {
558 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700559 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700560 else {
561 fwdToSw.add(via.get(0).toString());
562 }
Sangho Shin43cee112014-09-25 16:43:34 -0700563 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700564 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700565 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700566
567 // Send Barrier Message and make sure all rules are set
568 // before we set the rules to next routers
569 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
570 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700571 if (sw13 != null) {
572 try {
573 OFBarrierReplyFuture replyFuture = sw13.sendBarrier();
574 replyFuture.get(10, TimeUnit.SECONDS);
575 } catch (IOException e) {
576 e.printStackTrace();
577 } catch (InterruptedException | ExecutionException | TimeoutException e) {
578 log.error("Barrier message not received for sw: {}", sw.getDpid());
579 e.printStackTrace();
580 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700581 }
582 }
583
584 }
585
586
Sangho Shin99918bd2014-10-08 15:52:35 -0700587 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700588 * This class is used only for link recovery optimization in
589 * modifyEcmpRoutingRules() function.
Sangho Shin99918bd2014-10-08 15:52:35 -0700590 * TODO: please remove if the optimization is not used at all
Sangho Shinbce900e2014-10-07 17:13:23 -0700591 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700592 private class SwitchPair {
593 private Switch src;
594 private Switch dst;
595
596 public SwitchPair(Switch src, Switch dst) {
597 this.src = src;
598 this.dst = dst;
599 }
600
601 public Switch getSource() {
602 return src;
603 }
604
605 public Switch getDestination() {
606 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700607 }
Sangho Shin43cee112014-09-25 16:43:34 -0700608 }
609
610 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700611 * Modify the routing rules for the lost links
612 * - Recompute the path if the link failed is included in the path
613 * (including src and dest).
614 *
615 * @param newLink
616 */
617 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
618
619 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700620 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700621
622 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
623 Switch rootSw = ecmpSPG.getRootSwitch();
624 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
625 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
626 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
627 for (Switch destSw: p.keySet()) {
628 ArrayList<Path> path = p.get(destSw);
629 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700630 boolean found = false;
631 for (SwitchPair pair: linksToRecompute) {
632 if (pair.getSource().getDpid() == rootSw.getDpid() &&
633 pair.getSource().getDpid() == destSw.getDpid()) {
634 found = true;
635 }
636 }
637 if (!found) {
638 linksToRecompute.add(new SwitchPair(rootSw, destSw));
639 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700640 }
641 }
642 }
643 }
644
645 // Recompute the path for the specific route
646 for (SwitchPair pair: linksToRecompute) {
647
648 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
Sangho Shin99918bd2014-10-08 15:52:35 -0700649 // We need the following function for optimization
Sangho Shinfbc572c2014-10-02 16:37:05 -0700650 //ECMPShortestPathGraph ecmpSPG =
651 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
652 ECMPShortestPathGraph ecmpSPG =
653 new ECMPShortestPathGraph(pair.getSource());
Sangho Shin5be3e532014-10-03 17:20:58 -0700654 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700655 }
656 }
657
658 /**
659 * Check if the path is affected from the link removed
660 *
661 * @param path Path to check
662 * @param linkRemoved link removed
663 * @return true if the path contains the link removed
664 */
665 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
666
667 for (Path ppp: path) {
668 // TODO: need to check if this is a bidirectional or
669 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700670 for (LinkData link: ppp) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700671 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
672 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
673 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700674 }
675 }
676
677 return false;
678 }
679
680 /**
681 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700682 * Set routing rules in targetSw {forward packets to fwdToSw switches in
683 * order to send packets to destSw} - If the target switch is an edge router
684 * and final destnation switch is also an edge router, then set IP
685 * forwarding rules to subnets - If only the target switch is an edge
686 * router, then set IP forwarding rule to the transit router loopback IP
687 * address - If the target is a transit router, then just set the MPLS
688 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700689 *
Sangho Shin43cee112014-09-25 16:43:34 -0700690 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700691 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700692 * @param fwdToSw next hop switches
693 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700694 private void setRoutingRule(Switch targetSw, String destSw,
695 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700696
Sangho Shin43cee112014-09-25 16:43:34 -0700697 if (fwdToSw.isEmpty()) {
698 fwdToSw.add(destSw);
699 }
700
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700701 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700702 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
703 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700704 // We assume that there is at least one transit router b/w edge
705 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700706 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
707 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700708 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700709 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700710
Sangho Shin43cee112014-09-25 16:43:34 -0700711 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700712 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
713 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700714 // Edge router can be a transit router
715 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700716 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700717 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700718 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700719 // We assume that there is at least one transit router b/w edge
720 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700721 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
722 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700723 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
724 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700725 // Edge router can be a transit router
726 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700727 }
728 // if it is a transit router, then set rules in the MPLS table
729 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700730 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700731 }
732
733 }
734
Sangho Shinfbc572c2014-10-02 16:37:05 -0700735 /**
736 * Set IP forwarding rule to the gateway of each subnet of switches
737 *
738 * @param targetSw Switch to set rules
739 * @param subnets subnet information
740 * @param mplsLabel destination MPLS label
741 * @param fwdToSw router to forward packets to
742 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700743 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700744 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700745
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700746 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700747 new ArrayList<MatchActionOperationEntry>();
748
749 try {
750 JSONArray arry = new JSONArray(subnets);
751 for (int i = 0; i < arry.length(); i++) {
752 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700753 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
754 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700755 }
756 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700757 e.printStackTrace();
758 }
759
760 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700761 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700762 getSwId(targetSw.getDpid().toString()));
763
Sangho Shin721ca042014-10-09 13:03:40 -0700764 if (sw13 != null) {
765 try {
766 sw13.pushFlows(entries);
767 } catch (IOException e) {
768 e.printStackTrace();
769 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700770 }
771 }
772
773 }
774
Sangho Shin43cee112014-09-25 16:43:34 -0700775 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700776 * Check if the switch is the edge router or not.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700777 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700778 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700779 * @return true if it is an edge router, otherwise false
780 */
781 private boolean IsEdgeRouter(String dpid) {
782
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700783 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700784 String dpidStr = sw.getDpid().toString();
785 if (dpid.equals(dpidStr)) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700786 /*
Sangho Shin43cee112014-09-25 16:43:34 -0700787 String subnetInfo = sw.getStringAttribute("subnets");
788 if (subnetInfo == null || subnetInfo.equals("[]")) {
789 return false;
790 }
791 else
792 return true;
Sangho Shinbce900e2014-10-07 17:13:23 -0700793 */
794 String isEdge = sw.getStringAttribute("isEdgeRouter");
795 if (isEdge != null) {
796 if (isEdge.equals("true"))
797 return true;
798 else
799 return false;
800 }
Sangho Shin43cee112014-09-25 16:43:34 -0700801 }
802 }
803
804 return false;
805 }
806
807 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700808 * Set IP forwarding rule - If the destination is the next hop, then do not
809 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
810 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700811 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700812 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700813 * @param subnetIp Match IP address
814 * @param mplsLabel MPLS label of final destination router
815 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700816 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700817 */
818 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700819 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
820 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700821
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700822 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700823 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700824 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700825
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700826 // If destination SW is the same as the fwd SW, then do not push MPLS
827 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700828
829 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700830 PushMplsAction pushMplsAction = new PushMplsAction();
831 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
832 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700833 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700834
Sangho Shin62ce5c12014-10-08 16:24:40 -0700835 //actions.add(pushMplsAction);
836 //actions.add(copyTtlOutAction);
837 //actions.add(decMplsTtlAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700838 actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700839 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
840
Sangho Shin43cee112014-09-25 16:43:34 -0700841 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700842 else {
843 String fwdToSw = fwdToSws.get(0);
844 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
845 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
846 actions.add(decTtlAction);
847 }
848 else {
849 PushMplsAction pushMplsAction = new PushMplsAction();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700850 SetMplsIdAction setIdAction = new SetMplsIdAction(
851 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700852 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700853 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700854
Sangho Shin62ce5c12014-10-08 16:24:40 -0700855 //actions.add(pushMplsAction);
856 //actions.add(copyTtlOutAction);
857 //actions.add(decMplsTtlAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700858 actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700859 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700860 }
861 }
Sangho Shin43cee112014-09-25 16:43:34 -0700862
Sangho Shin43cee112014-09-25 16:43:34 -0700863 for (String fwdSw : fwdToSws) {
864 groupAction.addSwitch(new Dpid(fwdSw));
865 }
866 actions.add(groupAction);
867
Sangho Shin99918bd2014-10-08 15:52:35 -0700868 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700869 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700870
Sangho Shin5be3e532014-10-03 17:20:58 -0700871 Operator operator = null;
872 if (modified)
873 operator = Operator.MODIFY;
874 else
875 operator = Operator.ADD;
876
Sangho Shin43cee112014-09-25 16:43:34 -0700877 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700878 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700879
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700880 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700881 getSwId(sw.getDpid().toString()));
882
Sangho Shin5be3e532014-10-03 17:20:58 -0700883 if (sw13 != null) {
884 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700885 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700886 if (entries != null)
887 entries.add(maEntry);
888 else
889 sw13.pushFlow(maEntry);
890 } catch (IOException e) {
891 e.printStackTrace();
892 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700893 }
894
Sangho Shin43cee112014-09-25 16:43:34 -0700895 }
896
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700897 /**
898 * Convert a string DPID to its Switch Id (integer)
Sangho Shinfbc572c2014-10-02 16:37:05 -0700899 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700900 * @param dpid
901 * @return
902 */
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700903 private long getSwId(String dpid) {
904
905 long swId = 0;
906
Sangho Shinbce900e2014-10-07 17:13:23 -0700907 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
908 if (swIdHexStr != null)
909 swId = Integer.decode(swIdHexStr);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700910
911 return swId;
912 }
913
Sangho Shin43cee112014-09-25 16:43:34 -0700914 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700915 * Set MPLS forwarding rules to MPLS table
916 * </p>
917 * If the destination is the same as the next hop to forward packets then,
918 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
919 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
920 * TTL of the another MPLS header.
921 * If the next hop is not the destination, just forward packets to next
922 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700923 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700924 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700925 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700926 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700927 * */
Sangho Shin5be3e532014-10-03 17:20:58 -0700928 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
929 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -0700930
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700931 if (fwdSws.isEmpty())
932 return;
Sangho Shin43cee112014-09-25 16:43:34 -0700933
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700934 Collection<MatchActionOperationEntry> maEntries =
935 new ArrayList<MatchActionOperationEntry>();
936 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -0700937
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700938 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
939 // One rule for Bos = 1
940 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
941 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700942
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700943 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
944 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
945 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
946
947 actions.add(copyTtlInAction);
948 actions.add(popAction);
949 actions.add(decNwTtlAction);
950
951 GroupAction groupAction = new GroupAction();
952 groupAction.addSwitch(new Dpid(fwdSw1));
953 actions.add(groupAction);
954
955 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
956 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
957 Operator operator = Operator.ADD;
958 MatchActionOperationEntry maEntry =
959 new MatchActionOperationEntry(operator, matchAction);
960 maEntries.add(maEntry);
961
962 // One rule for Bos = 0
963 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
964 List<Action> actionsBos = new ArrayList<Action>();
965 actionsBos.add(popAction);
966 actionsBos.add(groupAction);
967
968 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
969 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
970 MatchActionOperationEntry maEntryBos =
971 new MatchActionOperationEntry(operator, matchActionBos);
972 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700973 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700974 else {
975 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
976 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700977
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700978 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
979 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700980
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700981 GroupAction groupAction = new GroupAction();
982 for (String fwdSw : fwdSws)
983 groupAction.addSwitch(new Dpid(fwdSw));
984 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -0700985
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700986 MatchAction matchAction = new MatchAction(new MatchActionId(
987 matchActionId++),
988 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
989 Operator operator = Operator.ADD;
990 MatchActionOperationEntry maEntry =
991 new MatchActionOperationEntry(operator, matchAction);
992 maEntries.add(maEntry);
993 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700994 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700995 getSwId(sw.getDpid().toString()));
996
Sangho Shin5be3e532014-10-03 17:20:58 -0700997 if (sw13 != null) {
998 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700999 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001000 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001001 } catch (IOException e) {
1002 e.printStackTrace();
1003 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001004 }
Sangho Shin43cee112014-09-25 16:43:34 -07001005 }
1006
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001007
Sangho Shin43cee112014-09-25 16:43:34 -07001008 /**
1009 * Debugging function to print out the Match Action Entry
Sangho Shinfbc572c2014-10-02 16:37:05 -07001010 *
Sangho Shin43cee112014-09-25 16:43:34 -07001011 * @param maEntry
1012 */
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001013 private void printMatchActionOperationEntry(Switch sw,
1014 MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -07001015
Sangho Shin0df01982014-09-25 17:11:18 -07001016 StringBuilder logStr = new StringBuilder("In switch " + sw.getDpid() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001017
1018 MatchAction ma = maEntry.getTarget();
1019 Match m = ma.getMatch();
1020 List<Action> actions = ma.getActions();
1021
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001022 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -07001023 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001024 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -07001025 logStr.append(ip.toString());
1026 logStr.append(" then ");
1027 }
1028 else if (m instanceof MplsMatch) {
1029 logStr.append("If the MPLS label matches with ");
1030 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1031 logStr.append(mplsLabel);
1032 logStr.append(" then ");
1033 }
1034
1035 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001036 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -07001037 if (action instanceof CopyTtlInAction) {
1038 logStr.append("copy ttl In, ");
1039 }
1040 else if (action instanceof CopyTtlOutAction) {
1041 logStr.append("copy ttl Out, ");
1042 }
1043 else if (action instanceof DecMplsTtlAction) {
1044 logStr.append("Dec MPLS TTL , ");
1045 }
1046 else if (action instanceof GroupAction) {
1047 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001048 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -07001049 logStr.append(dpids.toString() + ",");
1050
Sangho Shin43cee112014-09-25 16:43:34 -07001051 }
1052 else if (action instanceof PopMplsAction) {
1053 logStr.append("Pop MPLS label, ");
1054 }
1055 else if (action instanceof PushMplsAction) {
1056 logStr.append("Push MPLS label, ");
1057 }
1058 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001059 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -07001060 logStr.append("Set MPLS ID as " + id + ", ");
1061
1062 }
1063 }
1064
1065 log.debug(logStr.toString());
1066
Sangho Shineb083032014-09-22 16:11:34 -07001067 }
1068
1069 /**
1070 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001071 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001072 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001073 * @return MPLS label for the switch
1074 */
1075
Sangho Shin43cee112014-09-25 16:43:34 -07001076 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001077
1078 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001079 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001080 String dpidStr = sw.getDpid().toString();
1081 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001082 mplsLabel = sw.getStringAttribute("nodeSid");
1083 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001084 }
1085 }
1086
Sangho Shineb083032014-09-22 16:11:34 -07001087 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001088 }
1089
Sangho Shineb083032014-09-22 16:11:34 -07001090 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001091 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001092 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001093 * @param addr - subnet address to match
1094 * @param addr1 - IP address to check
1095 * @return true if the IP address matches to the subnet, otherwise false
1096 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001097 public boolean netMatch(String addr, String addr1) { // addr is subnet
1098 // address and addr1 is
1099 // ip address. Function
1100 // will return true, if
1101 // addr1 is within
1102 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001103
1104 String[] parts = addr.split("/");
1105 String ip = parts[0];
1106 int prefix;
1107
1108 if (parts.length < 2) {
1109 prefix = 0;
1110 } else {
1111 prefix = Integer.parseInt(parts[1]);
1112 }
1113
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001114 Inet4Address a = null;
1115 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001116 try {
1117 a = (Inet4Address) InetAddress.getByName(ip);
1118 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001119 } catch (UnknownHostException e) {
1120 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001121
1122 byte[] b = a.getAddress();
1123 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001124 ((b[1] & 0xFF) << 16) |
1125 ((b[2] & 0xFF) << 8) |
1126 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001127
1128 byte[] b1 = a1.getAddress();
1129 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001130 ((b1[1] & 0xFF) << 16) |
1131 ((b1[2] & 0xFF) << 8) |
1132 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001133
1134 int mask = ~((1 << (32 - prefix)) - 1);
1135
1136 if ((ipInt & mask) == (ipInt1 & mask)) {
1137 return true;
1138 }
1139 else {
1140 return false;
1141 }
1142 }
Sangho Shineb083032014-09-22 16:11:34 -07001143
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001144 /**
1145 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001146 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001147 * @param sw - Switch to add the rule
1148 * @param hostIpAddress Destination host IP address
1149 * @param hostMacAddress Destination host MAC address
1150 */
Sangho Shineb083032014-09-22 16:11:34 -07001151 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1152 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1153
1154 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001155
Sangho Shin463bee52014-09-29 15:14:43 -07001156 /**
1157 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001158 *
Sangho Shin463bee52014-09-29 15:14:43 -07001159 * @param ipv4
1160 */
1161 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001162 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001163 }
1164
1165 /**
1166 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001167 *
Sangho Shin463bee52014-09-29 15:14:43 -07001168 * @param destIp Destination address of packets to retrieve
1169 */
1170 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1171
1172 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1173
Sangho Shin61535402014-10-01 11:37:14 -07001174 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001175 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001176 int dest = ip.getDestinationAddress();
1177 IPv4Address ip1 = IPv4Address.of(dest);
1178 IPv4Address ip2 = IPv4Address.of(destIp);
1179 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001180 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001181 }
1182 }
1183 }
1184
1185 return bufferedPackets;
1186 }
1187
Sangho Shin2f263692014-09-15 14:09:41 -07001188}