blob: 34c5046279837b2ccece1b1fc5db51286f9d9cad [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 Shinbce900e2014-10-07 17:13:23 -070016import java.util.concurrent.ConcurrentMap;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070017import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070018import java.util.concurrent.ScheduledExecutorService;
19import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070020import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070021
22import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070023import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070024import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070025import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070026import net.floodlightcontroller.core.module.FloodlightModuleContext;
27import net.floodlightcontroller.core.module.FloodlightModuleException;
28import net.floodlightcontroller.core.module.IFloodlightModule;
29import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070030import net.floodlightcontroller.core.util.SingletonTask;
31import net.floodlightcontroller.threadpool.IThreadPoolService;
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 Shin2f263692014-09-15 14:09:41 -070053import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070054import net.onrc.onos.core.packet.Ethernet;
55import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070056import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070057import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070058import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070059import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070060import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070061import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070062import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070063import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070064import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070065import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070066import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070067import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070068import net.onrc.onos.core.util.IPv4Net;
69import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070070
Sangho Shin43cee112014-09-25 16:43:34 -070071import org.json.JSONArray;
72import org.json.JSONException;
Saurav Dasbc594a42014-09-25 20:13:50 -070073import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070074import org.projectfloodlight.openflow.types.IPv4Address;
75import org.slf4j.Logger;
76import org.slf4j.LoggerFactory;
77
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070078public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070079 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070080
81 private static final Logger log = LoggerFactory
82 .getLogger(SegmentRoutingManager.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070083 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070084 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070085 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070086 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070087
88 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070089 private ArpHandler arpHandler;
90 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070091 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070092 private IThreadPoolService threadPool;
93 private SingletonTask discoveryTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070094 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -070095
Sangho Shinfbc572c2014-10-02 16:37:05 -070096 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shinbce900e2014-10-07 17:13:23 -070097 //private HashSet<LinkData> topologyLinks;
Sangho Shin5be3e532014-10-03 17:20:58 -070098 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shinbce900e2014-10-07 17:13:23 -070099 private ConcurrentMap<Dpid, TopologyEvents> topologyEventMap;
100
101 private int numOfEvents = 0;
102 private int numOfEventProcess = 0;
103 private int numOfPopulation = 0;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700104
Sangho Shin2f263692014-09-15 14:09:41 -0700105 @Override
106 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
107 // TODO Auto-generated method stub
108 return null;
109 }
110
111 @Override
112 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
113 // TODO Auto-generated method stub
114 return null;
115 }
116
117 @Override
118 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
119 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
120
121 l.add(IFloodlightProviderService.class);
122 l.add(IConfigInfoService.class);
123 l.add(ITopologyService.class);
124 l.add(IPacketService.class);
125 l.add(IFlowPusherService.class);
126 l.add(ITopologyService.class);
127
128 return l;
129
130 }
131
132 @Override
133 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700134 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700135 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700136 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700137 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700138 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700139 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700140 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700141 mutableTopology = topologyService.getTopology();
142 topologyService.addListener(this, false);
Sangho Shin61535402014-10-01 11:37:14 -0700143 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700144 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700145 //topologyLinks = new HashSet<LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700146 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin2f263692014-09-15 14:09:41 -0700147
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700148 this.packetService = context.getServiceImpl(IPacketService.class);
149 packetService.registerPacketListener(this);
Sangho Shin9c0f4c32014-09-26 16:02:38 -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>();
275 Collection<SwitchData> switchRemoved = new ArrayList<SwitchData>();
276 Collection<MastershipData> mastershipRemoved = new ArrayList<MastershipData>();
277
Sangho Shin5be3e532014-10-03 17:20:58 -0700278 while (!topologyEventQueue.isEmpty()) {
279 TopologyEvents topologyEvents = topologyEventQueue.poll();
280
Sangho Shinbce900e2014-10-07 17:13:23 -0700281 if (linkEntriesAdded == null)
282 linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
283 else
284 linkEntriesAdded.addAll(topologyEvents.getAddedLinkDataEntries());
Sangho Shin5be3e532014-10-03 17:20:58 -0700285
Sangho Shinbce900e2014-10-07 17:13:23 -0700286 if (portEntriesAdded == null)
287 portEntriesAdded = topologyEvents.getAddedPortDataEntries();
288 else
289 portEntriesAdded.addAll(topologyEvents.getAddedPortDataEntries());
Sangho Shin5be3e532014-10-03 17:20:58 -0700290
Sangho Shinbce900e2014-10-07 17:13:23 -0700291 if (portEntriesRemoved == null)
292 portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
293 else
294 portEntriesRemoved.addAll(topologyEvents.getRemovedPortDataEntries());
Sangho Shin5be3e532014-10-03 17:20:58 -0700295
Sangho Shinbce900e2014-10-07 17:13:23 -0700296 if (linkEntriesRemoved == null)
297 linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
298 else
299 linkEntriesRemoved.addAll(topologyEvents.getRemovedLinkDataEntries());
Sangho Shin5be3e532014-10-03 17:20:58 -0700300
Sangho Shinbce900e2014-10-07 17:13:23 -0700301 if (switchRemoved == null)
302 switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
303 else
304 switchRemoved.addAll(topologyEvents.getRemovedSwitchDataEntries());
Sangho Shin5be3e532014-10-03 17:20:58 -0700305
Sangho Shinbce900e2014-10-07 17:13:23 -0700306 if (mastershipRemoved == null)
307 mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
308 else
309 mastershipRemoved.addAll(topologyEvents.getRemovedMastershipDataEntries());
310
311 numOfEvents++;
312 }
313
314
315 if (!linkEntriesAdded.isEmpty()) {
316 processLinkAdd(linkEntriesAdded);
317 }
318
319 if (portEntriesAdded != null) {
320 processPortAdd(portEntriesAdded);
321 }
322
323 if (!portEntriesRemoved.isEmpty()) {
324 processPortRemoval(portEntriesRemoved);
325 }
326
327 if (!linkEntriesRemoved.isEmpty()) {
328 processLinkRemoval(linkEntriesRemoved);
329 }
330
331 if (!switchRemoved.isEmpty()) {
332 processSwitchRemoved(switchRemoved);
333 }
334
335 if (!mastershipRemoved.isEmpty()) {
336 processMastershipRemoved(mastershipRemoved);
337 }
338
339 log.debug("num events {}, num of process {}, "
340 + "num of Population {}", numOfEvents, numOfEventProcess,
341 numOfPopulation);
342 }
343
344 /**
345 * Remove all ports connected to the switch removed
346 *
347 * @param mastershipRemoved master switch info removed
348 */
349 private void processMastershipRemoved(Collection<MastershipData>
350 mastershipRemoved) {
351 for (MastershipData mastership: mastershipRemoved) {
352 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
353 for (Link link: sw.getOutgoingLinks()) {
354 Port dstPort = link.getDstPort();
355 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
356 getSwId(dstPort.getDpid().toString()));
357 // TODO: please enable it when driver feature is implemented
358 //dstSw.removePortFromGroups(dstPort.getNumber());
359 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
360
361 }
Sangho Shin61535402014-10-01 11:37:14 -0700362 }
363 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700364
Sangho Shinbce900e2014-10-07 17:13:23 -0700365 /**
366 * Remove all ports connected to the switch removed
367 *
368 * @param switchRemoved Switch removed
369 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700370 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700371 //topologyLinks.clear();
372
373 for (SwitchData switchData: switchRemoved) {
374 Switch sw = mutableTopology.getSwitch(switchData.getDpid());
375 for (Link link: sw.getOutgoingLinks()) {
376 Port dstPort = link.getDstPort();
377 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
378 getSwId(dstPort.getDpid().toString()));
379 if (dstSw != null) {
380 //dstSw.removePortFromGroups(dstPort.getNumber());
381 log.debug("Switch {} is gone: remove port {}", sw.getDpid(), dstPort);
382 }
383 }
384 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700385 }
386
Sangho Shin61535402014-10-01 11:37:14 -0700387 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700388 * Report ports newly added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700389 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700390 * @param portEntries
391 */
392 private void processPortAdd(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700393 // TODO: do we need to add ports slowly?
394 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700395 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700396
Sangho Shinfbc572c2014-10-02 16:37:05 -0700397 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700398 getSwId(port.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700399 sw.addPortToGroups(port.getPortNumber());
400
401 log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700402 }
403 }
404
405 /**
406 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shinfbc572c2014-10-02 16:37:05 -0700407 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700408 * @param linkEntries
409 */
410 private void processLinkAdd(Collection<LinkData> linkEntries) {
411
Sangho Shinbce900e2014-10-07 17:13:23 -0700412 //boolean linkRecovered = false;
Sangho Shin5be3e532014-10-03 17:20:58 -0700413
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700414 // TODO: How to determine this link was broken before and back now
415 // If so, we need to ad the link slowly...
416 // Or, just add any new or restored link slowly ???
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700417 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700418
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700419 SwitchPort srcPort = link.getSrc();
420 SwitchPort dstPort = link.getDst();
421
Sangho Shinfbc572c2014-10-02 16:37:05 -0700422 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700423 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700424 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700425 getSwId(srcPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700426
Sangho Shinbce900e2014-10-07 17:13:23 -0700427 if (srcSw != null)
428 srcSw.addPortToGroups(srcPort.getPortNumber());
429 if (dstSw != null)
430 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700431
Sangho Shinbce900e2014-10-07 17:13:23 -0700432 /*
Sangho Shin5be3e532014-10-03 17:20:58 -0700433 if (!topologyLinks.contains(link)) {
434 topologyLinks.add(link);
435 }
436 else {
437 linkRecovered = true;
438 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700439 */
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700440 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700441
442 //if (linkRecovered) {
443 // populateEcmpRoutingRules(false);
444 //}
445 //else {
446 populateEcmpRoutingRules(false);
447 //}
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700448 }
449
450 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700451 * Check if all links are gone b/w the two switches. If all links are gone,
452 * then we need to recalculate the path. Otherwise, just report link failure
453 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700454 *
Sangho Shin61535402014-10-01 11:37:14 -0700455 * @param linkEntries
456 */
457 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700458 boolean recomputationRequired = false;
459
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700460 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700461 SwitchPort srcPort = link.getSrc();
462 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700463
Sangho Shinfbc572c2014-10-02 16:37:05 -0700464 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700465 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700466 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700467 getSwId(srcPort.getDpid().toString()));
Sangho Shinbce900e2014-10-07 17:13:23 -0700468 /*
Sangho Shinfbc572c2014-10-02 16:37:05 -0700469 if (srcSw != null)
470 srcSw.removePortFromGroups(srcPort.getPortNumber());
471 if (dstSw != null)
472 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shinbce900e2014-10-07 17:13:23 -0700473 */
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700474
475 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
476 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700477 // TODO: it is only for debugging purpose.
478 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700479 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700480 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700481 }
482 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700483
484 if (recomputationRequired)
485 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700486 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700487
Sangho Shin61535402014-10-01 11:37:14 -0700488 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700489 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700490 *
Sangho Shin61535402014-10-01 11:37:14 -0700491 * @param portEntries
492 */
493 private void processPortRemoval(Collection<PortData> portEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700494 /*
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700495 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700496 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700497
Sangho Shinfbc572c2014-10-02 16:37:05 -0700498 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700499 getSwId(port.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700500 if (sw != null)
501 sw.removePortFromGroups(port.getPortNumber());
502 log.debug("Remove port {} from switch {}", port, dpid);
Sangho Shin61535402014-10-01 11:37:14 -0700503 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700504 */
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700505 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700506
507 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700508 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700509 *
Sangho Shin1aa93542014-09-22 09:49:44 -0700510 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700511 private void populateEcmpRoutingRules(boolean modified) {
512 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700513 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700514 for (Switch sw : switches) {
515 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700516 graphs.put(sw, ecmpSPG);
517 //log.debug("ECMPShortestPathGraph is computed for switch {}",
518 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700519 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
520 if (modified) {
521 log.debug("Modify the rules for {}" , sw.getDpid());
522 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700523 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700524 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700525 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700526
Sangho Shinfbc572c2014-10-02 16:37:05 -0700527 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700528 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700529
Sangho Shinfbc572c2014-10-02 16:37:05 -0700530 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
531 ecmpSPG.getAllLearnedSwitchesAndVia();
532 for (Integer itrIdx : switchVia.keySet()) {
533 //log.debug("ECMPShortestPathGraph:Switches learned in "
534 // + "Iteration{} from switch {}:",
535 // itrIdx,
536 // HexString.toHexString(sw.getDpid().value()));
537 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
538 switchVia.get(itrIdx);
539 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700540 //log.debug("ECMPShortestPathGraph:****switch {} via:",
541 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700542 String destSw = sw.getDpid().toString();
543 List<String> fwdToSw = new ArrayList<String>();
544
Sangho Shinfbc572c2014-10-02 16:37:05 -0700545 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700546 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700547 if (via.isEmpty()) {
548 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700549 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700550 else {
551 fwdToSw.add(via.get(0).toString());
552 }
Sangho Shin43cee112014-09-25 16:43:34 -0700553 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700554 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700555 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700556
557 // Send Barrier Message and make sure all rules are set
558 // before we set the rules to next routers
559 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
560 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700561 if (sw13 != null) {
562 try {
563 OFBarrierReplyFuture replyFuture = sw13.sendBarrier();
564 replyFuture.get(10, TimeUnit.SECONDS);
565 } catch (IOException e) {
566 e.printStackTrace();
567 } catch (InterruptedException | ExecutionException | TimeoutException e) {
568 log.error("Barrier message not received for sw: {}", sw.getDpid());
569 e.printStackTrace();
570 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700571 }
572 }
573
574 }
575
576
Sangho Shinbce900e2014-10-07 17:13:23 -0700577 /*
578 * This class is used only for link recovery optimization in
579 * modifyEcmpRoutingRules() function.
580 * TODO: please remove if optimization is not used at all
581 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700582 private class SwitchPair {
583 private Switch src;
584 private Switch dst;
585
586 public SwitchPair(Switch src, Switch dst) {
587 this.src = src;
588 this.dst = dst;
589 }
590
591 public Switch getSource() {
592 return src;
593 }
594
595 public Switch getDestination() {
596 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700597 }
Sangho Shin43cee112014-09-25 16:43:34 -0700598 }
599
600 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700601 * Modify the routing rules for the lost links
602 * - Recompute the path if the link failed is included in the path
603 * (including src and dest).
604 *
605 * @param newLink
606 */
607 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
608
609 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700610 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700611
612 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
613 Switch rootSw = ecmpSPG.getRootSwitch();
614 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
615 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
616 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
617 for (Switch destSw: p.keySet()) {
618 ArrayList<Path> path = p.get(destSw);
619 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700620 boolean found = false;
621 for (SwitchPair pair: linksToRecompute) {
622 if (pair.getSource().getDpid() == rootSw.getDpid() &&
623 pair.getSource().getDpid() == destSw.getDpid()) {
624 found = true;
625 }
626 }
627 if (!found) {
628 linksToRecompute.add(new SwitchPair(rootSw, destSw));
629 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700630 }
631 }
632 }
633 }
634
635 // Recompute the path for the specific route
636 for (SwitchPair pair: linksToRecompute) {
637
638 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
639 // TODO : we need the following function
640 //ECMPShortestPathGraph ecmpSPG =
641 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
642 ECMPShortestPathGraph ecmpSPG =
643 new ECMPShortestPathGraph(pair.getSource());
644 // TODO: we need to use different function to MODIFY the rules
Sangho Shin5be3e532014-10-03 17:20:58 -0700645 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700646 }
647 }
648
649 /**
650 * Check if the path is affected from the link removed
651 *
652 * @param path Path to check
653 * @param linkRemoved link removed
654 * @return true if the path contains the link removed
655 */
656 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
657
658 for (Path ppp: path) {
659 // TODO: need to check if this is a bidirectional or
660 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700661 for (LinkData link: ppp) {
662 //if (link.equals(linkRemoved))
663 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
664 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
665 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700666 }
667 }
668
669 return false;
670 }
671
672 /**
673 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700674 * Set routing rules in targetSw {forward packets to fwdToSw switches in
675 * order to send packets to destSw} - If the target switch is an edge router
676 * and final destnation switch is also an edge router, then set IP
677 * forwarding rules to subnets - If only the target switch is an edge
678 * router, then set IP forwarding rule to the transit router loopback IP
679 * address - If the target is a transit router, then just set the MPLS
680 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700681 *
Sangho Shin43cee112014-09-25 16:43:34 -0700682 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700683 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700684 * @param fwdToSw next hop switches
685 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700686 private void setRoutingRule(Switch targetSw, String destSw, List<String> fwdToSw,
687 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700688
Sangho Shin43cee112014-09-25 16:43:34 -0700689 if (fwdToSw.isEmpty()) {
690 fwdToSw.add(destSw);
691 }
692
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700693 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700694 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
695 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700696 // We assume that there is at least one transit router b/w edge
697 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700698 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
699 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700700 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700701 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700702
Sangho Shin43cee112014-09-25 16:43:34 -0700703 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700704 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
705 null, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700706 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700707 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700708 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700709 // We assume that there is at least one transit router b/w edge
710 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700711 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
712 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700713 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
714 null, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700715 }
716 // if it is a transit router, then set rules in the MPLS table
717 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700718 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700719 }
720
721 }
722
Sangho Shinfbc572c2014-10-02 16:37:05 -0700723 /**
724 * Set IP forwarding rule to the gateway of each subnet of switches
725 *
726 * @param targetSw Switch to set rules
727 * @param subnets subnet information
728 * @param mplsLabel destination MPLS label
729 * @param fwdToSw router to forward packets to
730 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700731 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700732 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700733
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700734 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700735 new ArrayList<MatchActionOperationEntry>();
736
737 try {
738 JSONArray arry = new JSONArray(subnets);
739 for (int i = 0; i < arry.length(); i++) {
740 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700741 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
742 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700743 }
744 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700745 e.printStackTrace();
746 }
747
748 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700749 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700750 getSwId(targetSw.getDpid().toString()));
751
752 try {
753 sw13.pushFlows(entries);
754 } catch (IOException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700755 e.printStackTrace();
756 }
757 }
758
759 }
760
Sangho Shin43cee112014-09-25 16:43:34 -0700761 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700762 * Check if the switch is the edge router or not If any subnet information
763 * is defined in the config file, the we assume it is an edge router
Sangho Shinfbc572c2014-10-02 16:37:05 -0700764 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700765 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700766 * @return true if it is an edge router, otherwise false
767 */
768 private boolean IsEdgeRouter(String dpid) {
769
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700770 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700771 String dpidStr = sw.getDpid().toString();
772 if (dpid.equals(dpidStr)) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700773 /*
Sangho Shin43cee112014-09-25 16:43:34 -0700774 String subnetInfo = sw.getStringAttribute("subnets");
775 if (subnetInfo == null || subnetInfo.equals("[]")) {
776 return false;
777 }
778 else
779 return true;
Sangho Shinbce900e2014-10-07 17:13:23 -0700780 */
781 String isEdge = sw.getStringAttribute("isEdgeRouter");
782 if (isEdge != null) {
783 if (isEdge.equals("true"))
784 return true;
785 else
786 return false;
787 }
Sangho Shin43cee112014-09-25 16:43:34 -0700788 }
789 }
790
791 return false;
792 }
793
794 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700795 * Set IP forwarding rule - If the destination is the next hop, then do not
796 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
797 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700798 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700799 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700800 * @param subnetIp Match IP address
801 * @param mplsLabel MPLS label of final destination router
802 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700803 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700804 */
805 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700806 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
807 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700808
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700809 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700810 List<Action> actions = new ArrayList<>();
811
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700812 // If destination SW is the same as the fwd SW, then do not push MPLS
813 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700814
815 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700816 PushMplsAction pushMplsAction = new PushMplsAction();
817 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
818 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700819 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700820
821 actions.add(pushMplsAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700822 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700823 actions.add(decMplsTtlAction);
824 actions.add(setIdAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700825 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700826 else {
827 String fwdToSw = fwdToSws.get(0);
828 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
829 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
830 actions.add(decTtlAction);
831 }
832 else {
833 PushMplsAction pushMplsAction = new PushMplsAction();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700834 SetMplsIdAction setIdAction = new SetMplsIdAction(
835 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700836 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700837 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700838
839 actions.add(pushMplsAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700840 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700841 actions.add(decMplsTtlAction);
842 actions.add(setIdAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700843 }
844 }
Sangho Shin43cee112014-09-25 16:43:34 -0700845
846 GroupAction groupAction = new GroupAction();
847
848 for (String fwdSw : fwdToSws) {
849 groupAction.addSwitch(new Dpid(fwdSw));
850 }
851 actions.add(groupAction);
852
Sangho Shinc8d2f592014-09-30 16:53:57 -0700853 // TODO: Mactch Action Id should be set correctly
Sangho Shin43cee112014-09-25 16:43:34 -0700854 MatchAction matchAction = new MatchAction(new MatchActionId(0),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700855 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700856
Sangho Shin5be3e532014-10-03 17:20:58 -0700857 Operator operator = null;
858 if (modified)
859 operator = Operator.MODIFY;
860 else
861 operator = Operator.ADD;
862
Sangho Shin43cee112014-09-25 16:43:34 -0700863 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700864 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700865
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700866 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700867 getSwId(sw.getDpid().toString()));
868
Sangho Shin5be3e532014-10-03 17:20:58 -0700869 /* TODO: we should check the SWICH REMOVED events */
870 if (sw13 != null) {
871 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700872 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700873 if (entries != null)
874 entries.add(maEntry);
875 else
876 sw13.pushFlow(maEntry);
877 } catch (IOException e) {
878 e.printStackTrace();
879 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700880 }
881
Sangho Shin43cee112014-09-25 16:43:34 -0700882 }
883
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700884 /**
885 * Convert a string DPID to its Switch Id (integer)
Sangho Shinfbc572c2014-10-02 16:37:05 -0700886 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700887 * @param dpid
888 * @return
889 */
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700890 private long getSwId(String dpid) {
891
892 long swId = 0;
893
Sangho Shinbce900e2014-10-07 17:13:23 -0700894 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
895 if (swIdHexStr != null)
896 swId = Integer.decode(swIdHexStr);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700897
898 return swId;
899 }
900
Sangho Shin43cee112014-09-25 16:43:34 -0700901 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700902 * Set MPLS forwarding rules to MPLS table - If the destination is the same
903 * as the next hop to forward packets then, pop the MPLS label according to
904 * PHP rule - Otherwise, just forward packets to next hops using Group
905 * action
Sangho Shinfbc572c2014-10-02 16:37:05 -0700906 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700907 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700908 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700909 * @param fwdSws next hop switches
Sangho Shin43cee112014-09-25 16:43:34 -0700910 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700911 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
912 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -0700913
Sangho Shin43cee112014-09-25 16:43:34 -0700914 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel));
915
916 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700917
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700918 // If the destination is the same as the next hop, then pop MPLS
Sangho Shinc8d2f592014-09-30 16:53:57 -0700919 // Otherwise, just decrease the MPLS TTL.
Sangho Shin463bee52014-09-29 15:14:43 -0700920 if (fwdSws.size() == 1) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700921 String fwdMplsId = getMplsLabel(fwdSws.get(0));
922 if (fwdMplsId.equals(mplsLabel)) {
923 String fwdSw = fwdSws.get(0);
924 if (mplsLabel.equals(getMplsLabel(fwdSw))) {
925 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
926 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700927 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700928
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700929 actions.add(copyTtlInAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700930 actions.add(popAction);
931 actions.add(decNwTtlAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700932 }
933 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700934 else {
935 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
936 actions.add(decMplsTtlAction);
937 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700938 }
Sangho Shin43cee112014-09-25 16:43:34 -0700939 GroupAction groupAction = new GroupAction();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700940 for (String fwdSw : fwdSws)
Sangho Shin43cee112014-09-25 16:43:34 -0700941 groupAction.addSwitch(new Dpid(fwdSw));
942 actions.add(groupAction);
943
944 MatchAction matchAction = new MatchAction(new MatchActionId(0),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700945 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700946
Sangho Shin5be3e532014-10-03 17:20:58 -0700947 Operator operator = null;
948 if (modified)
949 operator = Operator.MODIFY;
950 else
951 operator = Operator.ADD;
952
Sangho Shin43cee112014-09-25 16:43:34 -0700953 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700954 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700955
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700956 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700957 getSwId(sw.getDpid().toString()));
958
Sangho Shin5be3e532014-10-03 17:20:58 -0700959 if (sw13 != null) {
960 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700961 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700962 sw13.pushFlow(maEntry);
963 } catch (IOException e) {
964 e.printStackTrace();
965 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700966 }
967
Sangho Shin43cee112014-09-25 16:43:34 -0700968 }
969
Sangho Shin43cee112014-09-25 16:43:34 -0700970 /**
971 * Debugging function to print out the Match Action Entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700972 *
Sangho Shin43cee112014-09-25 16:43:34 -0700973 * @param maEntry
974 */
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700975 private void printMatchActionOperationEntry(Switch sw,
976 MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -0700977
Sangho Shin0df01982014-09-25 17:11:18 -0700978 StringBuilder logStr = new StringBuilder("In switch " + sw.getDpid() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -0700979
980 MatchAction ma = maEntry.getTarget();
981 Match m = ma.getMatch();
982 List<Action> actions = ma.getActions();
983
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700984 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -0700985 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700986 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -0700987 logStr.append(ip.toString());
988 logStr.append(" then ");
989 }
990 else if (m instanceof MplsMatch) {
991 logStr.append("If the MPLS label matches with ");
992 int mplsLabel = ((MplsMatch) m).getMplsLabel();
993 logStr.append(mplsLabel);
994 logStr.append(" then ");
995 }
996
997 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700998 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -0700999 if (action instanceof CopyTtlInAction) {
1000 logStr.append("copy ttl In, ");
1001 }
1002 else if (action instanceof CopyTtlOutAction) {
1003 logStr.append("copy ttl Out, ");
1004 }
1005 else if (action instanceof DecMplsTtlAction) {
1006 logStr.append("Dec MPLS TTL , ");
1007 }
1008 else if (action instanceof GroupAction) {
1009 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001010 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -07001011 logStr.append(dpids.toString() + ",");
1012
Sangho Shin43cee112014-09-25 16:43:34 -07001013 }
1014 else if (action instanceof PopMplsAction) {
1015 logStr.append("Pop MPLS label, ");
1016 }
1017 else if (action instanceof PushMplsAction) {
1018 logStr.append("Push MPLS label, ");
1019 }
1020 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001021 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -07001022 logStr.append("Set MPLS ID as " + id + ", ");
1023
1024 }
1025 }
1026
1027 log.debug(logStr.toString());
1028
Sangho Shineb083032014-09-22 16:11:34 -07001029 }
1030
1031 /**
1032 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001033 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001034 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001035 * @return MPLS label for the switch
1036 */
1037
Sangho Shin43cee112014-09-25 16:43:34 -07001038 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001039
1040 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001041 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001042 String dpidStr = sw.getDpid().toString();
1043 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001044 mplsLabel = sw.getStringAttribute("nodeSid");
1045 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001046 }
1047 }
1048
Sangho Shineb083032014-09-22 16:11:34 -07001049 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001050 }
1051
Sangho Shineb083032014-09-22 16:11:34 -07001052 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001053 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001054 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001055 * @param addr - subnet address to match
1056 * @param addr1 - IP address to check
1057 * @return true if the IP address matches to the subnet, otherwise false
1058 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001059 public boolean netMatch(String addr, String addr1) { // addr is subnet
1060 // address and addr1 is
1061 // ip address. Function
1062 // will return true, if
1063 // addr1 is within
1064 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001065
1066 String[] parts = addr.split("/");
1067 String ip = parts[0];
1068 int prefix;
1069
1070 if (parts.length < 2) {
1071 prefix = 0;
1072 } else {
1073 prefix = Integer.parseInt(parts[1]);
1074 }
1075
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001076 Inet4Address a = null;
1077 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001078 try {
1079 a = (Inet4Address) InetAddress.getByName(ip);
1080 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001081 } catch (UnknownHostException e) {
1082 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001083
1084 byte[] b = a.getAddress();
1085 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001086 ((b[1] & 0xFF) << 16) |
1087 ((b[2] & 0xFF) << 8) |
1088 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001089
1090 byte[] b1 = a1.getAddress();
1091 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001092 ((b1[1] & 0xFF) << 16) |
1093 ((b1[2] & 0xFF) << 8) |
1094 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001095
1096 int mask = ~((1 << (32 - prefix)) - 1);
1097
1098 if ((ipInt & mask) == (ipInt1 & mask)) {
1099 return true;
1100 }
1101 else {
1102 return false;
1103 }
1104 }
Sangho Shineb083032014-09-22 16:11:34 -07001105
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001106 /**
1107 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001108 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001109 * @param sw - Switch to add the rule
1110 * @param hostIpAddress Destination host IP address
1111 * @param hostMacAddress Destination host MAC address
1112 */
Sangho Shineb083032014-09-22 16:11:34 -07001113 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1114 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1115
1116 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001117
Sangho Shin463bee52014-09-29 15:14:43 -07001118 /**
1119 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001120 *
Sangho Shin463bee52014-09-29 15:14:43 -07001121 * @param ipv4
1122 */
1123 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001124 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001125 }
1126
1127 /**
1128 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001129 *
Sangho Shin463bee52014-09-29 15:14:43 -07001130 * @param destIp Destination address of packets to retrieve
1131 */
1132 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1133
1134 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1135
Sangho Shin61535402014-10-01 11:37:14 -07001136 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001137 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001138 int dest = ip.getDestinationAddress();
1139 IPv4Address ip1 = IPv4Address.of(dest);
1140 IPv4Address ip2 = IPv4Address.of(destIp);
1141 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001142 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001143 }
1144 }
1145 }
1146
1147 return bufferedPackets;
1148 }
1149
Sangho Shin2f263692014-09-15 14:09:41 -07001150}