blob: fca1dfbe0c452a9dffab794f020eb3633350ddbe [file] [log] [blame]
Sangho Shin2f263692014-09-15 14:09:41 -07001package net.onrc.onos.apps.segmentrouting;
2
Sangho Shin9c0f4c32014-09-26 16:02:38 -07003import java.io.IOException;
Sangho Shin1aa93542014-09-22 09:49:44 -07004import java.net.Inet4Address;
5import java.net.InetAddress;
6import java.net.UnknownHostException;
Sangho Shin2f263692014-09-15 14:09:41 -07007import java.util.ArrayList;
8import java.util.Collection;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -07009import java.util.HashMap;
Sangho Shin5be3e532014-10-03 17:20:58 -070010import java.util.HashSet;
Sangho Shin2f263692014-09-15 14:09:41 -070011import java.util.Iterator;
12import java.util.List;
13import java.util.Map;
Sangho Shin5be3e532014-10-03 17:20:58 -070014import java.util.Set;
Sangho Shin61535402014-10-01 11:37:14 -070015import java.util.concurrent.ConcurrentLinkedQueue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070016import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070017import java.util.concurrent.ScheduledExecutorService;
18import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070019import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070020
21import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070022import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070023import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070024import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070025import net.floodlightcontroller.core.module.FloodlightModuleContext;
26import net.floodlightcontroller.core.module.FloodlightModuleException;
27import net.floodlightcontroller.core.module.IFloodlightModule;
28import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070029import net.floodlightcontroller.core.util.SingletonTask;
30import net.floodlightcontroller.threadpool.IThreadPoolService;
Sangho Shin15273b62014-10-16 22:22:05 -070031import net.floodlightcontroller.util.MACAddress;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070032import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070033import net.onrc.onos.api.packet.IPacketService;
34import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070035import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070036import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070037import net.onrc.onos.core.matchaction.MatchAction;
38import net.onrc.onos.core.matchaction.MatchActionId;
39import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070040import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070041import net.onrc.onos.core.matchaction.action.Action;
42import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
43import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
44import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
45import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
46import net.onrc.onos.core.matchaction.action.GroupAction;
47import net.onrc.onos.core.matchaction.action.PopMplsAction;
48import net.onrc.onos.core.matchaction.action.PushMplsAction;
49import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070050import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070051import net.onrc.onos.core.matchaction.match.Match;
52import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070053import net.onrc.onos.core.matchaction.match.PacketMatch;
54import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070055import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070056import net.onrc.onos.core.packet.Ethernet;
57import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070058import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070059import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070060import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070061import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070062import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070063import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070064import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070065import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070066import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070067import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070068import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070069import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070070import net.onrc.onos.core.util.IPv4Net;
71import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070072
Sangho Shin43cee112014-09-25 16:43:34 -070073import org.json.JSONArray;
74import org.json.JSONException;
Saurav Dasa962a692014-10-17 14:52:38 -070075import org.projectfloodlight.openflow.protocol.OFBarrierReply;
Saurav Dasbc594a42014-09-25 20:13:50 -070076import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070077import org.projectfloodlight.openflow.types.IPv4Address;
78import org.slf4j.Logger;
79import org.slf4j.LoggerFactory;
80
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070081public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070082 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070083
84 private static final Logger log = LoggerFactory
85 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070086
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -070087 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070088 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070089 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070090 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070091
92 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070093 private ArpHandler arpHandler;
94 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070095 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070096 private IThreadPoolService threadPool;
97 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -070098 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -070099 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700100 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700101
Sangho Shinfbc572c2014-10-02 16:37:05 -0700102 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700103 private HashMap<String, LinkData> linksDown;
104 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700105 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shin15273b62014-10-16 22:22:05 -0700106 private HashMap<Integer, HashMap<String, PolicyRouteInfo>> stitchInfo;
107 private HashMap<Integer, HashMap<String, Integer>> tunnelGroupMap;
Sangho Shinbb2b8362014-10-17 21:07:16 -0700108 private HashMap<Integer, HashMap<PacketMatch, Integer>> policyMap;
109
110 private int testMode = 0;
Sangho Shinbce900e2014-10-07 17:13:23 -0700111
112 private int numOfEvents = 0;
113 private int numOfEventProcess = 0;
114 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700115 private long matchActionId = 0L;
Sangho Shin23f898d2014-10-13 16:54:00 -0700116 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700117 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700118
Sangho Shinbb2b8362014-10-17 21:07:16 -0700119 private final int POLICY_ADD = 1;
120 private final int POLICY_REMOVE = 2;
121
Sangho Shin2f263692014-09-15 14:09:41 -0700122 @Override
123 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
124 // TODO Auto-generated method stub
125 return null;
126 }
127
128 @Override
129 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
130 // TODO Auto-generated method stub
131 return null;
132 }
133
134 @Override
135 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
136 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
137
138 l.add(IFloodlightProviderService.class);
139 l.add(IConfigInfoService.class);
140 l.add(ITopologyService.class);
141 l.add(IPacketService.class);
142 l.add(IFlowPusherService.class);
143 l.add(ITopologyService.class);
144
145 return l;
146
147 }
148
149 @Override
150 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700151 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700152 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700153 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700154 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700155 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700156 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700157 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700158 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700159 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700160 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700161 linksDown = new HashMap<String, LinkData>();
162 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700163 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700164 stitchInfo = new HashMap<Integer, HashMap<String, PolicyRouteInfo>>();
165 packetService = context.getServiceImpl(IPacketService.class);
166 tunnelGroupMap = new HashMap<Integer, HashMap<String, Integer>>();
Sangho Shinbb2b8362014-10-17 21:07:16 -0700167 policyMap = new HashMap<Integer, HashMap<PacketMatch, Integer>>();
Sangho Shin2f263692014-09-15 14:09:41 -0700168
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700169 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700170 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700171
Sangho Shin99918bd2014-10-08 15:52:35 -0700172
Sangho Shin2f263692014-09-15 14:09:41 -0700173 }
174
175 @Override
176 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700177 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700178
Sangho Shinc8d2f592014-09-30 16:53:57 -0700179 discoveryTask = new SingletonTask(ses, new Runnable() {
180 @Override
181 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700182 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700183 }
184 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700185
186 linkAddTask = new SingletonTask(ses, new Runnable() {
187 @Override
188 public void run() {
189 delayedAddLink();
190 }
191 });
192
Sangho Shin15273b62014-10-16 22:22:05 -0700193 testTask = new SingletonTask(ses, new Runnable() {
194 @Override
195 public void run() {
196 runTest();
197 }
198 });
199
Sangho Shinbb2b8362014-10-17 21:07:16 -0700200 //policy routing test task
201 testMode = POLICY_ADD;
202 testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700203 }
204
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700205 @Override
206 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700207 if (payload.getEtherType() == Ethernet.TYPE_ARP)
208 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700209 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700210 addPacket((IPv4) payload.getPayload());
211 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
212 icmpHandler.processPacketIn(sw, inPort, payload);
213 else
214 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700215 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700216 else {
217 log.debug("{}", payload.toString());
218 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700219 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700220
Sangho Shin2f263692014-09-15 14:09:41 -0700221 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700222 * Update ARP Cache using ARP packets It is used to set destination MAC
223 * address to forward packets to known hosts. But, it will be replace with
224 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700225 *
Sangho Shin2f263692014-09-15 14:09:41 -0700226 * @param arp APR packets to use for updating ARP entries
227 */
228 public void updateArpCache(ARP arp) {
229
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700230 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
231 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700232 // TODO: Need to check the duplication
233 arpEntries.add(arpEntry);
234 }
235
236 /**
237 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700238 *
Sangho Shin2f263692014-09-15 14:09:41 -0700239 * @param destinationAddress IP address to get MAC address
240 * @return MAC Address to given IP address
241 */
242 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
243
244 // Can't we get the host IP address from the TopologyService ??
245
246 Iterator<ArpEntry> iterator = arpEntries.iterator();
247
248 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
249 byte[] ipAddressInByte = ipAddress.getBytes();
250
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700251 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700252 ArpEntry arpEntry = iterator.next();
253 byte[] address = arpEntry.targetIpAddress;
254
255 IPv4Address a = IPv4Address.of(address);
256 IPv4Address b = IPv4Address.of(ipAddressInByte);
257
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700258 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700259 log.debug("Found an arp entry");
260 return arpEntry.targetMacAddress;
261 }
262 }
263
264 return null;
265 }
266
Sangho Shineb083032014-09-22 16:11:34 -0700267 /**
268 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700269 *
Sangho Shineb083032014-09-22 16:11:34 -0700270 * @param destinationAddress
271 * @param sw
272 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700273 *
Sangho Shineb083032014-09-22 16:11:34 -0700274 */
275 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
276 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
277 }
Sangho Shin2f263692014-09-15 14:09:41 -0700278
279 /**
280 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700281 *
Sangho Shin2f263692014-09-15 14:09:41 -0700282 */
283 private class ArpEntry {
284
285 byte[] targetMacAddress;
286 byte[] targetIpAddress;
287
288 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
289 this.targetMacAddress = macAddress;
290 this.targetIpAddress = ipAddress;
291 }
Sangho Shin2f263692014-09-15 14:09:41 -0700292 }
Sangho Shineb083032014-09-22 16:11:34 -0700293
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700294 /**
295 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700296 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700297 * @param topologyEvents the generated Topology Events
298 * @see TopologyEvents
299 */
300 public void topologyEvents(TopologyEvents topologyEvents)
301 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700302 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700303 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700304 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700305
Sangho Shin23f898d2014-10-13 16:54:00 -0700306 /**
307 * Process the multiple topology events with some delay (100MS at most for now)
308 *
309 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700310 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700311 numOfEventProcess ++;
312
Sangho Shin51625342014-10-17 09:30:48 -0700313 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
314 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
315 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
316 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
317 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
318 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
319 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700320
Sangho Shin5be3e532014-10-03 17:20:58 -0700321 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700322 // We should handle the events in the order of when they happen
323 // TODO: We need to simulate the final results of multiple events
324 // and shoot only the final state.
325 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
326 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700327
Sangho Shin5be3e532014-10-03 17:20:58 -0700328 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700329
330 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
331 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
332 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
333 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
334 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
335 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
336 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
337
338 linkEntriesAddedAll.addAll(linkEntriesAdded);
339 portEntriesAddedAll.addAll(portEntriesAdded);
340 portEntriesRemovedAll.addAll(portEntriesRemoved);
341 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
342 switchAddedAll.addAll(switchAdded);
343 switchRemovedAll.addAll(switchRemoved);
344 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700345 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700346
347 if (!portEntriesRemoved.isEmpty()) {
348 processPortRemoval(portEntriesRemoved);
349 }
350
351 if (!linkEntriesRemoved.isEmpty()) {
352 processLinkRemoval(linkEntriesRemoved);
353 }
354
355 if (!switchRemoved.isEmpty()) {
356 processSwitchRemoved(switchRemoved);
357 }
358
359 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700360 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700361 }
362
363 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700364 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700365 }
366
367 if (!portEntriesAdded.isEmpty()) {
368 processPortAdd(portEntriesAdded);
369 }
370
371 if (!switchAdded.isEmpty()) {
372 processSwitchAdd(switchAdded);
373 }
Sangho Shin51625342014-10-17 09:30:48 -0700374
Sangho Shinbce900e2014-10-07 17:13:23 -0700375 }
376
Sangho Shin23f898d2014-10-13 16:54:00 -0700377 // TODO: 100ms is enough to check both mastership removed events
378 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700379 if (!mastershipRemovedAll.isEmpty()) {
380 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700381 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700382 }
383 else {
384 HashMap<String, MastershipData> mastershipToRemove =
385 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700386 for (MastershipData ms: mastershipRemovedAll) {
387 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700388 // TODO: check ALL ports of the switch are dead ..
389 if (port.getDpid().equals(ms.getDpid())) {
390 mastershipToRemove.put(ms.getDpid().toString(), ms);
391 }
392 }
393 log.debug("Swtich {} is really down.", ms.getDpid());
394 }
395 processMastershipRemoved(mastershipToRemove.values());
396 }
397 }
398
Sangho Shinbce900e2014-10-07 17:13:23 -0700399 log.debug("num events {}, num of process {}, "
400 + "num of Population {}", numOfEvents, numOfEventProcess,
401 numOfPopulation);
402 }
403
404 /**
Sangho Shin23f898d2014-10-13 16:54:00 -0700405 * Add the link immediately
406 * The function is scheduled when link add event happens and called
407 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
408 */
409 private void delayedAddLink() {
410
411 processLinkAdd(linksToAdd.values(), true);
412
413 }
414
415 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700416 * Process the SwitchAdded events from topologyMananger.
417 * It does nothing. When a switch is added, then link will be added too.
418 * LinkAdded event will handle process all re-computation.
419 *
420 * @param switchAdded
421 */
422 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
423
424 }
425
426 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700427 * Remove all ports connected to the switch removed
428 *
429 * @param mastershipRemoved master switch info removed
430 */
431 private void processMastershipRemoved(Collection<MastershipData>
432 mastershipRemoved) {
433 for (MastershipData mastership: mastershipRemoved) {
434 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
435 for (Link link: sw.getOutgoingLinks()) {
436 Port dstPort = link.getDstPort();
437 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
438 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700439 if (dstSw != null) {
440 dstSw.removePortFromGroups(dstPort.getNumber());
441 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
442 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700443 }
Sangho Shin61535402014-10-01 11:37:14 -0700444 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700445
446 linksToAdd.clear();
447 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700448 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700449
Sangho Shinbce900e2014-10-07 17:13:23 -0700450 /**
451 * Remove all ports connected to the switch removed
452 *
453 * @param switchRemoved Switch removed
454 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700455 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700456 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700457 }
458
Sangho Shin61535402014-10-01 11:37:14 -0700459 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700460 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700461 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700462 * @param portEntries
463 */
464 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700465 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700466 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700467 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700468
Sangho Shinfbc572c2014-10-02 16:37:05 -0700469 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700470 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700471 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700472 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700473 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700474 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700475 }
476 }
477
478 /**
479 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700480 * If the link to add was removed before, then we just schedule the add link
481 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700482 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700483 * @param linkEntries
484 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700485 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700486
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700487 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700488
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700489 SwitchPort srcPort = link.getSrc();
490 SwitchPort dstPort = link.getDst();
491
Sangho Shin23f898d2014-10-13 16:54:00 -0700492 String key = srcPort.getDpid().toString() +
493 dstPort.getDpid().toString();
494 if (!delayed) {
495 if (linksDown.containsKey(key)) {
496 linksToAdd.put(key, link);
497 linksDown.remove(key);
498 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
499 log.debug("Add link {} with 5 sec delay", link);
500 // TODO: What if we have multiple events of add link:
501 // one is new link add, the other one is link up for
502 // broken link? ECMPSPG function cannot deal with it for now
503 return;
504 }
505 }
506 else {
507 if (linksDown.containsKey(key)) {
508 linksToAdd.remove(key);
509 log.debug("Do not add the link {}: it is down again!", link);
510 return;
511 }
512 }
513
Sangho Shinfbc572c2014-10-02 16:37:05 -0700514 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700515 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700516 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700517 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700518
Sangho Shin815af0c2014-10-10 13:05:45 -0700519 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700520 continue;
521
522 srcSw.addPortToGroups(srcPort.getPortNumber());
523 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700524
Sangho Shin15273b62014-10-16 22:22:05 -0700525 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
526 // link);
527 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
528 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700529
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700530 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700531 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700532 }
533
534 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700535 * Check if all links are gone b/w the two switches. If all links are gone,
536 * then we need to recalculate the path. Otherwise, just report link failure
537 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700538 *
Sangho Shin61535402014-10-01 11:37:14 -0700539 * @param linkEntries
540 */
541 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700542 boolean recomputationRequired = false;
543
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700544 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700545 SwitchPort srcPort = link.getSrc();
546 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700547
Sangho Shinfbc572c2014-10-02 16:37:05 -0700548 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700549 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700550 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700551 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700552 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700553 /* If this link is not between two switches, ignore it */
554 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700555
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700556 srcSw.removePortFromGroups(srcPort.getPortNumber());
557 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700558 log.debug("Remove port {} from switch {}", srcPort, srcSw);
559 log.debug("Remove port {} from switch {}", dstPort, dstSw);
560
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700561 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
562 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700563 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700564 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700565 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700566 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700567 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700568 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700569
570 String key = link.getSrc().getDpid().toString()+
571 link.getDst().getDpid().toString();
572 if (!linksDown.containsKey(key)) {
573 linksDown.put(key, link);
574 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700575 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700576
577 if (recomputationRequired)
578 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700579 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700580
Sangho Shin61535402014-10-01 11:37:14 -0700581 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700582 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700583 *
Sangho Shin61535402014-10-01 11:37:14 -0700584 * @param portEntries
585 */
586 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700587 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700588 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700589
Sangho Shinfbc572c2014-10-02 16:37:05 -0700590 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700591 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700592 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700593 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700594 log.debug("Remove port {} from switch {}", port, dpid);
595 }
Sangho Shin61535402014-10-01 11:37:14 -0700596 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700597 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700598
599 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700600 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700601 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700602 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700603 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700604 private void populateEcmpRoutingRules(boolean modified) {
605 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700606 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700607 for (Switch sw : switches) {
608 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700609 graphs.put(sw, ecmpSPG);
610 //log.debug("ECMPShortestPathGraph is computed for switch {}",
611 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700612 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700613 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700614 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700615 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700616
Sangho Shin99918bd2014-10-08 15:52:35 -0700617 /**
618 * populate routing rules to forward packets from the switch given to
619 * all other switches.
620 *
621 * @param sw source switch
622 * @param ecmpSPG shortest path from the the source switch to all others
623 * @param modified modification flag
624 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700625 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700626 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700627
Sangho Shinfbc572c2014-10-02 16:37:05 -0700628 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
629 ecmpSPG.getAllLearnedSwitchesAndVia();
630 for (Integer itrIdx : switchVia.keySet()) {
631 //log.debug("ECMPShortestPathGraph:Switches learned in "
632 // + "Iteration{} from switch {}:",
633 // itrIdx,
634 // HexString.toHexString(sw.getDpid().value()));
635 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
636 switchVia.get(itrIdx);
637 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700638 //log.debug("ECMPShortestPathGraph:****switch {} via:",
639 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700640 String destSw = sw.getDpid().toString();
641 List<String> fwdToSw = new ArrayList<String>();
642
Sangho Shinfbc572c2014-10-02 16:37:05 -0700643 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700644 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700645 if (via.isEmpty()) {
646 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700647 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700648 else {
649 fwdToSw.add(via.get(0).toString());
650 }
Sangho Shin43cee112014-09-25 16:43:34 -0700651 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700652 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700653 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700654
655 // Send Barrier Message and make sure all rules are set
656 // before we set the rules to next routers
Saurav Dasa962a692014-10-17 14:52:38 -0700657 // TODO: barriers to all switches in this update stage
Sangho Shinfbc572c2014-10-02 16:37:05 -0700658 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
659 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700660 if (sw13 != null) {
Saurav Dasa962a692014-10-17 14:52:38 -0700661 OFBarrierReplyFuture replyFuture = null;
Sangho Shin5be3e532014-10-03 17:20:58 -0700662 try {
Saurav Dasa962a692014-10-17 14:52:38 -0700663 replyFuture = sw13.sendBarrier();
Sangho Shin5be3e532014-10-03 17:20:58 -0700664 } catch (IOException e) {
Saurav Dasa962a692014-10-17 14:52:38 -0700665 log.error("Error sending barrier request to switch {}",
666 sw13.getId(), e.getCause());
Sangho Shin5be3e532014-10-03 17:20:58 -0700667 }
Saurav Dasa962a692014-10-17 14:52:38 -0700668 OFBarrierReply br = null;
669 try {
670 br = replyFuture.get(2, TimeUnit.SECONDS);
671 } catch (TimeoutException | InterruptedException | ExecutionException e) {
672 // XXX for some reason these exceptions are not being thrown
673 }
674 if (br == null) {
675 log.warn("Did not receive barrier-reply from {}", sw13.getId());
676 // XXX take corrective action
677 }
678
Sangho Shinfbc572c2014-10-02 16:37:05 -0700679 }
680 }
681
682 }
683
Sangho Shin99918bd2014-10-08 15:52:35 -0700684 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700685 * This class is used only for link recovery optimization in
686 * modifyEcmpRoutingRules() function.
Sangho Shin99918bd2014-10-08 15:52:35 -0700687 * TODO: please remove if the optimization is not used at all
Sangho Shinbce900e2014-10-07 17:13:23 -0700688 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700689 private class SwitchPair {
690 private Switch src;
691 private Switch dst;
692
693 public SwitchPair(Switch src, Switch dst) {
694 this.src = src;
695 this.dst = dst;
696 }
697
698 public Switch getSource() {
699 return src;
700 }
701
702 public Switch getDestination() {
703 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700704 }
Sangho Shin43cee112014-09-25 16:43:34 -0700705 }
706
707 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700708 * Modify the routing rules for the lost links
709 * - Recompute the path if the link failed is included in the path
710 * (including src and dest).
711 *
712 * @param newLink
713 */
714 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
715
716 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700717 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700718
719 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
720 Switch rootSw = ecmpSPG.getRootSwitch();
721 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
722 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
723 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
724 for (Switch destSw: p.keySet()) {
725 ArrayList<Path> path = p.get(destSw);
726 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700727 boolean found = false;
728 for (SwitchPair pair: linksToRecompute) {
729 if (pair.getSource().getDpid() == rootSw.getDpid() &&
730 pair.getSource().getDpid() == destSw.getDpid()) {
731 found = true;
732 }
733 }
734 if (!found) {
735 linksToRecompute.add(new SwitchPair(rootSw, destSw));
736 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700737 }
738 }
739 }
740 }
741
742 // Recompute the path for the specific route
743 for (SwitchPair pair: linksToRecompute) {
744
745 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
Sangho Shin99918bd2014-10-08 15:52:35 -0700746 // We need the following function for optimization
Sangho Shinfbc572c2014-10-02 16:37:05 -0700747 //ECMPShortestPathGraph ecmpSPG =
748 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
749 ECMPShortestPathGraph ecmpSPG =
750 new ECMPShortestPathGraph(pair.getSource());
Sangho Shin5be3e532014-10-03 17:20:58 -0700751 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700752 }
753 }
754
755 /**
756 * Check if the path is affected from the link removed
757 *
758 * @param path Path to check
759 * @param linkRemoved link removed
760 * @return true if the path contains the link removed
761 */
762 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
763
764 for (Path ppp: path) {
765 // TODO: need to check if this is a bidirectional or
766 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700767 for (LinkData link: ppp) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700768 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
769 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
770 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700771 }
772 }
773
774 return false;
775 }
776
777 /**
778 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700779 * Set routing rules in targetSw {forward packets to fwdToSw switches in
780 * order to send packets to destSw} - If the target switch is an edge router
781 * and final destnation switch is also an edge router, then set IP
782 * forwarding rules to subnets - If only the target switch is an edge
783 * router, then set IP forwarding rule to the transit router loopback IP
784 * address - If the target is a transit router, then just set the MPLS
785 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700786 *
Sangho Shin43cee112014-09-25 16:43:34 -0700787 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700788 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700789 * @param fwdToSw next hop switches
790 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700791 private void setRoutingRule(Switch targetSw, String destSw,
792 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700793
Sangho Shin43cee112014-09-25 16:43:34 -0700794 if (fwdToSw.isEmpty()) {
795 fwdToSw.add(destSw);
796 }
797
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700798 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700799 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
800 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700801 // We assume that there is at least one transit router b/w edge
802 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700803 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
804 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700805 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700806 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700807
Sangho Shin43cee112014-09-25 16:43:34 -0700808 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700809 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
810 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700811 // Edge router can be a transit router
812 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700813 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700814 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700815 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700816 // We assume that there is at least one transit router b/w edge
817 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700818 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
819 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700820 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
821 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700822 // Edge router can be a transit router
823 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700824 }
825 // if it is a transit router, then set rules in the MPLS table
826 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700827 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700828 }
829
830 }
831
Sangho Shinfbc572c2014-10-02 16:37:05 -0700832 /**
833 * Set IP forwarding rule to the gateway of each subnet of switches
834 *
835 * @param targetSw Switch to set rules
836 * @param subnets subnet information
837 * @param mplsLabel destination MPLS label
838 * @param fwdToSw router to forward packets to
839 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700840 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700841 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700842
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700843 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700844 new ArrayList<MatchActionOperationEntry>();
845
846 try {
847 JSONArray arry = new JSONArray(subnets);
848 for (int i = 0; i < arry.length(); i++) {
849 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700850 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
851 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700852 }
853 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700854 e.printStackTrace();
855 }
856
857 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700858 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700859 getSwId(targetSw.getDpid().toString()));
860
Sangho Shin721ca042014-10-09 13:03:40 -0700861 if (sw13 != null) {
862 try {
863 sw13.pushFlows(entries);
864 } catch (IOException e) {
865 e.printStackTrace();
866 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700867 }
868 }
869
870 }
871
Sangho Shin43cee112014-09-25 16:43:34 -0700872 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700873 * Check if the switch is the edge router or not.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700874 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700875 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700876 * @return true if it is an edge router, otherwise false
877 */
878 private boolean IsEdgeRouter(String dpid) {
879
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700880 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700881 String dpidStr = sw.getDpid().toString();
882 if (dpid.equals(dpidStr)) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700883 /*
Sangho Shin43cee112014-09-25 16:43:34 -0700884 String subnetInfo = sw.getStringAttribute("subnets");
885 if (subnetInfo == null || subnetInfo.equals("[]")) {
886 return false;
887 }
888 else
889 return true;
Sangho Shinbce900e2014-10-07 17:13:23 -0700890 */
891 String isEdge = sw.getStringAttribute("isEdgeRouter");
892 if (isEdge != null) {
893 if (isEdge.equals("true"))
894 return true;
895 else
896 return false;
897 }
Sangho Shin43cee112014-09-25 16:43:34 -0700898 }
899 }
900
901 return false;
902 }
903
904 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700905 * Set IP forwarding rule - If the destination is the next hop, then do not
906 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
907 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700908 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700909 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700910 * @param subnetIp Match IP address
911 * @param mplsLabel MPLS label of final destination router
912 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700913 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700914 */
915 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700916 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
917 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700918
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700919 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700920 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700921 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700922
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700923 // If destination SW is the same as the fwd SW, then do not push MPLS
924 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700925 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700926 PushMplsAction pushMplsAction = new PushMplsAction();
927 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
928 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700929 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700930
Sangho Shin62ce5c12014-10-08 16:24:40 -0700931 //actions.add(pushMplsAction);
932 //actions.add(copyTtlOutAction);
933 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700934 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700935 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700936 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700937 else {
938 String fwdToSw = fwdToSws.get(0);
939 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
940 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
941 actions.add(decTtlAction);
942 }
943 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700944 SetMplsIdAction setIdAction = new SetMplsIdAction(
945 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700946 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700947 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700948
Sangho Shin62ce5c12014-10-08 16:24:40 -0700949 //actions.add(pushMplsAction);
950 //actions.add(copyTtlOutAction);
951 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700952 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700953 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700954 }
955 }
Sangho Shin43cee112014-09-25 16:43:34 -0700956
Sangho Shin43cee112014-09-25 16:43:34 -0700957 for (String fwdSw : fwdToSws) {
958 groupAction.addSwitch(new Dpid(fwdSw));
959 }
960 actions.add(groupAction);
961
Sangho Shin99918bd2014-10-08 15:52:35 -0700962 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700963 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700964
Sangho Shin5be3e532014-10-03 17:20:58 -0700965 Operator operator = null;
966 if (modified)
967 operator = Operator.MODIFY;
968 else
969 operator = Operator.ADD;
970
Sangho Shin43cee112014-09-25 16:43:34 -0700971 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700972 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700973
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700974 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700975 getSwId(sw.getDpid().toString()));
976
Sangho Shin5be3e532014-10-03 17:20:58 -0700977 if (sw13 != null) {
978 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700979 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700980 if (entries != null)
981 entries.add(maEntry);
982 else
983 sw13.pushFlow(maEntry);
984 } catch (IOException e) {
985 e.printStackTrace();
986 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700987 }
988
Sangho Shin43cee112014-09-25 16:43:34 -0700989 }
990
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700991 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700992 * Set MPLS forwarding rules to MPLS table
993 * </p>
994 * If the destination is the same as the next hop to forward packets then,
995 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
996 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
997 * TTL of the another MPLS header.
998 * If the next hop is not the destination, just forward packets to next
999 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001000 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001001 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -07001002 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001003 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001004 * */
Sangho Shin5be3e532014-10-03 17:20:58 -07001005 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
1006 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -07001007
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001008 if (fwdSws.isEmpty())
1009 return;
Sangho Shin43cee112014-09-25 16:43:34 -07001010
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001011 Collection<MatchActionOperationEntry> maEntries =
1012 new ArrayList<MatchActionOperationEntry>();
1013 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -07001014
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001015 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
1016 // One rule for Bos = 1
1017 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
1018 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001019
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001020 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
1021 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
1022 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
1023
1024 actions.add(copyTtlInAction);
1025 actions.add(popAction);
1026 actions.add(decNwTtlAction);
1027
1028 GroupAction groupAction = new GroupAction();
1029 groupAction.addSwitch(new Dpid(fwdSw1));
1030 actions.add(groupAction);
1031
1032 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
1033 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1034 Operator operator = Operator.ADD;
1035 MatchActionOperationEntry maEntry =
1036 new MatchActionOperationEntry(operator, matchAction);
1037 maEntries.add(maEntry);
1038
1039 // One rule for Bos = 0
Sangho Shin23f898d2014-10-13 16:54:00 -07001040 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001041 List<Action> actionsBos = new ArrayList<Action>();
Sangho Shin15273b62014-10-16 22:22:05 -07001042 PopMplsAction popActionBos = new PopMplsAction(EthType.MPLS_UNICAST);
1043 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1044
1045 actionsBos.add(copyTtlInAction);
1046 actionsBos.add(popActionBos);
1047 actionsBos.add(decMplsTtlAction);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001048 actionsBos.add(groupAction);
1049
1050 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
1051 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
1052 MatchActionOperationEntry maEntryBos =
1053 new MatchActionOperationEntry(operator, matchActionBos);
1054 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001055 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001056 else {
1057 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
1058 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -07001059
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001060 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1061 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -07001062
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001063 GroupAction groupAction = new GroupAction();
1064 for (String fwdSw : fwdSws)
1065 groupAction.addSwitch(new Dpid(fwdSw));
1066 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -07001067
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001068 MatchAction matchAction = new MatchAction(new MatchActionId(
1069 matchActionId++),
1070 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1071 Operator operator = Operator.ADD;
1072 MatchActionOperationEntry maEntry =
1073 new MatchActionOperationEntry(operator, matchAction);
1074 maEntries.add(maEntry);
Sangho Shine2e9bcd2014-10-13 15:14:18 -07001075
1076 // BoS = 1
1077 MplsMatch mplsMatchBoS = new MplsMatch(Integer.parseInt(mplsLabel), true);
1078 List<Action> actionsBoS = new ArrayList<Action>();
1079
1080 DecMplsTtlAction decMplsTtlActionBoS = new DecMplsTtlAction(1);
1081 actionsBoS.add(decMplsTtlActionBoS);
1082
1083 GroupAction groupActionBoS = new GroupAction();
1084 for (String fwdSw : fwdSws)
1085 groupActionBoS.addSwitch(new Dpid(fwdSw));
1086 actionsBoS.add(groupActionBoS);
1087
1088 MatchAction matchActionBos = new MatchAction(new MatchActionId(
1089 matchActionId++),
1090 new SwitchPort((long) 0, (short) 0), mplsMatchBoS, actionsBoS);
1091 MatchActionOperationEntry maEntryBoS =
1092 new MatchActionOperationEntry(operator, matchActionBos);
1093 maEntries.add(maEntryBoS);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001094 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001095 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001096 getSwId(sw.getDpid().toString()));
1097
Sangho Shin5be3e532014-10-03 17:20:58 -07001098 if (sw13 != null) {
1099 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001100 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001101 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001102 } catch (IOException e) {
1103 e.printStackTrace();
1104 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001105 }
Sangho Shin43cee112014-09-25 16:43:34 -07001106 }
1107
Sangho Shin15273b62014-10-16 22:22:05 -07001108 /**
1109 * Create a tunnel for policy routing
1110 * It delivers the node IDs of tunnels to driver.
1111 * Split the node IDs if number of IDs exceeds the limit for stitching.
1112 *
1113 * @param tunnelId Node IDs for the tunnel
1114 * @param Ids tunnel ID
1115 */
1116 public boolean createTunnel(int tunnelId, List<String> Ids) {
1117
1118 if (tunnelId < 0) {
1119 log.debug("Tunnel ID should be posivtive integer.");
1120 return false;
1121 }
1122
1123 if (Ids.isEmpty() || Ids.size() < 2) {
1124 log.debug("Wrong tunnel information");
1125 return false;
1126 }
1127
1128 HashMap<String, PolicyRouteInfo> stitchingRule = getStitchingRule(Ids);
1129 stitchInfo.put(Integer.valueOf(tunnelId), stitchingRule);
1130 if (stitchingRule == null) {
1131 log.debug("Failed to get the policy rule.");
1132 return false;
1133 }
1134 HashMap<String, Integer> switchGroupPair = new HashMap<String, Integer>();
1135 for (String targetDpid: stitchingRule.keySet()) {
1136 PolicyRouteInfo route = stitchingRule.get(targetDpid);
1137
1138 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
1139 getSwId(targetDpid.toString()));
1140
1141 if (targetSw == null) {
1142 log.debug("Switch {} is gone.", targetDpid);
1143 return false;
1144 }
1145
1146 NeighborSet ns = new NeighborSet();
1147 for (Dpid dpid: route.getFwdSwDpid())
1148 ns.addDpid(dpid);
1149
1150 printTunnelInfo(targetSw, tunnelId, route.getRoute(), ns);
1151 int groupId = targetSw.createTunnel(tunnelId, route.getRoute(), ns);
1152 switchGroupPair.put(targetDpid.toString(), groupId);
1153
1154 }
1155
1156 tunnelGroupMap.put(Integer.valueOf(tunnelId), switchGroupPair);
1157
1158 return true;
1159 }
1160
Sangho Shinbb2b8362014-10-17 21:07:16 -07001161 public void removeTunnel(int tunnelId) {
1162
1163 }
1164
Sangho Shin15273b62014-10-16 22:22:05 -07001165 /**
1166 * Set policy table for policy routing
1167 *
1168 * @param sw
1169 * @param mplsLabel
1170 */
Sangho Shinbb2b8362014-10-17 21:07:16 -07001171 public void setPolicyTable(int pid, MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001172 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
1173 Short srcTcpPort, Short dstTcpPort, int tid) {
1174
1175 HashMap<String, PolicyRouteInfo> routeInfo = stitchInfo.get(Integer.valueOf(tid));
1176 HashMap<String, Integer> switchGroupPair = tunnelGroupMap.get(Integer.valueOf(tid));
Sangho Shinbb2b8362014-10-17 21:07:16 -07001177 HashMap<PacketMatch, Integer> policyInfo = new HashMap<PacketMatch, Integer>();
1178
1179 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1180
1181 if (srcMac != null)
1182 packetBuilder.setSrcMac(srcMac);
1183 if (dstMac != null)
1184 packetBuilder.setDstMac(dstMac);
1185 if (etherType != null)
1186 packetBuilder.setEtherType(etherType);
1187 if (srcIp != null)
1188 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1189 if (dstIp != null)
1190 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1191 if (ipProto != null)
1192 packetBuilder.setIpProto(ipProto);
1193 if (srcTcpPort > 0)
1194 packetBuilder.setSrcTcpPort(srcTcpPort);
1195 if (dstTcpPort > 0)
1196 packetBuilder.setDstTcpPort(dstTcpPort);
1197 PacketMatch packetMatch = packetBuilder.build();
1198
Sangho Shin15273b62014-10-16 22:22:05 -07001199 for (String srcDpid: routeInfo.keySet()) {
Sangho Shin15273b62014-10-16 22:22:05 -07001200 List<Action> actions = new ArrayList<>();
1201 GroupAction groupAction = new GroupAction();
1202 int gropuId = switchGroupPair.get(srcDpid);
1203 groupAction.setGroupId(gropuId);
1204 actions.add(groupAction);
1205
1206 MatchAction matchAction = new MatchAction(new MatchActionId(
1207 matchActionId++),
Sangho Shinbb2b8362014-10-17 21:07:16 -07001208 new SwitchPort((long) 0, (short) 0), packetMatch, actions);
Sangho Shin15273b62014-10-16 22:22:05 -07001209 MatchActionOperationEntry maEntry =
1210 new MatchActionOperationEntry(Operator.ADD, matchAction);
1211
1212 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1213 getSwId(srcDpid));
1214
1215 if (sw13 != null) {
1216 printMatchActionOperationEntry(sw13, maEntry);
1217 try {
1218 sw13.pushFlow(maEntry);
1219 } catch (IOException e) {
1220 e.printStackTrace();
Sangho Shinbb2b8362014-10-17 21:07:16 -07001221 log.debug("Policy was not set due to pushFlow() error");
Sangho Shin15273b62014-10-16 22:22:05 -07001222 }
1223 }
1224 }
Sangho Shinbb2b8362014-10-17 21:07:16 -07001225 policyInfo.put(packetMatch, Integer.valueOf(tid));
1226 policyMap.put(Integer.valueOf(pid), policyInfo);
1227 }
1228
1229 /**
1230 * Remove all policies applied to specific tunnel.
1231 *
1232 * @param srcMac
1233 * @param dstMac
1234 * @param etherType
1235 * @param srcIp
1236 * @param dstIp
1237 * @param ipProto
1238 * @param srcTcpPort
1239 * @param dstTcpPort
1240 * @param tid
1241 */
1242 public void removePolicy(int pid) {
1243
1244 HashMap<PacketMatch, Integer> policyInfo = policyMap.get(Integer.valueOf(pid));
1245 PacketMatch policyMatch = (PacketMatch) policyInfo.keySet().toArray()[0];
1246 int tid = policyInfo.get(policyMatch).intValue();
1247
1248 List<Action> actions = new ArrayList<>();
1249 int gropuId = 0; // dummy group ID
1250 GroupAction groupAction = new GroupAction();
1251 groupAction.setGroupId(gropuId);
1252 actions.add(groupAction);
1253
1254 MatchAction matchAction = new MatchAction(new MatchActionId(
1255 matchActionId++),
1256 new SwitchPort((long) 0, (short) 0), policyMatch, actions);
1257 MatchActionOperationEntry maEntry =
1258 new MatchActionOperationEntry(Operator.REMOVE, matchAction);
1259
1260 HashMap<String, Integer> groupInfo = tunnelGroupMap.get(
1261 Integer.valueOf(tid));
1262
1263 for (String dpid: groupInfo.keySet()) {
1264 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1265 getSwId(dpid));
1266
1267 if (sw13 != null) {
1268 printMatchActionOperationEntry(sw13, maEntry);
1269 try {
1270 sw13.pushFlow(maEntry);
1271 } catch (IOException e) {
1272 e.printStackTrace();
1273 log.debug("policy remove failed due to pushFlow() exception");
1274 return;
1275 }
1276 }
1277 }
1278
1279 log.debug("Policy {} is removed.", pid);
Sangho Shin15273b62014-10-16 22:22:05 -07001280 }
1281
1282 /**
1283 * Get the forwarding Switch DPIDs to send packets to a node
1284 *
1285 * @param srcSw source switch
1286 * @param nodeId destination node Id
1287 * @return list of switch DPID to forward packets to
1288 */
1289
1290 private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
1291
1292 List<Dpid> fwdSws = new ArrayList<Dpid>();
1293 Switch destSw = null;
1294
1295 destSw = getSwitchFromNodeId(nodeId);
1296
1297 if (destSw == null) {
1298 log.debug("Cannot find the switch with ID {}", nodeId);
1299 return null;
1300 }
1301
1302 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1303
1304 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1305 ecmpSPG.getAllLearnedSwitchesAndVia();
1306 for (Integer itrIdx : switchVia.keySet()) {
1307 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1308 switchVia.get(itrIdx);
1309 for (Switch targetSw : swViaMap.keySet()) {
1310 String destSwDpid = destSw.getDpid().toString();
1311 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1312 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1313 if (via.isEmpty()) {
1314 fwdSws.add(destSw.getDpid());
1315 }
1316 else {
1317 fwdSws.add(via.get(0));
1318 }
1319 }
1320 }
1321 }
1322 }
1323
1324 return fwdSws;
1325 }
1326
1327 /**
1328 * Get switch for the node Id specified
1329 *
1330 * @param nodeId node ID for switch
1331 * @return Switch
1332 */
1333 private Switch getSwitchFromNodeId(String nodeId) {
1334
1335 for (Switch sw : mutableTopology.getSwitches()) {
1336 String id = sw.getStringAttribute("nodeSid");
1337 if (id.equals(nodeId)) {
1338 return sw;
1339 }
1340 }
1341
1342 return null;
1343 }
1344
1345 /**
1346 * Convert a string DPID to its Switch Id (integer)
1347 *
1348 * @param dpid
1349 * @return
1350 */
1351 private long getSwId(String dpid) {
1352
1353 long swId = 0;
1354
1355 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1356 if (swIdHexStr != null)
1357 swId = Integer.decode(swIdHexStr);
1358
1359 return swId;
1360 }
1361
1362 private void runTest() {
1363
Sangho Shinbb2b8362014-10-17 21:07:16 -07001364 if (testMode == POLICY_ADD) {
1365 String[] routeArray = {"101", "102", "103", "104", "105", "108",
1366 "110"};
1367 List<String> routeList = new ArrayList<String>();
1368 for (int i = 0; i < routeArray.length; i++)
1369 routeList.add(routeArray[i]);
Sangho Shin15273b62014-10-16 22:22:05 -07001370
Sangho Shinbb2b8362014-10-17 21:07:16 -07001371 if (createTunnel(1, routeList)) {
1372 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1373 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
Sangho Shin15273b62014-10-16 22:22:05 -07001374
Sangho Shinbb2b8362014-10-17 21:07:16 -07001375 this.setPolicyTable(1, null, null, Ethernet.TYPE_IPV4, srcIp,
1376 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 1);
1377
1378 testMode = POLICY_REMOVE;
1379 testTask.reschedule(10, TimeUnit.SECONDS);
1380 }
1381 else {
1382 testTask.reschedule(5, TimeUnit.SECONDS);
1383 }
Sangho Shin15273b62014-10-16 22:22:05 -07001384 }
Sangho Shinbb2b8362014-10-17 21:07:16 -07001385 else if (testMode == POLICY_REMOVE) {
1386 this.removePolicy(1);
Sangho Shin15273b62014-10-16 22:22:05 -07001387 }
1388 }
1389
1390 private void runTest1() {
1391
1392 String dpid1 = "00:00:00:00:00:00:00:01";
1393 String dpid2 = "00:00:00:00:00:00:00:0a";
1394 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1395 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1396
1397 if (srcSw == null || dstSw == null) {
1398 testTask.reschedule(1, TimeUnit.SECONDS);
1399 log.debug("Switch is gone. Reschedule the test");
1400 return;
1401 }
1402
1403 String[] routeArray = {"101", "102", "105", "108", "110"};
1404 List<String> routeList = new ArrayList<String>();
1405 for (int i = 0; i < routeArray.length; i++)
1406 routeList.add(routeArray[i]);
1407
1408 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1409
1410 log.debug("Test set is {}", routeList.toString());
1411 log.debug("Result set is {}", optimizedRoute.toString());
1412
1413
1414 }
1415
1416 /**
1417 * Optimize the mpls label
1418 * The feature will be used only for policy of "avoid a specific switch".
1419 * Check route to each router in route backward.
1420 * If there is only one route to the router and the routers are included in
1421 * the route, remove the id from the path.
1422 * A-B-C-D-E => A-B-C-D-E -> A-E
1423 * | | => A-B-H-I -> A-I
1424 * F-G-H-I => A-D-I -> A-D-I
1425 */
1426 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
1427
1428 List<String> optimizedPath = new ArrayList<String>();
1429 optimizedPath.addAll(route);
1430 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1431
1432 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
1433 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
1434 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
1435 for (Switch s: p.keySet()) {
1436 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
1437 ArrayList<Path> ecmpPaths = p.get(s);
1438 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
1439 for (Path path: ecmpPaths) {
1440 for (LinkData link: path) {
1441 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
1442 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
1443 if (optimizedPath.contains(srcId)) {
1444 optimizedPath.remove(srcId);
1445 }
1446 if (optimizedPath.contains(dstId)) {
1447 optimizedPath.remove(dstId);
1448 }
1449 }
1450 }
1451 }
1452 }
1453 }
1454 }
1455
1456 return optimizedPath;
1457
1458 }
1459
Sangho Shinbb2b8362014-10-17 21:07:16 -07001460 /**
1461 * Strore policy routing info
1462 */
Sangho Shin15273b62014-10-16 22:22:05 -07001463 class PolicyRouteInfo {
1464
1465 String srcSwDpid;
1466 List<Dpid> fwdSwDpids;
1467 List<String> route;
1468
1469 PolicyRouteInfo() {
1470 fwdSwDpids = new ArrayList<Dpid>();
1471 route = new ArrayList<String>();
1472 }
1473
1474 void setSrcDpid(String dpid) {
1475 this.srcSwDpid = dpid;
1476 }
1477
1478 void setFwdSwDpid(List<Dpid> dpid) {
1479 this.fwdSwDpids = dpid;
1480 }
1481
1482 void addRoute(String id) {
1483 route.add(id);
1484 }
1485
1486 void setRoute(List<String> r) {
1487 this.route = r;
1488 }
1489
1490 String getSrcSwDpid() {
1491 return this.srcSwDpid;
1492 }
1493
1494 List<Dpid> getFwdSwDpid() {
1495 return this.fwdSwDpids;
1496 }
1497
1498 List<String> getRoute() {
1499 return this.route;
1500 }
1501 }
1502
Sangho Shin15273b62014-10-16 22:22:05 -07001503 /**
1504 *
1505 *
1506 * @param srcSw
1507 * @param dstSw
1508 * @param route
1509 * @return
1510 */
1511 private HashMap<String, PolicyRouteInfo> getStitchingRule(List<String> route) {
1512
1513 if (route.isEmpty() || route.size() < 2)
1514 return null;
1515
1516 HashMap<String, PolicyRouteInfo> rules = new HashMap<String, PolicyRouteInfo>();
1517
1518 Switch srcSw = this.getSwitchFromNodeId(route.get(0));
1519 String srcDpid = srcSw.getDpid().toString();
1520
1521 if (route.size() <= MAX_NUM_LABELS+1) {
1522 PolicyRouteInfo info = new PolicyRouteInfo();
1523 info.setSrcDpid(srcSw.getDpid().toString());
1524 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, route.get(1));
1525 info.setFwdSwDpid(fwdSwDpids);
1526 route.remove(0);
1527 info.setRoute(route);
1528 rules.put(srcDpid, info);
1529 return rules;
1530 }
1531
1532 int i = 0;
1533 PolicyRouteInfo routeInfo = new PolicyRouteInfo();
1534 String prevNodeId = null;
1535 boolean checkNeighbor = true;
1536
1537 for (String nodeId: route) {
1538 if (i == 0) {
1539 routeInfo.setSrcDpid(srcDpid);
1540 srcSw = getSwitchFromNodeId(nodeId);
1541 i++;
1542 }
1543 else if (i == 1) {
1544 if (checkNeighbor) {
1545 // Check if next node is the neighbor SW of the source SW
1546 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
1547 if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
1548 log.debug("There is no route from node {} to node {}", srcSw.getDpid(), nodeId);
1549 return null;
1550 }
1551 // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
1552 boolean match = false;
1553 for (Dpid dpid: fwdSwDpids) {
1554 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1555 List<Dpid> fwdSws = new ArrayList<Dpid>();
1556 fwdSws.add(dpid);
1557 routeInfo.setFwdSwDpid(fwdSws);
1558 match = true;
1559 break;
1560 }
1561 }
1562 if (!match) {
1563 routeInfo.addRoute(nodeId);
1564 routeInfo.setFwdSwDpid(fwdSwDpids);
1565 i++;
1566 }
1567
1568 checkNeighbor = false;
1569 }
1570 else {
1571 routeInfo.addRoute(nodeId);
1572 i++;
1573 }
1574 }
1575 else {
1576 routeInfo.addRoute(nodeId);
1577 i++;
1578 }
1579
1580 if (i == MAX_NUM_LABELS+1) {
1581 rules.put(srcDpid, routeInfo);
1582 routeInfo = new PolicyRouteInfo();
1583 srcSw = getSwitchFromNodeId(nodeId);
1584 srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
1585 routeInfo.setSrcDpid(srcDpid);
1586 i = 1;
1587 checkNeighbor = true;
1588 }
1589 }
1590
1591 if (i < MAX_NUM_LABELS+1) {
1592 rules.put(srcDpid, routeInfo);
1593 }
1594
1595 return rules;
1596 }
1597
1598 /**
1599 * print tunnel info - used only for debugging.
1600 * @param targetSw
1601 *
1602 * @param fwdSwDpids
1603 * @param ids
1604 * @param tunnelId
1605 */
1606 private void printTunnelInfo(IOF13Switch targetSw, int tunnelId,
1607 List<String> ids, NeighborSet ns) {
1608 StringBuilder logStr = new StringBuilder("In switch " +
1609 targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
1610 for (String id: ids)
1611 logStr.append(id + "-");
1612 logStr.append(" output to ");
1613 for (Dpid dpid: ns.getDpids())
1614 logStr.append(dpid + " - ");
1615
1616 log.debug(logStr.toString());
1617
1618 }
1619
Sangho Shin43cee112014-09-25 16:43:34 -07001620 /**
1621 * Debugging function to print out the Match Action Entry
Sangho Shin15273b62014-10-16 22:22:05 -07001622 * @param sw13
Sangho Shinfbc572c2014-10-02 16:37:05 -07001623 *
Sangho Shin43cee112014-09-25 16:43:34 -07001624 * @param maEntry
1625 */
Sangho Shin15273b62014-10-16 22:22:05 -07001626 private void printMatchActionOperationEntry(
1627 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -07001628
Sangho Shin15273b62014-10-16 22:22:05 -07001629 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001630
1631 MatchAction ma = maEntry.getTarget();
1632 Match m = ma.getMatch();
1633 List<Action> actions = ma.getActions();
1634
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001635 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -07001636 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001637 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -07001638 logStr.append(ip.toString());
1639 logStr.append(" then ");
1640 }
1641 else if (m instanceof MplsMatch) {
1642 logStr.append("If the MPLS label matches with ");
1643 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1644 logStr.append(mplsLabel);
1645 logStr.append(" then ");
1646 }
Sangho Shin15273b62014-10-16 22:22:05 -07001647 else if (m instanceof PacketMatch) {
1648 GroupAction ga = (GroupAction)actions.get(0);
1649 logStr.append("if the policy match is XXX then go to group " +
1650 ga.getGroupId());
1651 log.debug(logStr.toString());
1652 return;
1653 }
Sangho Shin43cee112014-09-25 16:43:34 -07001654
1655 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001656 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -07001657 if (action instanceof CopyTtlInAction) {
1658 logStr.append("copy ttl In, ");
1659 }
1660 else if (action instanceof CopyTtlOutAction) {
1661 logStr.append("copy ttl Out, ");
1662 }
1663 else if (action instanceof DecMplsTtlAction) {
1664 logStr.append("Dec MPLS TTL , ");
1665 }
1666 else if (action instanceof GroupAction) {
1667 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001668 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -07001669 logStr.append(dpids.toString() + ",");
1670
Sangho Shin43cee112014-09-25 16:43:34 -07001671 }
1672 else if (action instanceof PopMplsAction) {
1673 logStr.append("Pop MPLS label, ");
1674 }
1675 else if (action instanceof PushMplsAction) {
1676 logStr.append("Push MPLS label, ");
1677 }
1678 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001679 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -07001680 logStr.append("Set MPLS ID as " + id + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001681 }
1682 }
1683
1684 log.debug(logStr.toString());
1685
Sangho Shineb083032014-09-22 16:11:34 -07001686 }
1687
1688 /**
1689 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001690 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001691 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001692 * @return MPLS label for the switch
1693 */
1694
Sangho Shin43cee112014-09-25 16:43:34 -07001695 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001696
1697 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001698 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001699 String dpidStr = sw.getDpid().toString();
1700 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001701 mplsLabel = sw.getStringAttribute("nodeSid");
1702 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001703 }
1704 }
1705
Sangho Shineb083032014-09-22 16:11:34 -07001706 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001707 }
1708
Sangho Shineb083032014-09-22 16:11:34 -07001709 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001710 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001711 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001712 * @param addr - subnet address to match
1713 * @param addr1 - IP address to check
1714 * @return true if the IP address matches to the subnet, otherwise false
1715 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001716 public boolean netMatch(String addr, String addr1) { // addr is subnet
1717 // address and addr1 is
1718 // ip address. Function
1719 // will return true, if
1720 // addr1 is within
1721 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001722
1723 String[] parts = addr.split("/");
1724 String ip = parts[0];
1725 int prefix;
1726
1727 if (parts.length < 2) {
1728 prefix = 0;
1729 } else {
1730 prefix = Integer.parseInt(parts[1]);
1731 }
1732
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001733 Inet4Address a = null;
1734 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001735 try {
1736 a = (Inet4Address) InetAddress.getByName(ip);
1737 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001738 } catch (UnknownHostException e) {
1739 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001740
1741 byte[] b = a.getAddress();
1742 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001743 ((b[1] & 0xFF) << 16) |
1744 ((b[2] & 0xFF) << 8) |
1745 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001746
1747 byte[] b1 = a1.getAddress();
1748 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001749 ((b1[1] & 0xFF) << 16) |
1750 ((b1[2] & 0xFF) << 8) |
1751 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001752
1753 int mask = ~((1 << (32 - prefix)) - 1);
1754
1755 if ((ipInt & mask) == (ipInt1 & mask)) {
1756 return true;
1757 }
1758 else {
1759 return false;
1760 }
1761 }
Sangho Shineb083032014-09-22 16:11:34 -07001762
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001763 /**
1764 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001765 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001766 * @param sw - Switch to add the rule
1767 * @param hostIpAddress Destination host IP address
1768 * @param hostMacAddress Destination host MAC address
1769 */
Sangho Shineb083032014-09-22 16:11:34 -07001770 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1771 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1772
1773 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001774
Sangho Shin463bee52014-09-29 15:14:43 -07001775 /**
1776 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001777 *
Sangho Shin463bee52014-09-29 15:14:43 -07001778 * @param ipv4
1779 */
1780 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001781 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001782 }
1783
1784 /**
1785 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001786 *
Sangho Shin463bee52014-09-29 15:14:43 -07001787 * @param destIp Destination address of packets to retrieve
1788 */
1789 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1790
1791 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1792
Sangho Shin61535402014-10-01 11:37:14 -07001793 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001794 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001795 int dest = ip.getDestinationAddress();
1796 IPv4Address ip1 = IPv4Address.of(dest);
1797 IPv4Address ip2 = IPv4Address.of(destIp);
1798 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001799 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001800 }
1801 }
1802 }
1803
1804 return bufferedPackets;
1805 }
1806
Sangho Shin15273b62014-10-16 22:22:05 -07001807
1808
Sangho Shin2f263692014-09-15 14:09:41 -07001809}