blob: 918a12f758a863caead0956e7dff8bb73525c7a7 [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 Shinc8d2f592014-09-30 16:53:57 -070057import net.onrc.onos.core.topology.LinkData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070058import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070059import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070060import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070061import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070062import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070063import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070064import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070065import net.onrc.onos.core.util.IPv4Net;
66import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070067
Sangho Shin43cee112014-09-25 16:43:34 -070068import org.json.JSONArray;
69import org.json.JSONException;
Saurav Dasbc594a42014-09-25 20:13:50 -070070import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070071import org.projectfloodlight.openflow.types.IPv4Address;
72import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070075public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070076 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070077
78 private static final Logger log = LoggerFactory
79 .getLogger(SegmentRoutingManager.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070080 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070081 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070082 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070083 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070084
85 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070086 private ArpHandler arpHandler;
87 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070088 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070089 private IThreadPoolService threadPool;
90 private SingletonTask discoveryTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070091 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -070092
Sangho Shinfbc572c2014-10-02 16:37:05 -070093 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin5be3e532014-10-03 17:20:58 -070094 private HashSet<LinkData> topologyLinks;
95 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shinfbc572c2014-10-02 16:37:05 -070096
Sangho Shin2f263692014-09-15 14:09:41 -070097 @Override
98 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
99 // TODO Auto-generated method stub
100 return null;
101 }
102
103 @Override
104 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
105 // TODO Auto-generated method stub
106 return null;
107 }
108
109 @Override
110 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
111 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
112
113 l.add(IFloodlightProviderService.class);
114 l.add(IConfigInfoService.class);
115 l.add(ITopologyService.class);
116 l.add(IPacketService.class);
117 l.add(IFlowPusherService.class);
118 l.add(ITopologyService.class);
119
120 return l;
121
122 }
123
124 @Override
125 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700126 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700127 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700128 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700129 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700130 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700131 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700132 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700133 mutableTopology = topologyService.getTopology();
134 topologyService.addListener(this, false);
Sangho Shin61535402014-10-01 11:37:14 -0700135 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700136 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700137 topologyLinks = new HashSet<LinkData>();
138 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin2f263692014-09-15 14:09:41 -0700139
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700140 this.packetService = context.getServiceImpl(IPacketService.class);
141 packetService.registerPacketListener(this);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700142
Sangho Shin2f263692014-09-15 14:09:41 -0700143 }
144
145 @Override
146 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700147 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700148
Sangho Shinc8d2f592014-09-30 16:53:57 -0700149 discoveryTask = new SingletonTask(ses, new Runnable() {
150 @Override
151 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700152 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700153 }
154 });
Sangho Shin2f263692014-09-15 14:09:41 -0700155 }
156
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700157 @Override
158 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700159 if (payload.getEtherType() == Ethernet.TYPE_ARP)
160 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700161 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700162 addPacket((IPv4) payload.getPayload());
163 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
164 icmpHandler.processPacketIn(sw, inPort, payload);
165 else
166 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700167 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700168 else {
169 log.debug("{}", payload.toString());
170 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700171 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700172
Sangho Shin2f263692014-09-15 14:09:41 -0700173 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700174 * Update ARP Cache using ARP packets It is used to set destination MAC
175 * address to forward packets to known hosts. But, it will be replace with
176 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700177 *
Sangho Shin2f263692014-09-15 14:09:41 -0700178 * @param arp APR packets to use for updating ARP entries
179 */
180 public void updateArpCache(ARP arp) {
181
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700182 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
183 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700184 // TODO: Need to check the duplication
185 arpEntries.add(arpEntry);
186 }
187
188 /**
189 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700190 *
Sangho Shin2f263692014-09-15 14:09:41 -0700191 * @param destinationAddress IP address to get MAC address
192 * @return MAC Address to given IP address
193 */
194 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
195
196 // Can't we get the host IP address from the TopologyService ??
197
198 Iterator<ArpEntry> iterator = arpEntries.iterator();
199
200 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
201 byte[] ipAddressInByte = ipAddress.getBytes();
202
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700203 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700204 ArpEntry arpEntry = iterator.next();
205 byte[] address = arpEntry.targetIpAddress;
206
207 IPv4Address a = IPv4Address.of(address);
208 IPv4Address b = IPv4Address.of(ipAddressInByte);
209
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700210 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700211 log.debug("Found an arp entry");
212 return arpEntry.targetMacAddress;
213 }
214 }
215
216 return null;
217 }
218
Sangho Shineb083032014-09-22 16:11:34 -0700219 /**
220 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700221 *
Sangho Shineb083032014-09-22 16:11:34 -0700222 * @param destinationAddress
223 * @param sw
224 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700225 *
Sangho Shineb083032014-09-22 16:11:34 -0700226 */
227 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
228 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
229 }
Sangho Shin2f263692014-09-15 14:09:41 -0700230
231 /**
232 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700233 *
Sangho Shin2f263692014-09-15 14:09:41 -0700234 */
235 private class ArpEntry {
236
237 byte[] targetMacAddress;
238 byte[] targetIpAddress;
239
240 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
241 this.targetMacAddress = macAddress;
242 this.targetIpAddress = ipAddress;
243 }
Sangho Shin2f263692014-09-15 14:09:41 -0700244 }
Sangho Shineb083032014-09-22 16:11:34 -0700245
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700246 /**
247 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700248 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700249 * @param topologyEvents the generated Topology Events
250 * @see TopologyEvents
251 */
252 public void topologyEvents(TopologyEvents topologyEvents)
253 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700254 topologyEventQueue.add(topologyEvents);
255 discoveryTask.reschedule(500, TimeUnit.MILLISECONDS);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700256
Sangho Shin5be3e532014-10-03 17:20:58 -0700257 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700258
Sangho Shinc8d2f592014-09-30 16:53:57 -0700259
Sangho Shin5be3e532014-10-03 17:20:58 -0700260 private void handleTopologyChangeEvents() {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700261
Sangho Shin5be3e532014-10-03 17:20:58 -0700262 while (!topologyEventQueue.isEmpty()) {
263 TopologyEvents topologyEvents = topologyEventQueue.poll();
264
265 Collection<LinkData> linkEntriesAdded =
266 topologyEvents.getAddedLinkDataEntries();
267 if (!linkEntriesAdded.isEmpty()) {
268 processLinkAdd(linkEntriesAdded);
269 }
270
271 Collection<PortData> PortEntriesAdded =
272 topologyEvents.getAddedPortDataEntries();
273 if (linkEntriesAdded != null) {
274 processPortAdd(PortEntriesAdded);
275 }
276
277 Collection<PortData> portEntries =
278 topologyEvents.getRemovedPortDataEntries();
279 if (!portEntries.isEmpty()) {
280 processPortRemoval(portEntries);
281 }
282
283 Collection<LinkData> linkEntriesRemoved =
284 topologyEvents.getRemovedLinkDataEntries();
285 if (!linkEntriesRemoved.isEmpty()) {
286 processLinkRemoval(linkEntriesRemoved);
287 }
288
289 Collection<SwitchData> switchRemoved =
290 topologyEvents.getRemovedSwitchDataEntries();
291 if (!switchRemoved.isEmpty()) {
292 processSwitchRemoved(switchRemoved);
293 }
294
Sangho Shin61535402014-10-01 11:37:14 -0700295 }
296 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700297
Sangho Shin5be3e532014-10-03 17:20:58 -0700298 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
299 /* TODO: We should remove only the links of the switch removed */
300 topologyLinks.clear();
301 }
302
Sangho Shin61535402014-10-01 11:37:14 -0700303 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700304 * Report ports newly added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700305 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700306 * @param portEntries
307 */
308 private void processPortAdd(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700309 // TODO: do we need to add ports slowly?
310 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700311 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700312
Sangho Shinfbc572c2014-10-02 16:37:05 -0700313 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700314 getSwId(port.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700315 sw.addPortToGroups(port.getPortNumber());
316
317 log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700318 }
319 }
320
321 /**
322 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shinfbc572c2014-10-02 16:37:05 -0700323 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700324 * @param linkEntries
325 */
326 private void processLinkAdd(Collection<LinkData> linkEntries) {
327
Sangho Shin5be3e532014-10-03 17:20:58 -0700328 boolean linkRecovered = false;
329
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700330 // TODO: How to determine this link was broken before and back now
331 // If so, we need to ad the link slowly...
332 // Or, just add any new or restored link slowly ???
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700333 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700334
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700335 SwitchPort srcPort = link.getSrc();
336 SwitchPort dstPort = link.getDst();
337
Sangho Shinfbc572c2014-10-02 16:37:05 -0700338 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700339 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700340 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700341 getSwId(srcPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700342
Sangho Shinfbc572c2014-10-02 16:37:05 -0700343 srcSw.addPortToGroups(srcPort.getPortNumber());
344 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700345
346
347 if (!topologyLinks.contains(link)) {
348 topologyLinks.add(link);
349 }
350 else {
351 linkRecovered = true;
352 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700353 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700354 if (linkRecovered) {
355 populateEcmpRoutingRules(true);
356 }
357 else {
358 populateEcmpRoutingRules(false);
359 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700360 }
361
362 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700363 * Check if all links are gone b/w the two switches. If all links are gone,
364 * then we need to recalculate the path. Otherwise, just report link failure
365 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700366 *
Sangho Shin61535402014-10-01 11:37:14 -0700367 * @param linkEntries
368 */
369 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700370 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700371 SwitchPort srcPort = link.getSrc();
372 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700373
Sangho Shinfbc572c2014-10-02 16:37:05 -0700374 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700375 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700376 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700377 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700378
379 // TODO: Why do we get null for the master switch??
380 if (srcSw != null)
381 srcSw.removePortFromGroups(srcPort.getPortNumber());
382 if (dstSw != null)
383 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700384
385 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
386 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700387 //modifyEcmpRoutingRules(link);
388 populateEcmpRoutingRules(true);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700389 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700390 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700391 }
392 }
Sangho Shin61535402014-10-01 11:37:14 -0700393 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700394
Sangho Shin61535402014-10-01 11:37:14 -0700395 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700396 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700397 *
Sangho Shin61535402014-10-01 11:37:14 -0700398 * @param portEntries
399 */
400 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700401 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700402 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700403
Sangho Shinfbc572c2014-10-02 16:37:05 -0700404 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700405 getSwId(port.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700406 if (sw != null)
407 sw.removePortFromGroups(port.getPortNumber());
408 log.debug("Remove port {} from switch {}", port, dpid);
Sangho Shin61535402014-10-01 11:37:14 -0700409 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700410 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700411
412 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700413 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700414 *
Sangho Shin1aa93542014-09-22 09:49:44 -0700415 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700416 private void populateEcmpRoutingRules(boolean modified) {
417 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700418 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700419 for (Switch sw : switches) {
420 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700421 graphs.put(sw, ecmpSPG);
422 //log.debug("ECMPShortestPathGraph is computed for switch {}",
423 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700424 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
425 if (modified) {
426 log.debug("Modify the rules for {}" , sw.getDpid());
427 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700428 }
429 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700430
Sangho Shinfbc572c2014-10-02 16:37:05 -0700431 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700432 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700433
Sangho Shinfbc572c2014-10-02 16:37:05 -0700434 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
435 ecmpSPG.getAllLearnedSwitchesAndVia();
436 for (Integer itrIdx : switchVia.keySet()) {
437 //log.debug("ECMPShortestPathGraph:Switches learned in "
438 // + "Iteration{} from switch {}:",
439 // itrIdx,
440 // HexString.toHexString(sw.getDpid().value()));
441 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
442 switchVia.get(itrIdx);
443 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700444 //log.debug("ECMPShortestPathGraph:****switch {} via:",
445 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700446 String destSw = sw.getDpid().toString();
447 List<String> fwdToSw = new ArrayList<String>();
448
Sangho Shinfbc572c2014-10-02 16:37:05 -0700449 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700450 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700451 if (via.isEmpty()) {
452 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700453 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700454 else {
455 fwdToSw.add(via.get(0).toString());
456 }
Sangho Shin43cee112014-09-25 16:43:34 -0700457 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700458 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700459 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700460
461 // Send Barrier Message and make sure all rules are set
462 // before we set the rules to next routers
463 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
464 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700465 if (sw13 != null) {
466 try {
467 OFBarrierReplyFuture replyFuture = sw13.sendBarrier();
468 replyFuture.get(10, TimeUnit.SECONDS);
469 } catch (IOException e) {
470 e.printStackTrace();
471 } catch (InterruptedException | ExecutionException | TimeoutException e) {
472 log.error("Barrier message not received for sw: {}", sw.getDpid());
473 e.printStackTrace();
474 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700475 }
476 }
477
478 }
479
480
481 private class SwitchPair {
482 private Switch src;
483 private Switch dst;
484
485 public SwitchPair(Switch src, Switch dst) {
486 this.src = src;
487 this.dst = dst;
488 }
489
490 public Switch getSource() {
491 return src;
492 }
493
494 public Switch getDestination() {
495 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700496 }
Sangho Shin43cee112014-09-25 16:43:34 -0700497 }
498
499 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700500 * Modify the routing rules for the lost links
501 * - Recompute the path if the link failed is included in the path
502 * (including src and dest).
503 *
504 * @param newLink
505 */
506 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
507
508 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700509 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700510
511 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
512 Switch rootSw = ecmpSPG.getRootSwitch();
513 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
514 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
515 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
516 for (Switch destSw: p.keySet()) {
517 ArrayList<Path> path = p.get(destSw);
518 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700519 boolean found = false;
520 for (SwitchPair pair: linksToRecompute) {
521 if (pair.getSource().getDpid() == rootSw.getDpid() &&
522 pair.getSource().getDpid() == destSw.getDpid()) {
523 found = true;
524 }
525 }
526 if (!found) {
527 linksToRecompute.add(new SwitchPair(rootSw, destSw));
528 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700529 }
530 }
531 }
532 }
533
534 // Recompute the path for the specific route
535 for (SwitchPair pair: linksToRecompute) {
536
537 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
538 // TODO : we need the following function
539 //ECMPShortestPathGraph ecmpSPG =
540 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
541 ECMPShortestPathGraph ecmpSPG =
542 new ECMPShortestPathGraph(pair.getSource());
543 // TODO: we need to use different function to MODIFY the rules
Sangho Shin5be3e532014-10-03 17:20:58 -0700544 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700545 }
546 }
547
548 /**
549 * Check if the path is affected from the link removed
550 *
551 * @param path Path to check
552 * @param linkRemoved link removed
553 * @return true if the path contains the link removed
554 */
555 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
556
557 for (Path ppp: path) {
558 // TODO: need to check if this is a bidirectional or
559 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700560 for (LinkData link: ppp) {
561 //if (link.equals(linkRemoved))
562 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
563 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
564 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700565 }
566 }
567
568 return false;
569 }
570
571 /**
572 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700573 * Set routing rules in targetSw {forward packets to fwdToSw switches in
574 * order to send packets to destSw} - If the target switch is an edge router
575 * and final destnation switch is also an edge router, then set IP
576 * forwarding rules to subnets - If only the target switch is an edge
577 * router, then set IP forwarding rule to the transit router loopback IP
578 * address - If the target is a transit router, then just set the MPLS
579 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700580 *
Sangho Shin43cee112014-09-25 16:43:34 -0700581 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700582 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700583 * @param fwdToSw next hop switches
584 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700585 private void setRoutingRule(Switch targetSw, String destSw, List<String> fwdToSw,
586 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700587
Sangho Shin43cee112014-09-25 16:43:34 -0700588 if (fwdToSw.isEmpty()) {
589 fwdToSw.add(destSw);
590 }
591
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700592 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700593 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
594 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700595 // We assume that there is at least one transit router b/w edge
596 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700597 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
598 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700599 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700600 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700601
Sangho Shin43cee112014-09-25 16:43:34 -0700602 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700603 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
604 null, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700605 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700606 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700607 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700608 // We assume that there is at least one transit router b/w edge
609 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700610 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
611 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700612 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
613 null, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700614 }
615 // if it is a transit router, then set rules in the MPLS table
616 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700617 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700618 }
619
620 }
621
Sangho Shinfbc572c2014-10-02 16:37:05 -0700622 /**
623 * Set IP forwarding rule to the gateway of each subnet of switches
624 *
625 * @param targetSw Switch to set rules
626 * @param subnets subnet information
627 * @param mplsLabel destination MPLS label
628 * @param fwdToSw router to forward packets to
629 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700630 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700631 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700632
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700633 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700634 new ArrayList<MatchActionOperationEntry>();
635
636 try {
637 JSONArray arry = new JSONArray(subnets);
638 for (int i = 0; i < arry.length(); i++) {
639 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700640 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
641 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700642 }
643 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700644 e.printStackTrace();
645 }
646
647 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700648 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700649 getSwId(targetSw.getDpid().toString()));
650
651 try {
652 sw13.pushFlows(entries);
653 } catch (IOException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700654 e.printStackTrace();
655 }
656 }
657
658 }
659
Sangho Shin43cee112014-09-25 16:43:34 -0700660 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700661 * Check if the switch is the edge router or not If any subnet information
662 * is defined in the config file, the we assume it is an edge router
Sangho Shinfbc572c2014-10-02 16:37:05 -0700663 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700664 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700665 * @return true if it is an edge router, otherwise false
666 */
667 private boolean IsEdgeRouter(String dpid) {
668
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700669 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700670 String dpidStr = sw.getDpid().toString();
671 if (dpid.equals(dpidStr)) {
672 String subnetInfo = sw.getStringAttribute("subnets");
673 if (subnetInfo == null || subnetInfo.equals("[]")) {
674 return false;
675 }
676 else
677 return true;
678 }
679 }
680
681 return false;
682 }
683
684 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700685 * Set IP forwarding rule - If the destination is the next hop, then do not
686 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
687 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700688 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700689 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700690 * @param subnetIp Match IP address
691 * @param mplsLabel MPLS label of final destination router
692 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700693 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700694 */
695 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700696 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
697 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700698
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700699 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700700 List<Action> actions = new ArrayList<>();
701
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700702 // If destination SW is the same as the fwd SW, then do not push MPLS
703 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700704
705 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700706 PushMplsAction pushMplsAction = new PushMplsAction();
707 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
708 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700709 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700710
711 actions.add(pushMplsAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700712 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700713 actions.add(decMplsTtlAction);
714 actions.add(setIdAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700715 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700716 else {
717 String fwdToSw = fwdToSws.get(0);
718 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
719 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
720 actions.add(decTtlAction);
721 }
722 else {
723 PushMplsAction pushMplsAction = new PushMplsAction();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700724 SetMplsIdAction setIdAction = new SetMplsIdAction(
725 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700726 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700727 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700728
729 actions.add(pushMplsAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700730 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700731 actions.add(decMplsTtlAction);
732 actions.add(setIdAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700733 }
734 }
Sangho Shin43cee112014-09-25 16:43:34 -0700735
736 GroupAction groupAction = new GroupAction();
737
738 for (String fwdSw : fwdToSws) {
739 groupAction.addSwitch(new Dpid(fwdSw));
740 }
741 actions.add(groupAction);
742
Sangho Shinc8d2f592014-09-30 16:53:57 -0700743 // TODO: Mactch Action Id should be set correctly
Sangho Shin43cee112014-09-25 16:43:34 -0700744 MatchAction matchAction = new MatchAction(new MatchActionId(0),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700745 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700746
Sangho Shin5be3e532014-10-03 17:20:58 -0700747 Operator operator = null;
748 if (modified)
749 operator = Operator.MODIFY;
750 else
751 operator = Operator.ADD;
752
Sangho Shin43cee112014-09-25 16:43:34 -0700753 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700754 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700755
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700756 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700757 getSwId(sw.getDpid().toString()));
758
Sangho Shin5be3e532014-10-03 17:20:58 -0700759 /* TODO: we should check the SWICH REMOVED events */
760 if (sw13 != null) {
761 try {
762 printMatchActionOperationEntry(sw, maEntry);
763 if (entries != null)
764 entries.add(maEntry);
765 else
766 sw13.pushFlow(maEntry);
767 } catch (IOException e) {
768 e.printStackTrace();
769 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700770 }
771
Sangho Shin43cee112014-09-25 16:43:34 -0700772 }
773
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700774 /**
775 * Convert a string DPID to its Switch Id (integer)
Sangho Shinfbc572c2014-10-02 16:37:05 -0700776 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700777 * @param dpid
778 * @return
779 */
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700780 private long getSwId(String dpid) {
781
782 long swId = 0;
783
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700784 String swIdStr = dpid.substring(dpid.lastIndexOf(":") + 1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700785 if (swIdStr != null)
786 swId = Integer.parseInt(swIdStr);
787
788 return swId;
789 }
790
Sangho Shin43cee112014-09-25 16:43:34 -0700791 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700792 * Set MPLS forwarding rules to MPLS table - If the destination is the same
793 * as the next hop to forward packets then, pop the MPLS label according to
794 * PHP rule - Otherwise, just forward packets to next hops using Group
795 * action
Sangho Shinfbc572c2014-10-02 16:37:05 -0700796 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700797 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700798 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700799 * @param fwdSws next hop switches
Sangho Shin43cee112014-09-25 16:43:34 -0700800 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700801 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
802 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -0700803
Sangho Shin43cee112014-09-25 16:43:34 -0700804 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel));
805
806 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700807
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700808 // If the destination is the same as the next hop, then pop MPLS
Sangho Shinc8d2f592014-09-30 16:53:57 -0700809 // Otherwise, just decrease the MPLS TTL.
Sangho Shin463bee52014-09-29 15:14:43 -0700810 if (fwdSws.size() == 1) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700811 String fwdMplsId = getMplsLabel(fwdSws.get(0));
812 if (fwdMplsId.equals(mplsLabel)) {
813 String fwdSw = fwdSws.get(0);
814 if (mplsLabel.equals(getMplsLabel(fwdSw))) {
815 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
816 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700817 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700818
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700819 actions.add(copyTtlInAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700820 actions.add(popAction);
821 actions.add(decNwTtlAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700822 }
823 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700824 else {
825 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
826 actions.add(decMplsTtlAction);
827 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700828 }
Sangho Shin43cee112014-09-25 16:43:34 -0700829 GroupAction groupAction = new GroupAction();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700830 for (String fwdSw : fwdSws)
Sangho Shin43cee112014-09-25 16:43:34 -0700831 groupAction.addSwitch(new Dpid(fwdSw));
832 actions.add(groupAction);
833
834 MatchAction matchAction = new MatchAction(new MatchActionId(0),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700835 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700836
Sangho Shin5be3e532014-10-03 17:20:58 -0700837 Operator operator = null;
838 if (modified)
839 operator = Operator.MODIFY;
840 else
841 operator = Operator.ADD;
842
Sangho Shin43cee112014-09-25 16:43:34 -0700843 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700844 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700845
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700846 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700847 getSwId(sw.getDpid().toString()));
848
Sangho Shin5be3e532014-10-03 17:20:58 -0700849 if (sw13 != null) {
850 try {
851 printMatchActionOperationEntry(sw, maEntry);
852 sw13.pushFlow(maEntry);
853 } catch (IOException e) {
854 e.printStackTrace();
855 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700856 }
857
Sangho Shin43cee112014-09-25 16:43:34 -0700858 }
859
Sangho Shin43cee112014-09-25 16:43:34 -0700860 /**
861 * Debugging function to print out the Match Action Entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700862 *
Sangho Shin43cee112014-09-25 16:43:34 -0700863 * @param maEntry
864 */
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700865 private void printMatchActionOperationEntry(Switch sw,
866 MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -0700867
Sangho Shin0df01982014-09-25 17:11:18 -0700868 StringBuilder logStr = new StringBuilder("In switch " + sw.getDpid() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -0700869
870 MatchAction ma = maEntry.getTarget();
871 Match m = ma.getMatch();
872 List<Action> actions = ma.getActions();
873
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700874 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -0700875 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700876 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -0700877 logStr.append(ip.toString());
878 logStr.append(" then ");
879 }
880 else if (m instanceof MplsMatch) {
881 logStr.append("If the MPLS label matches with ");
882 int mplsLabel = ((MplsMatch) m).getMplsLabel();
883 logStr.append(mplsLabel);
884 logStr.append(" then ");
885 }
886
887 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700888 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -0700889 if (action instanceof CopyTtlInAction) {
890 logStr.append("copy ttl In, ");
891 }
892 else if (action instanceof CopyTtlOutAction) {
893 logStr.append("copy ttl Out, ");
894 }
895 else if (action instanceof DecMplsTtlAction) {
896 logStr.append("Dec MPLS TTL , ");
897 }
898 else if (action instanceof GroupAction) {
899 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700900 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -0700901 logStr.append(dpids.toString() + ",");
902
Sangho Shin43cee112014-09-25 16:43:34 -0700903 }
904 else if (action instanceof PopMplsAction) {
905 logStr.append("Pop MPLS label, ");
906 }
907 else if (action instanceof PushMplsAction) {
908 logStr.append("Push MPLS label, ");
909 }
910 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700911 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -0700912 logStr.append("Set MPLS ID as " + id + ", ");
913
914 }
915 }
916
917 log.debug(logStr.toString());
918
Sangho Shineb083032014-09-22 16:11:34 -0700919 }
920
921 /**
922 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -0700923 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700924 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -0700925 * @return MPLS label for the switch
926 */
927
Sangho Shin43cee112014-09-25 16:43:34 -0700928 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -0700929
930 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700931 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700932 String dpidStr = sw.getDpid().toString();
933 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -0700934 mplsLabel = sw.getStringAttribute("nodeSid");
935 break;
Sangho Shin1aa93542014-09-22 09:49:44 -0700936 }
937 }
938
Sangho Shineb083032014-09-22 16:11:34 -0700939 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -0700940 }
941
Sangho Shineb083032014-09-22 16:11:34 -0700942 /**
Sangho Shin1aa93542014-09-22 09:49:44 -0700943 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -0700944 *
Sangho Shin1aa93542014-09-22 09:49:44 -0700945 * @param addr - subnet address to match
946 * @param addr1 - IP address to check
947 * @return true if the IP address matches to the subnet, otherwise false
948 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700949 public boolean netMatch(String addr, String addr1) { // addr is subnet
950 // address and addr1 is
951 // ip address. Function
952 // will return true, if
953 // addr1 is within
954 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -0700955
956 String[] parts = addr.split("/");
957 String ip = parts[0];
958 int prefix;
959
960 if (parts.length < 2) {
961 prefix = 0;
962 } else {
963 prefix = Integer.parseInt(parts[1]);
964 }
965
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700966 Inet4Address a = null;
967 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -0700968 try {
969 a = (Inet4Address) InetAddress.getByName(ip);
970 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700971 } catch (UnknownHostException e) {
972 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700973
974 byte[] b = a.getAddress();
975 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700976 ((b[1] & 0xFF) << 16) |
977 ((b[2] & 0xFF) << 8) |
978 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -0700979
980 byte[] b1 = a1.getAddress();
981 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700982 ((b1[1] & 0xFF) << 16) |
983 ((b1[2] & 0xFF) << 8) |
984 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -0700985
986 int mask = ~((1 << (32 - prefix)) - 1);
987
988 if ((ipInt & mask) == (ipInt1 & mask)) {
989 return true;
990 }
991 else {
992 return false;
993 }
994 }
Sangho Shineb083032014-09-22 16:11:34 -0700995
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700996 /**
997 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -0700998 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700999 * @param sw - Switch to add the rule
1000 * @param hostIpAddress Destination host IP address
1001 * @param hostMacAddress Destination host MAC address
1002 */
Sangho Shineb083032014-09-22 16:11:34 -07001003 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1004 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1005
1006 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001007
Sangho Shin463bee52014-09-29 15:14:43 -07001008 /**
1009 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001010 *
Sangho Shin463bee52014-09-29 15:14:43 -07001011 * @param ipv4
1012 */
1013 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001014 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001015 }
1016
1017 /**
1018 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001019 *
Sangho Shin463bee52014-09-29 15:14:43 -07001020 * @param destIp Destination address of packets to retrieve
1021 */
1022 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1023
1024 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1025
Sangho Shin61535402014-10-01 11:37:14 -07001026 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001027 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001028 int dest = ip.getDestinationAddress();
1029 IPv4Address ip1 = IPv4Address.of(dest);
1030 IPv4Address ip2 = IPv4Address.of(destIp);
1031 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001032 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001033 }
1034 }
1035 }
1036
1037 return bufferedPackets;
1038 }
1039
Sangho Shin2f263692014-09-15 14:09:41 -07001040}