blob: 34b1a8c109b3d3086f7a31c6744525b65253c6bf [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;
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07008import java.util.Arrays;
Sangho Shin2f263692014-09-15 14:09:41 -07009import java.util.Collection;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070010import java.util.HashMap;
Sangho Shin5be3e532014-10-03 17:20:58 -070011import java.util.HashSet;
Sangho Shin2f263692014-09-15 14:09:41 -070012import java.util.Iterator;
13import java.util.List;
14import java.util.Map;
Sangho Shin5be3e532014-10-03 17:20:58 -070015import java.util.Set;
Sangho Shin61535402014-10-01 11:37:14 -070016import java.util.concurrent.ConcurrentLinkedQueue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070017import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070018import java.util.concurrent.ScheduledExecutorService;
19import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070020import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070021
22import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070023import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070024import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070025import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070026import net.floodlightcontroller.core.module.FloodlightModuleContext;
27import net.floodlightcontroller.core.module.FloodlightModuleException;
28import net.floodlightcontroller.core.module.IFloodlightModule;
29import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070030import net.floodlightcontroller.core.util.SingletonTask;
Sangho Shin7330c032014-10-20 10:34:51 -070031import net.floodlightcontroller.restserver.IRestApiService;
Sangho Shin43cee112014-09-25 16:43:34 -070032import net.floodlightcontroller.threadpool.IThreadPoolService;
Sangho Shin15273b62014-10-16 22:22:05 -070033import net.floodlightcontroller.util.MACAddress;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070034import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070035import net.onrc.onos.api.packet.IPacketService;
Sangho Shinf65b4da2014-10-28 16:58:13 -070036import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicy.PolicyType;
37import net.onrc.onos.apps.segmentrouting.SegmentRoutingTunnel.TunnelRouteInfo;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070038import net.onrc.onos.apps.segmentrouting.web.SegmentRoutingWebRoutable;
Srikanth Vavilapalli8a661e72014-10-27 15:40:22 -070039import net.onrc.onos.core.drivermanager.OFSwitchImplDellOSR;
Sangho Shin2f263692014-09-15 14:09:41 -070040import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070041import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070042import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070043import net.onrc.onos.core.matchaction.MatchAction;
44import net.onrc.onos.core.matchaction.MatchActionId;
45import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070046import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070047import net.onrc.onos.core.matchaction.action.Action;
48import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
49import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
50import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
51import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
52import net.onrc.onos.core.matchaction.action.GroupAction;
Sangho Shin6d3c2f02014-10-22 10:10:55 -070053import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
54import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
55import net.onrc.onos.core.matchaction.action.OutputAction;
Sangho Shin43cee112014-09-25 16:43:34 -070056import net.onrc.onos.core.matchaction.action.PopMplsAction;
57import net.onrc.onos.core.matchaction.action.PushMplsAction;
Sangho Shine842cad2014-10-24 16:07:35 -070058import net.onrc.onos.core.matchaction.action.SetDAAction;
Sangho Shin43cee112014-09-25 16:43:34 -070059import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Sangho Shine842cad2014-10-24 16:07:35 -070060import net.onrc.onos.core.matchaction.action.SetSAAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070061import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070062import net.onrc.onos.core.matchaction.match.Match;
63import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070064import net.onrc.onos.core.matchaction.match.PacketMatch;
65import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070066import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070067import net.onrc.onos.core.packet.Ethernet;
68import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070069import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070070import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070071import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070072import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070073import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070074import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070075import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070076import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070077import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070078import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070079import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070080import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070081import net.onrc.onos.core.util.IPv4Net;
Sangho Shin6d3c2f02014-10-22 10:10:55 -070082import net.onrc.onos.core.util.PortNumber;
Sangho Shin43cee112014-09-25 16:43:34 -070083import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070084
Sangho Shin43cee112014-09-25 16:43:34 -070085import org.json.JSONArray;
86import org.json.JSONException;
Saurav Dasa962a692014-10-17 14:52:38 -070087import org.projectfloodlight.openflow.protocol.OFBarrierReply;
Saurav Dasbc594a42014-09-25 20:13:50 -070088import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070089import org.projectfloodlight.openflow.types.IPv4Address;
Sangho Shine842cad2014-10-24 16:07:35 -070090import org.projectfloodlight.openflow.types.MacAddress;
Sangho Shin2f263692014-09-15 14:09:41 -070091import org.slf4j.Logger;
92import org.slf4j.LoggerFactory;
93
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070094public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -070095 ITopologyListener, IPacketListener, ISegmentRoutingService {
Sangho Shin2f263692014-09-15 14:09:41 -070096
97 private static final Logger log = LoggerFactory
98 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070099
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -0700100 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700101 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700102 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -0700103 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700104 private IRestApiService restApi;
Sangho Shin2f263692014-09-15 14:09:41 -0700105 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -0700106 private ArpHandler arpHandler;
107 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700108 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -0700109 private IThreadPoolService threadPool;
110 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -0700111 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -0700112 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700113 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700114
Sangho Shinfbc572c2014-10-02 16:37:05 -0700115 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700116 private HashMap<String, LinkData> linksDown;
117 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700118 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shinf65b4da2014-10-28 16:58:13 -0700119 private HashMap<String, SegmentRoutingPolicy> policyTable;
120 private HashMap<String, SegmentRoutingTunnel> tunnelTable;
Sangho Shin6471d202014-10-23 10:59:36 -0700121 private HashMap<Integer, HashMap<Integer, List<Integer>>> adjacencySidTable;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700122
Sangho Shine842cad2014-10-24 16:07:35 -0700123 // Flag whether transit router supports ECMP or not
Srikanth Vavilapalli8a661e72014-10-27 15:40:22 -0700124 // private boolean supportTransitECMP = true;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700125
Sangho Shine842cad2014-10-24 16:07:35 -0700126 private int testMode = 0;
Sangho Shinbce900e2014-10-07 17:13:23 -0700127
128 private int numOfEvents = 0;
129 private int numOfEventProcess = 0;
130 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700131 private long matchActionId = 0L;
Sangho Shin58182672014-10-21 13:23:38 -0700132
Sangho Shin23f898d2014-10-13 16:54:00 -0700133 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700134 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700135
Sangho Shin5b8f5452014-10-20 11:46:01 -0700136 private final int POLICY_ADD1 = 1;
137 private final int POLICY_ADD2 = 2;
138 private final int POLICY_REMOVE1 = 3;
139 private final int POLICY_REMOVE2 = 4;
Sangho Shin4b46bcd2014-10-20 15:48:47 -0700140 private final int TUNNEL_REMOVE1 = 5;
141 private final int TUNNEL_REMOVE2 = 6;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700142
143
Sangho Shin7330c032014-10-20 10:34:51 -0700144 // ************************************
145 // IFloodlightModule implementation
146 // ************************************
147
Sangho Shin2f263692014-09-15 14:09:41 -0700148 @Override
149 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700150 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
151 l.add(ISegmentRoutingService.class);
152 return l;
Sangho Shin2f263692014-09-15 14:09:41 -0700153 }
154
155 @Override
156 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700157 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
158 m.put(ISegmentRoutingService.class, this);
159 return m;
Sangho Shin2f263692014-09-15 14:09:41 -0700160 }
161
162 @Override
163 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
164 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
165
166 l.add(IFloodlightProviderService.class);
167 l.add(IConfigInfoService.class);
168 l.add(ITopologyService.class);
169 l.add(IPacketService.class);
170 l.add(IFlowPusherService.class);
171 l.add(ITopologyService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700172 l.add(IRestApiService.class);
Sangho Shin2f263692014-09-15 14:09:41 -0700173
174 return l;
175
176 }
177
178 @Override
179 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700180 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700181 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700182 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700183 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700184 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700185 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700186 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700187 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700188 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700189 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700190 linksDown = new HashMap<String, LinkData>();
191 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700192 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700193 packetService = context.getServiceImpl(IPacketService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700194 restApi = context.getServiceImpl(IRestApiService.class);
Sangho Shinf65b4da2014-10-28 16:58:13 -0700195 policyTable = new HashMap<String, SegmentRoutingPolicy>();
196 tunnelTable = new HashMap<String, SegmentRoutingTunnel>();
Sangho Shin6471d202014-10-23 10:59:36 -0700197 adjacencySidTable = new HashMap<Integer,HashMap<Integer, List<Integer>>>();
Sangho Shin2f263692014-09-15 14:09:41 -0700198
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700199 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700200 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700201
Sangho Shin99918bd2014-10-08 15:52:35 -0700202
Sangho Shin2f263692014-09-15 14:09:41 -0700203 }
204
205 @Override
206 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700207 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700208 restApi.addRestletRoutable(new SegmentRoutingWebRoutable());
Sangho Shin2f263692014-09-15 14:09:41 -0700209
Sangho Shinc8d2f592014-09-30 16:53:57 -0700210 discoveryTask = new SingletonTask(ses, new Runnable() {
211 @Override
212 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700213 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700214 }
215 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700216
217 linkAddTask = new SingletonTask(ses, new Runnable() {
218 @Override
219 public void run() {
220 delayedAddLink();
221 }
222 });
223
Sangho Shin15273b62014-10-16 22:22:05 -0700224 testTask = new SingletonTask(ses, new Runnable() {
225 @Override
226 public void run() {
227 runTest();
228 }
229 });
230
Sangho Shin5b8f5452014-10-20 11:46:01 -0700231 testMode = POLICY_ADD1;
Sangho Shin69229fb2014-10-27 16:17:04 -0700232 //testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700233 }
234
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700235 @Override
236 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700237 if (payload.getEtherType() == Ethernet.TYPE_ARP)
238 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700239 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Sangho Shin7330c032014-10-20 10:34:51 -0700240 addPacketToPacketBuffer((IPv4) payload.getPayload());
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700241 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
242 icmpHandler.processPacketIn(sw, inPort, payload);
243 else
244 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700245 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700246 else {
247 log.debug("{}", payload.toString());
248 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700249 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700250
Sangho Shin2f263692014-09-15 14:09:41 -0700251
Sangho Shin7330c032014-10-20 10:34:51 -0700252 // ************************************
253 // Topology event handlers
254 // ************************************
Sangho Shineb083032014-09-22 16:11:34 -0700255
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700256 /**
257 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700258 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700259 * @param topologyEvents the generated Topology Events
260 * @see TopologyEvents
261 */
262 public void topologyEvents(TopologyEvents topologyEvents)
263 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700264 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700265 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700266 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700267
Sangho Shin23f898d2014-10-13 16:54:00 -0700268 /**
269 * Process the multiple topology events with some delay (100MS at most for now)
270 *
271 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700272 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700273 numOfEventProcess ++;
274
Sangho Shin51625342014-10-17 09:30:48 -0700275 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
276 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
277 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
278 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
279 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
280 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
281 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700282
Sangho Shin5be3e532014-10-03 17:20:58 -0700283 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700284 // We should handle the events in the order of when they happen
285 // TODO: We need to simulate the final results of multiple events
286 // and shoot only the final state.
287 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
288 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700289
Sangho Shin5be3e532014-10-03 17:20:58 -0700290 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700291
292 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
293 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
294 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
295 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
296 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
297 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
298 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
299
300 linkEntriesAddedAll.addAll(linkEntriesAdded);
301 portEntriesAddedAll.addAll(portEntriesAdded);
302 portEntriesRemovedAll.addAll(portEntriesRemoved);
303 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
304 switchAddedAll.addAll(switchAdded);
305 switchRemovedAll.addAll(switchRemoved);
306 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700307 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700308
309 if (!portEntriesRemoved.isEmpty()) {
310 processPortRemoval(portEntriesRemoved);
311 }
312
313 if (!linkEntriesRemoved.isEmpty()) {
314 processLinkRemoval(linkEntriesRemoved);
315 }
316
317 if (!switchRemoved.isEmpty()) {
318 processSwitchRemoved(switchRemoved);
319 }
320
321 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700322 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700323 }
324
325 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700326 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700327 }
328
329 if (!portEntriesAdded.isEmpty()) {
330 processPortAdd(portEntriesAdded);
331 }
332
333 if (!switchAdded.isEmpty()) {
334 processSwitchAdd(switchAdded);
335 }
Sangho Shin51625342014-10-17 09:30:48 -0700336
Sangho Shinbce900e2014-10-07 17:13:23 -0700337 }
338
Sangho Shin23f898d2014-10-13 16:54:00 -0700339 // TODO: 100ms is enough to check both mastership removed events
340 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700341 if (!mastershipRemovedAll.isEmpty()) {
342 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700343 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700344 }
345 else {
346 HashMap<String, MastershipData> mastershipToRemove =
347 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700348 for (MastershipData ms: mastershipRemovedAll) {
349 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700350 // TODO: check ALL ports of the switch are dead ..
351 if (port.getDpid().equals(ms.getDpid())) {
352 mastershipToRemove.put(ms.getDpid().toString(), ms);
353 }
354 }
355 log.debug("Swtich {} is really down.", ms.getDpid());
356 }
357 processMastershipRemoved(mastershipToRemove.values());
358 }
359 }
360
Sangho Shinbce900e2014-10-07 17:13:23 -0700361 log.debug("num events {}, num of process {}, "
362 + "num of Population {}", numOfEvents, numOfEventProcess,
363 numOfPopulation);
364 }
365
366 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700367 * Process the SwitchAdded events from topologyMananger.
368 * It does nothing. When a switch is added, then link will be added too.
369 * LinkAdded event will handle process all re-computation.
370 *
371 * @param switchAdded
372 */
373 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
374
375 }
376
377 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700378 * Remove all ports connected to the switch removed
379 *
380 * @param mastershipRemoved master switch info removed
381 */
382 private void processMastershipRemoved(Collection<MastershipData>
383 mastershipRemoved) {
384 for (MastershipData mastership: mastershipRemoved) {
385 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
386 for (Link link: sw.getOutgoingLinks()) {
387 Port dstPort = link.getDstPort();
388 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
389 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700390 if (dstSw != null) {
391 dstSw.removePortFromGroups(dstPort.getNumber());
392 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
393 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700394 }
Sangho Shin61535402014-10-01 11:37:14 -0700395 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700396
397 linksToAdd.clear();
398 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700399 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700400
Sangho Shinbce900e2014-10-07 17:13:23 -0700401 /**
402 * Remove all ports connected to the switch removed
403 *
404 * @param switchRemoved Switch removed
405 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700406 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700407 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700408 }
409
Sangho Shin61535402014-10-01 11:37:14 -0700410 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700411 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700412 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700413 * @param portEntries
414 */
415 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700416 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700417 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700418 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700419
Sangho Shinfbc572c2014-10-02 16:37:05 -0700420 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700421 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700422 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700423 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700424 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700425 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700426 }
427 }
428
429 /**
430 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700431 * If the link to add was removed before, then we just schedule the add link
432 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700433 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700434 * @param linkEntries
435 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700436 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700437
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700438 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700439
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700440 SwitchPort srcPort = link.getSrc();
441 SwitchPort dstPort = link.getDst();
442
Sangho Shin23f898d2014-10-13 16:54:00 -0700443 String key = srcPort.getDpid().toString() +
444 dstPort.getDpid().toString();
445 if (!delayed) {
446 if (linksDown.containsKey(key)) {
447 linksToAdd.put(key, link);
448 linksDown.remove(key);
449 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
450 log.debug("Add link {} with 5 sec delay", link);
451 // TODO: What if we have multiple events of add link:
452 // one is new link add, the other one is link up for
453 // broken link? ECMPSPG function cannot deal with it for now
454 return;
455 }
456 }
457 else {
458 if (linksDown.containsKey(key)) {
459 linksToAdd.remove(key);
460 log.debug("Do not add the link {}: it is down again!", link);
461 return;
462 }
463 }
464
Sangho Shinfbc572c2014-10-02 16:37:05 -0700465 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700466 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700467 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700468 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700469
Sangho Shin815af0c2014-10-10 13:05:45 -0700470 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700471 continue;
472
473 srcSw.addPortToGroups(srcPort.getPortNumber());
474 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700475
Sangho Shin15273b62014-10-16 22:22:05 -0700476 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
477 // link);
478 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
479 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700480
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700481 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700482 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700483 }
484
485 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700486 * Check if all links are gone b/w the two switches. If all links are gone,
487 * then we need to recalculate the path. Otherwise, just report link failure
Sangho Shin370e17b2014-10-27 11:39:08 -0700488 * to the driver. IF the switches do not support ECMP in transit routers and
489 * the link removed is between transit routers, then just recompute the path
490 * regardless of ECMP.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700491 *
Sangho Shin61535402014-10-01 11:37:14 -0700492 * @param linkEntries
493 */
494 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700495 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700496 SwitchPort srcPort = link.getSrc();
497 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700498
Sangho Shinfbc572c2014-10-02 16:37:05 -0700499 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700500 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700501 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700502 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700503 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700504 /* If this link is not between two switches, ignore it */
505 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700506
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700507 srcSw.removePortFromGroups(srcPort.getPortNumber());
508 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700509 log.debug("Remove port {} from switch {}", srcPort, srcSw);
510 log.debug("Remove port {} from switch {}", dstPort, dstSw);
511
Sangho Shinf66aa262014-10-27 16:03:42 -0700512 if ((srcSw instanceof OFSwitchImplDellOSR &&
513 dstSw instanceof OFSwitchImplDellOSR) &&
Sangho Shin370e17b2014-10-27 11:39:08 -0700514 isTransitRouter(mutableTopology.getSwitch(srcPort.getDpid())) &&
515 isTransitRouter(mutableTopology.getSwitch(dstPort.getDpid()))) {
516 populateEcmpRoutingRules(false);
517 }
518 else {
519 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
520 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
521 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
522 dstPort.getDpid());
523 log.debug("All paths will recomputed regardless of the rest "
524 + "of the event");
525 populateEcmpRoutingRules(false);
526 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700527 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700528
529 String key = link.getSrc().getDpid().toString()+
530 link.getDst().getDpid().toString();
531 if (!linksDown.containsKey(key)) {
532 linksDown.put(key, link);
533 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700534 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700535
Sangho Shin61535402014-10-01 11:37:14 -0700536 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700537
Sangho Shin61535402014-10-01 11:37:14 -0700538 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700539 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700540 *
Sangho Shin61535402014-10-01 11:37:14 -0700541 * @param portEntries
542 */
543 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700544 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700545 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700546
Sangho Shinfbc572c2014-10-02 16:37:05 -0700547 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700548 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700549 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700550 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700551 log.debug("Remove port {} from switch {}", port, dpid);
552 }
Sangho Shin61535402014-10-01 11:37:14 -0700553 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700554 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700555
556 /**
Sangho Shin7330c032014-10-20 10:34:51 -0700557 * Add the link immediately
558 * The function is scheduled when link add event happens and called
559 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
560 */
561 private void delayedAddLink() {
562
563 processLinkAdd(linksToAdd.values(), true);
564
565 }
566
567
568 // ************************************
569 // ECMP shorted path routing functions
570 // ************************************
571
572 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700573 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700574 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700575 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700576 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700577 private void populateEcmpRoutingRules(boolean modified) {
578 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700579 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700580 for (Switch sw : switches) {
581 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700582 graphs.put(sw, ecmpSPG);
583 //log.debug("ECMPShortestPathGraph is computed for switch {}",
584 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700585 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700586
587 // Set adjacency routing rule for all switches
588 try {
589 populateAdjacencyncyRule(sw);
590 } catch (JSONException e) {
591 // TODO Auto-generated catch block
592 e.printStackTrace();
593 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700594 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700595 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700596 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700597
Sangho Shin204b9972014-10-22 11:08:10 -0700598 /**
599 * populate the MPLS rules to handle Adjacency IDs
600 *
601 * @param sw Switch
602 * @throws JSONException
603 */
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700604 private void populateAdjacencyncyRule(Switch sw) throws JSONException {
605 String adjInfo = sw.getStringAttribute("adjacencySids");
Sangho Shin204b9972014-10-22 11:08:10 -0700606 String nodeSidStr = sw.getStringAttribute("nodeSid");
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700607 String srcMac = sw.getStringAttribute("routerMac");
Sangho Shin204b9972014-10-22 11:08:10 -0700608 String autoAdjInfo = sw.getStringAttribute("autogenAdjSids");
609
Sangho Shinced05b62014-10-22 11:23:14 -0700610 if (autoAdjInfo == null || srcMac == null || nodeSidStr == null)
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700611 return;
612
Sangho Shinced05b62014-10-22 11:23:14 -0700613 // parse adjacency Id
Sangho Shincfef3922014-10-22 12:04:16 -0700614 HashMap<Integer, List<Integer>> adjacencyInfo = null;
Sangho Shinced05b62014-10-22 11:23:14 -0700615 if (adjInfo != null) {
Sangho Shincfef3922014-10-22 12:04:16 -0700616 adjacencyInfo = parseAdjacencySidInfo(adjInfo);
Sangho Shinced05b62014-10-22 11:23:14 -0700617 }
Sangho Shincfef3922014-10-22 12:04:16 -0700618 // parse auto generated adjacency Id
619 adjacencyInfo.putAll(parseAdjacencySidInfo(autoAdjInfo));
Sangho Shinced05b62014-10-22 11:23:14 -0700620
Sangho Shin6471d202014-10-23 10:59:36 -0700621 adjacencySidTable.put(Integer.parseInt(nodeSidStr), adjacencyInfo);
Sangho Shin204b9972014-10-22 11:08:10 -0700622
Sangho Shin6471d202014-10-23 10:59:36 -0700623 for (Integer adjId: adjacencyInfo.keySet()) {
624 List<Integer> ports = adjacencyInfo.get(adjId);
625 if (ports.size() == 1) {
626 setAdjacencyRuleOfOutput(sw, adjId, srcMac, ports.get(0));
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700627 }
628 else {
Sangho Shin6471d202014-10-23 10:59:36 -0700629 setAdjacencyRuleOfGroup(sw, adjId, ports);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700630 }
Sangho Shin6471d202014-10-23 10:59:36 -0700631 }
632 }
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700633
Sangho Shin6471d202014-10-23 10:59:36 -0700634 /**
635 * Set Adjacency Rule to MPLS table for adjacency Ids attached to multiple
636 * ports
637 *
638 * @param sw Switch
639 * @param adjId Adjacency ID
640 * @param ports List of ports assigned to the Adjacency ID
641 */
642 private void setAdjacencyRuleOfGroup(Switch sw, Integer adjId, List<Integer> ports) {
643
644 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
645 getSwId(sw.getDpid().toString()));
646
647 int groupId = -1;
648 if (sw13 != null) {
649 List<PortNumber> portList = new ArrayList<PortNumber>();
650 for (Integer port: ports)
651 portList.add(PortNumber.uint32(port));
652 groupId = sw13.createGroup(new ArrayList<Integer>(), portList);
653 }
654
655 if (groupId < 0) {
656 log.debug("Failed to create a group at driver for adj ID {}", adjId);
657 }
658
659 pushAdjRule(sw, adjId, null, null, groupId, true);
660 pushAdjRule(sw, adjId, null, null, groupId, false);
661 }
662
663 /**
664 * Set Adjacency Rule to MPLS table for adjacency Ids attached to single port
665 *
666 * @param sw Switch
667 * @param adjId Adjacency ID
668 * @param ports List of ports assigned to the Adjacency ID
669 */
670 private void setAdjacencyRuleOfOutput(Switch sw, Integer adjId, String srcMac, Integer portNo) {
671
672 Dpid dstDpid = null;
673 for (Link link: sw.getOutgoingLinks()) {
674 if (link.getSrcPort().getPortNumber().value() == portNo) {
675 dstDpid = link.getDstPort().getDpid();
676 break;
677 }
678 }
679 if (dstDpid == null) {
680 log.debug("Cannot find the destination switch for the adjacency ID {}", adjId);
681 return;
682 }
683 Switch dstSw = mutableTopology.getSwitch(dstDpid);
684 String dstMac = null;
685 if (dstSw == null) {
686 log.debug("Cannot find SW {}", dstDpid.toString());
687 return;
688 }
689 else {
690 dstMac = dstSw.getStringAttribute("routerMac");
691 }
692
693 pushAdjRule(sw, adjId, srcMac, dstMac, portNo, true); // BoS = 1
694 pushAdjRule(sw, adjId, srcMac, dstMac, portNo, false); // BoS = 0
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700695
696 }
697
Sangho Shin204b9972014-10-22 11:08:10 -0700698 /**
699 * Push the MPLS rule for Adjacency ID
700 *
701 * @param sw Switch to push the rule
702 * @param id Adjacency ID
703 * @param srcMac source MAC address
704 * @param dstMac destination MAC address
705 * @param portNo port number assigned to the ID
706 * @param bos BoS option
707 */
Sangho Shin6471d202014-10-23 10:59:36 -0700708 private void pushAdjRule(Switch sw, int id, String srcMac, String dstMac,
709 int num, boolean bos) {
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700710
711 MplsMatch mplsMatch = new MplsMatch(id, bos);
712 List<Action> actions = new ArrayList<Action>();
713
714 if (bos) {
715 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
716 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
717 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
718 actions.add(copyTtlInAction);
719 actions.add(popAction);
720 actions.add(decNwTtlAction);
721 }
722 else {
723 PopMplsAction popAction = new PopMplsAction(EthType.MPLS_UNICAST);
724 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
725 actions.add(popAction);
726 actions.add(decMplsTtlAction);
727 }
728
Sangho Shin6471d202014-10-23 10:59:36 -0700729 // Output action
730 if (srcMac != null && dstMac != null) {
Sangho Shind6d8a7e2014-10-28 14:51:03 -0700731 ModifyDstMacAction setDstAction = new ModifyDstMacAction(MACAddress.valueOf(dstMac));
732 ModifySrcMacAction setSrcAction = new ModifySrcMacAction(MACAddress.valueOf(srcMac));
Sangho Shin6471d202014-10-23 10:59:36 -0700733 OutputAction outportAction = new OutputAction(PortNumber.uint32(num));
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700734
Sangho Shin6471d202014-10-23 10:59:36 -0700735 actions.add(setDstAction);
736 actions.add(setSrcAction);
737 actions.add(outportAction);
738 }
739 // Group Action
740 else {
741 GroupAction groupAction = new GroupAction();
742 groupAction.setGroupId(num);
743 actions.add(groupAction);
744 }
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700745
746 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
747 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
748 Operator operator = Operator.ADD;
749 MatchActionOperationEntry maEntry =
750 new MatchActionOperationEntry(operator, matchAction);
751
752 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
753 getSwId(sw.getDpid().toString()));
754
755 if (sw13 != null) {
756 try {
757 //printMatchActionOperationEntry(sw, maEntry);
758 sw13.pushFlow(maEntry);
759 } catch (IOException e) {
760 e.printStackTrace();
761 }
762 }
763 }
764
Sangho Shin99918bd2014-10-08 15:52:35 -0700765 /**
766 * populate routing rules to forward packets from the switch given to
767 * all other switches.
768 *
769 * @param sw source switch
770 * @param ecmpSPG shortest path from the the source switch to all others
771 * @param modified modification flag
772 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700773 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700774 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700775
Sangho Shinfbc572c2014-10-02 16:37:05 -0700776 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
777 ecmpSPG.getAllLearnedSwitchesAndVia();
778 for (Integer itrIdx : switchVia.keySet()) {
779 //log.debug("ECMPShortestPathGraph:Switches learned in "
780 // + "Iteration{} from switch {}:",
781 // itrIdx,
782 // HexString.toHexString(sw.getDpid().value()));
783 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
784 switchVia.get(itrIdx);
785 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700786 //log.debug("ECMPShortestPathGraph:****switch {} via:",
787 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700788 String destSw = sw.getDpid().toString();
789 List<String> fwdToSw = new ArrayList<String>();
790
Sangho Shinfbc572c2014-10-02 16:37:05 -0700791 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700792 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700793 if (via.isEmpty()) {
794 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700795 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700796 else {
797 fwdToSw.add(via.get(0).toString());
798 }
Sangho Shin43cee112014-09-25 16:43:34 -0700799 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700800 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700801 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700802
803 // Send Barrier Message and make sure all rules are set
804 // before we set the rules to next routers
Saurav Dasa962a692014-10-17 14:52:38 -0700805 // TODO: barriers to all switches in this update stage
Sangho Shinfbc572c2014-10-02 16:37:05 -0700806 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
807 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700808 if (sw13 != null) {
Saurav Dasa962a692014-10-17 14:52:38 -0700809 OFBarrierReplyFuture replyFuture = null;
Sangho Shin5be3e532014-10-03 17:20:58 -0700810 try {
Saurav Dasa962a692014-10-17 14:52:38 -0700811 replyFuture = sw13.sendBarrier();
Sangho Shin5be3e532014-10-03 17:20:58 -0700812 } catch (IOException e) {
Saurav Dasa962a692014-10-17 14:52:38 -0700813 log.error("Error sending barrier request to switch {}",
814 sw13.getId(), e.getCause());
Sangho Shin5be3e532014-10-03 17:20:58 -0700815 }
Saurav Dasa962a692014-10-17 14:52:38 -0700816 OFBarrierReply br = null;
817 try {
818 br = replyFuture.get(2, TimeUnit.SECONDS);
819 } catch (TimeoutException | InterruptedException | ExecutionException e) {
820 // XXX for some reason these exceptions are not being thrown
821 }
822 if (br == null) {
823 log.warn("Did not receive barrier-reply from {}", sw13.getId());
824 // XXX take corrective action
825 }
826
Sangho Shinfbc572c2014-10-02 16:37:05 -0700827 }
828 }
829
830 }
831
Sangho Shinfbc572c2014-10-02 16:37:05 -0700832 /**
833 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700834 * Set routing rules in targetSw {forward packets to fwdToSw switches in
835 * order to send packets to destSw} - If the target switch is an edge router
836 * and final destnation switch is also an edge router, then set IP
837 * forwarding rules to subnets - If only the target switch is an edge
838 * router, then set IP forwarding rule to the transit router loopback IP
839 * address - If the target is a transit router, then just set the MPLS
840 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700841 *
Sangho Shin43cee112014-09-25 16:43:34 -0700842 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700843 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700844 * @param fwdToSw next hop switches
845 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700846 private void setRoutingRule(Switch targetSw, String destSw,
847 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700848
Sangho Shin43cee112014-09-25 16:43:34 -0700849 if (fwdToSw.isEmpty()) {
850 fwdToSw.add(destSw);
851 }
852
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700853 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700854 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
855 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700856 // We assume that there is at least one transit router b/w edge
857 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700858 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
859 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700860 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700861 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700862
Sangho Shin43cee112014-09-25 16:43:34 -0700863 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700864 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
865 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700866 // Edge router can be a transit router
867 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700868 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700869 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700870 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700871 // We assume that there is at least one transit router b/w edge
872 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700873 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
874 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700875 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
876 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700877 // Edge router can be a transit router
878 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700879 }
880 // if it is a transit router, then set rules in the MPLS table
881 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700882 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700883 }
884
885 }
886
Sangho Shinfbc572c2014-10-02 16:37:05 -0700887 /**
888 * Set IP forwarding rule to the gateway of each subnet of switches
889 *
890 * @param targetSw Switch to set rules
891 * @param subnets subnet information
892 * @param mplsLabel destination MPLS label
893 * @param fwdToSw router to forward packets to
894 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700895 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700896 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700897
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700898 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700899 new ArrayList<MatchActionOperationEntry>();
900
901 try {
902 JSONArray arry = new JSONArray(subnets);
903 for (int i = 0; i < arry.length(); i++) {
904 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700905 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
906 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700907 }
908 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700909 e.printStackTrace();
910 }
911
912 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700913 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700914 getSwId(targetSw.getDpid().toString()));
915
Sangho Shin721ca042014-10-09 13:03:40 -0700916 if (sw13 != null) {
917 try {
918 sw13.pushFlows(entries);
919 } catch (IOException e) {
920 e.printStackTrace();
921 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700922 }
923 }
924
925 }
926
Sangho Shin43cee112014-09-25 16:43:34 -0700927 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700928 * Set IP forwarding rule - If the destination is the next hop, then do not
929 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
930 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700931 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700932 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700933 * @param subnetIp Match IP address
934 * @param mplsLabel MPLS label of final destination router
935 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700936 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700937 */
938 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700939 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
940 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700941
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700942 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700943 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700944 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700945
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700946 // If destination SW is the same as the fwd SW, then do not push MPLS
947 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700948 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700949 PushMplsAction pushMplsAction = new PushMplsAction();
950 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
951 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700952 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700953
Sangho Shin62ce5c12014-10-08 16:24:40 -0700954 //actions.add(pushMplsAction);
955 //actions.add(copyTtlOutAction);
956 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700957 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700958 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700959 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700960 else {
961 String fwdToSw = fwdToSws.get(0);
962 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
963 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
964 actions.add(decTtlAction);
965 }
966 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700967 SetMplsIdAction setIdAction = new SetMplsIdAction(
968 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700969 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700970 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700971
Sangho Shin62ce5c12014-10-08 16:24:40 -0700972 //actions.add(pushMplsAction);
973 //actions.add(copyTtlOutAction);
974 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700975 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700976 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700977 }
978 }
Sangho Shin43cee112014-09-25 16:43:34 -0700979
Sangho Shin43cee112014-09-25 16:43:34 -0700980 for (String fwdSw : fwdToSws) {
981 groupAction.addSwitch(new Dpid(fwdSw));
982 }
983 actions.add(groupAction);
984
Sangho Shin99918bd2014-10-08 15:52:35 -0700985 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700986 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700987
Sangho Shin5be3e532014-10-03 17:20:58 -0700988 Operator operator = null;
989 if (modified)
990 operator = Operator.MODIFY;
991 else
992 operator = Operator.ADD;
993
Sangho Shin43cee112014-09-25 16:43:34 -0700994 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700995 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700996
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700997 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700998 getSwId(sw.getDpid().toString()));
999
Sangho Shin5be3e532014-10-03 17:20:58 -07001000 if (sw13 != null) {
1001 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001002 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -07001003 if (entries != null)
1004 entries.add(maEntry);
1005 else
1006 sw13.pushFlow(maEntry);
1007 } catch (IOException e) {
1008 e.printStackTrace();
1009 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001010 }
1011
Sangho Shin43cee112014-09-25 16:43:34 -07001012 }
1013
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001014 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001015 * Set MPLS forwarding rules to MPLS table
1016 * </p>
1017 * If the destination is the same as the next hop to forward packets then,
1018 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
1019 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
1020 * TTL of the another MPLS header.
1021 * If the next hop is not the destination, just forward packets to next
1022 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001023 *
Sangho Shin204b9972014-10-22 11:08:10 -07001024 * TODO: refactoring required
1025 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001026 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -07001027 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001028 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001029 * */
Sangho Shin5be3e532014-10-03 17:20:58 -07001030 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
1031 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -07001032
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001033 if (fwdSws.isEmpty())
1034 return;
Sangho Shin43cee112014-09-25 16:43:34 -07001035
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001036 Collection<MatchActionOperationEntry> maEntries =
1037 new ArrayList<MatchActionOperationEntry>();
1038 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -07001039
Sangho Shine842cad2014-10-24 16:07:35 -07001040 //If the next hop is the destination router, do PHP
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001041 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
Sangho Shine842cad2014-10-24 16:07:35 -07001042 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, true, true));
1043 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, true, false));
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001044 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001045 else {
Sangho Shine842cad2014-10-24 16:07:35 -07001046 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, false, true));
1047 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, false, false));
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001048 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001049 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001050 getSwId(sw.getDpid().toString()));
1051
Sangho Shin5be3e532014-10-03 17:20:58 -07001052 if (sw13 != null) {
1053 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001054 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001055 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001056 } catch (IOException e) {
1057 e.printStackTrace();
1058 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001059 }
Sangho Shin43cee112014-09-25 16:43:34 -07001060 }
1061
Sangho Shin7330c032014-10-20 10:34:51 -07001062
1063 // ************************************
1064 // Policy routing classes and functions
1065 // ************************************
1066
Fahad Naeem Khan1e712ad2014-10-27 16:48:07 -07001067 /**
Sangho Shin81655442014-10-20 14:22:46 -07001068 * Return the Tunnel table
1069 *
1070 * @return collection of TunnelInfo
1071 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001072 public Collection<SegmentRoutingTunnel> getTunnelTable() {
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001073 return this.tunnelTable.values();
Sangho Shin81655442014-10-20 14:22:46 -07001074 }
Sangho Shin204b9972014-10-22 11:08:10 -07001075
Sangho Shinf65b4da2014-10-28 16:58:13 -07001076 public Collection<SegmentRoutingPolicy> getPoclicyTable() {
Fahad Naeem Khan12fa63a2014-10-21 17:01:27 -07001077 return this.policyTable.values();
1078 }
Sangho Shin81655442014-10-20 14:22:46 -07001079
1080 /**
Sangho Shin5671cbb2014-10-20 22:35:41 -07001081 * Return router DPIDs for the tunnel
1082 *
1083 * @param tid tunnel ID
1084 * @return List of DPID
1085 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001086 public SegmentRoutingTunnel getTunnelInfo(String tid) {
1087 return tunnelTable.get(tid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001088 }
1089
1090 /**
1091 * Get the first group ID for the tunnel for specific source router
1092 * If Segment Stitching was required to create the tunnel, there are
Sangho Shinf65b4da2014-10-28 16:58:13 -07001093 * multiple source routers.
Sangho Shin5671cbb2014-10-20 22:35:41 -07001094 *
1095 * @param tunnelId ID for the tunnel
1096 * @param dpid source router DPID
1097 * @return the first group ID of the tunnel
1098 */
1099 public int getTunnelGroupId(String tunnelId, String dpid) {
Sangho Shinf65b4da2014-10-28 16:58:13 -07001100 SegmentRoutingTunnel tunnel = tunnelTable.get(tunnelId);
1101 for (TunnelRouteInfo routeInfo: tunnel.getRoutes()) {
Sangho Shin6471d202014-10-23 10:59:36 -07001102 String tunnelSrcDpid = routeInfo.getSrcSwDpid();
1103 if (tunnelSrcDpid.equals(dpid))
1104 return routeInfo.getGroupId();
1105 }
Sangho Shin5671cbb2014-10-20 22:35:41 -07001106
Sangho Shin6471d202014-10-23 10:59:36 -07001107 return -1;
Sangho Shin5671cbb2014-10-20 22:35:41 -07001108 }
1109
1110 /**
Sangho Shin15273b62014-10-16 22:22:05 -07001111 * Create a tunnel for policy routing
1112 * It delivers the node IDs of tunnels to driver.
1113 * Split the node IDs if number of IDs exceeds the limit for stitching.
1114 *
1115 * @param tunnelId Node IDs for the tunnel
1116 * @param Ids tunnel ID
1117 */
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001118 public boolean createTunnel(String tunnelId, List<Integer> labelIds) {
Sangho Shin15273b62014-10-16 22:22:05 -07001119
Sangho Shinf65b4da2014-10-28 16:58:13 -07001120 SegmentRoutingTunnel srTunnel =
1121 new SegmentRoutingTunnel(this, tunnelId, labelIds);
1122 if (srTunnel.createTunnel()) {
1123 tunnelTable.put(tunnelId, srTunnel);
1124 return true;
1125 }
1126 else {
Sangho Shin15273b62014-10-16 22:22:05 -07001127 return false;
1128 }
Sangho Shin15273b62014-10-16 22:22:05 -07001129 }
1130
Sangho Shinf65b4da2014-10-28 16:58:13 -07001131 @Override
1132 public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
1133 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
1134 Short srcPort, Short dstPort, int priority, String tid) {
Sangho Shin6471d202014-10-23 10:59:36 -07001135
Sangho Shinf65b4da2014-10-28 16:58:13 -07001136 return createPolicy(pid, srcMac, dstMac, etherType, srcIp, dstIp, ipProto,
1137 srcPort, dstPort, priority, tid, PolicyType.TUNNEL_FLOW);
Sangho Shin6471d202014-10-23 10:59:36 -07001138 }
1139
Sangho Shin15273b62014-10-16 22:22:05 -07001140 /**
1141 * Set policy table for policy routing
1142 *
1143 * @param sw
1144 * @param mplsLabel
Sangho Shin306633a2014-10-20 14:26:55 -07001145 * @return
Sangho Shin15273b62014-10-16 22:22:05 -07001146 */
Sangho Shin306633a2014-10-20 14:26:55 -07001147 public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001148 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
Sangho Shinf65b4da2014-10-28 16:58:13 -07001149 Short srcTcpPort, Short dstTcpPort, int priority, String tid,
1150 PolicyType type) {
1151
1152 // Sanity check
1153 SegmentRoutingTunnel tunnelInfo = tunnelTable.get(tid);
1154 if (tunnelInfo == null) {
1155 log.warn("Tunnel {} is not defined", tid);
1156 return false;
1157 }
Sangho Shin15273b62014-10-16 22:22:05 -07001158
Sangho Shin5b8f5452014-10-20 11:46:01 -07001159 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1160
1161 if (srcMac != null)
1162 packetBuilder.setSrcMac(srcMac);
1163 if (dstMac != null)
1164 packetBuilder.setDstMac(dstMac);
Sangho Shin58182672014-10-21 13:23:38 -07001165 if (etherType == null) // Cqpd requires the type of IPV4
1166 packetBuilder.setEtherType(Ethernet.TYPE_IPV4);
1167 else
Sangho Shin5b8f5452014-10-20 11:46:01 -07001168 packetBuilder.setEtherType(etherType);
1169 if (srcIp != null)
1170 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1171 if (dstIp != null)
1172 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1173 if (ipProto != null)
1174 packetBuilder.setIpProto(ipProto);
1175 if (srcTcpPort > 0)
1176 packetBuilder.setSrcTcpPort(srcTcpPort);
1177 if (dstTcpPort > 0)
1178 packetBuilder.setDstTcpPort(dstTcpPort);
1179 PacketMatch policyMatch = packetBuilder.build();
Sangho Shinf65b4da2014-10-28 16:58:13 -07001180
1181 if (type == PolicyType.TUNNEL_FLOW) {
1182 SegmentRoutingPolicy srPolicy =
1183 new SegmentRoutingPolicyTunnel(this,pid, type, policyMatch,
1184 priority, tid);
1185 if (srPolicy.createPolicy()) {
1186 policyTable.put(pid, srPolicy);
1187 return true;
1188 }
1189 else { log.warn("Failed to create a policy");
1190 return false;
1191 }
1192 }
1193 else {
1194 log.warn("No other policy is supported yet.");
Sangho Shin6471d202014-10-23 10:59:36 -07001195 return false;
1196 }
Sangho Shin15273b62014-10-16 22:22:05 -07001197 }
1198
Sangho Shin5b8f5452014-10-20 11:46:01 -07001199 /**
1200 * Remove all policies applied to specific tunnel.
1201 *
1202 * @param srcMac
1203 * @param dstMac
1204 * @param etherType
1205 * @param srcIp
1206 * @param dstIp
1207 * @param ipProto
1208 * @param srcTcpPort
1209 * @param dstTcpPort
1210 * @param tid
Sangho Shin306633a2014-10-20 14:26:55 -07001211 * @return
Sangho Shin5b8f5452014-10-20 11:46:01 -07001212 */
Sangho Shin306633a2014-10-20 14:26:55 -07001213 public boolean removePolicy(String pid) {
Sangho Shinf65b4da2014-10-28 16:58:13 -07001214 //Sanity check
1215 SegmentRoutingPolicy policy = policyTable.get(pid);
1216 if (policy == null) {
1217 log.warn("Cannot find the policy {}", pid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001218 return false;
Sangho Shinf65b4da2014-10-28 16:58:13 -07001219 }
1220 if (policy.removePolicy()) {
1221 policyTable.remove(pid);
1222 log.debug("Policy {} is removed.", pid);
1223 return true;
1224 }
1225 else {
1226 log.warn("Faild to remove the policy {}", pid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001227 return false;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001228 }
1229
Sangho Shine020cc32014-10-20 13:28:02 -07001230 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001231
Fahad Naeem Khan4ff83d62014-10-28 16:18:07 -07001232 public enum removeTunnelMessages{
1233 SUCCESS(0, "Tunnel is removed successfully."),
1234 ERROR_REFERENCED(1, "Can't remove tunnel as its referenced by other policy(s)"),
1235 ERROR_SWITCH(2, "Switch not found in the tunnel route"),
1236 ERROR_DRIVER(3, "Can't remove tunnel at driver"),
1237 ERROR_TUNNEL(4, "Tunnel not found");
1238
1239 private final int code;
1240 private final String description;
1241
1242 private removeTunnelMessages(int code, String description) {
1243 this.code = code;
1244 this.description = description;
1245 }
1246
1247 public String getDescription() {
1248 return this.description;
1249 }
1250
1251 public int getCode() {
1252 return this.code;
1253 }
1254
1255 @Override
1256 public String toString() {
1257 return "[" + this.code + ": " + this.description + "]";
1258 }
1259
1260 }
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001261 /**
1262 * Remove a tunnel
1263 * It removes all groups for the tunnel if the tunnel is not used for any
1264 * policy.
1265 *
1266 * @param tunnelId tunnel ID to remove
1267 */
Fahad Naeem Khan4ff83d62014-10-28 16:18:07 -07001268 public removeTunnelMessages removeTunnel(String tunnelId) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001269
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001270 // Check if the tunnel is used for any policy
Sangho Shinf65b4da2014-10-28 16:58:13 -07001271 for (SegmentRoutingPolicy policy: policyTable.values()) {
1272 if (policy.getType() == PolicyType.TUNNEL_FLOW) {
1273 String tid = ((SegmentRoutingPolicyTunnel)policy).getTunnelId();
1274 if (tid.equals(tunnelId)) {
1275 log.debug("Tunnel {} is still used for the policy {}.",
1276 policy.getPolicyId(), tunnelId);
1277 return removeTunnelMessages.ERROR_REFERENCED;
1278 }
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001279 }
1280 }
1281
Sangho Shinf65b4da2014-10-28 16:58:13 -07001282 SegmentRoutingTunnel tunnel = tunnelTable.get(tunnelId);
1283 if (tunnel == null) {
1284 log.warn("Tunnul object does not exist {}", tunnelId);
Fahad Naeem Khan4ff83d62014-10-28 16:18:07 -07001285 return removeTunnelMessages.ERROR_TUNNEL;
Sangho Shinf65b4da2014-10-28 16:58:13 -07001286 }
1287 else {
1288 if (tunnel.removeTunnel()) {
1289 tunnelTable.remove(tunnelId);
1290 log.debug("Tunnel {} was removed successfully.", tunnelId);
1291 return removeTunnelMessages.SUCCESS;
Sangho Shin5671cbb2014-10-20 22:35:41 -07001292 }
1293 else {
Sangho Shinf65b4da2014-10-28 16:58:13 -07001294 log.warn("Faild in removing the tunnel {}", tunnelId);
1295 return removeTunnelMessages.ERROR_DRIVER;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001296 }
1297 }
Sangho Shin55d00e12014-10-20 12:13:07 -07001298 }
1299
Sangho Shin7330c032014-10-20 10:34:51 -07001300 // ************************************
1301 // Utility functions
1302 // ************************************
1303
Sangho Shinf65b4da2014-10-28 16:58:13 -07001304 public long getNextMatchActionID() {
1305 return this.matchActionId++;
1306 }
Sangho Shin1a692c02014-10-23 17:05:41 -07001307
Sangho Shinf65b4da2014-10-28 16:58:13 -07001308
1309 public List<Integer> getAdacencyPorts(int nodeSid, int adjacencySid) {
Sangho Shin1a692c02014-10-23 17:05:41 -07001310 HashMap<Integer, List<Integer>> adjacencySidInfo =
Sangho Shinf65b4da2014-10-28 16:58:13 -07001311 adjacencySidTable.get(Integer.valueOf(nodeSid));
1312 if (adjacencySidInfo == null)
Sangho Shin6471d202014-10-23 10:59:36 -07001313 return null;
Sangho Shinf65b4da2014-10-28 16:58:13 -07001314 else
1315 return adjacencySidInfo.get(Integer.valueOf(adjacencySid));
Sangho Shin6471d202014-10-23 10:59:36 -07001316 }
1317
Sangho Shine842cad2014-10-24 16:07:35 -07001318 /**
1319 * Check if the node ID is the adjacency ID or not
1320 *
1321 * @param nodeId to check
1322 * @return true if the node ID is the adjacency ID, false otherwise
1323 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001324 public boolean isAdjacencySid(String nodeId) {
Sangho Shin6471d202014-10-23 10:59:36 -07001325 // XXX The rule might change
1326 if (Integer.parseInt(nodeId) > 10000)
1327 return true;
1328
1329 return false;
1330 }
1331
Sangho Shin15273b62014-10-16 22:22:05 -07001332 /**
Sangho Shinced05b62014-10-22 11:23:14 -07001333 * Returns the Adjacency IDs for the node
1334 *
1335 * @param nodeSid Node SID
Sangho Shincfef3922014-10-22 12:04:16 -07001336 * @return Collection of Adjacency ID
Sangho Shinced05b62014-10-22 11:23:14 -07001337 */
Sangho Shincfef3922014-10-22 12:04:16 -07001338 public Collection<Integer> getAdjacencyIds(int nodeSid) {
1339 HashMap<Integer, List<Integer>> adjecencyInfo =
Sangho Shin6471d202014-10-23 10:59:36 -07001340 adjacencySidTable.get(Integer.valueOf(nodeSid));
Sangho Shincfef3922014-10-22 12:04:16 -07001341
1342 return adjecencyInfo.keySet();
1343 }
1344
1345 /**
1346 * Returns the Adjacency Info for the node
1347 *
1348 * @param nodeSid Node SID
1349 * @return HashMap of <AdjacencyID, list of ports>
1350 */
1351 public HashMap<Integer, List<Integer>> getAdjacencyInfo(int nodeSid) {
Sangho Shin6471d202014-10-23 10:59:36 -07001352 return adjacencySidTable.get(Integer.valueOf(nodeSid));
Sangho Shincfef3922014-10-22 12:04:16 -07001353 }
1354
Sangho Shine842cad2014-10-24 16:07:35 -07001355 /**
1356 * Parse the adjacency jason string and build the adjacency Table
1357 *
1358 * @param adjInfo adjacency info jason string
1359 * @return HashMap<Adjacency ID, List of ports> object
1360 * @throws JSONException
1361 */
1362 private HashMap<Integer, List<Integer>> parseAdjacencySidInfo(String adjInfo)
1363 throws JSONException {
Sangho Shincfef3922014-10-22 12:04:16 -07001364 JSONArray arry = new JSONArray(adjInfo);
1365 HashMap<Integer, List<Integer>> AdjacencyInfo =
1366 new HashMap<Integer, List<Integer>>();
1367
1368 for (int i = 0; i < arry.length(); i++) {
1369 Integer adjId = (Integer) arry.getJSONObject(i).get("adjSid");
1370 JSONArray portNos = (JSONArray) arry.getJSONObject(i).get("ports");
1371 if (adjId == null || portNos == null)
1372 continue;
1373
1374 List<Integer> portNoList = new ArrayList<Integer>();
1375 for (int j = 0; j < portNos.length(); j++) {
Sangho Shin62325582014-10-24 10:36:09 -07001376 portNoList.add(Integer.valueOf(portNos.getInt(j)));
Sangho Shincfef3922014-10-22 12:04:16 -07001377 }
1378 AdjacencyInfo.put(adjId, portNoList);
1379 }
1380 return AdjacencyInfo;
Sangho Shinced05b62014-10-22 11:23:14 -07001381 }
1382
1383 /**
Sangho Shine842cad2014-10-24 16:07:35 -07001384 * Build the MatchActionOperationEntry according to the flag
1385 *
1386 * @param sw node ID to push for MPLS label
1387 * @param mplsLabel List of Switch DPIDs to forwards packets to
1388 * @param fwdSws PHP flag
1389 * @param Bos BoS flag
1390 * @param isTransitRouter
1391 * @return MatchiACtionOperationEntry object
1392 */
1393 private MatchActionOperationEntry buildMAEntry(Switch sw,
1394 String mplsLabel, List<String> fwdSws, boolean php,
1395 boolean Bos) {
1396 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), Bos);
1397 List<Action> actions = new ArrayList<Action>();
1398
1399 PopMplsAction popActionBos = new PopMplsAction(EthType.IPv4);
1400 PopMplsAction popAction = new PopMplsAction(EthType.MPLS_UNICAST);
1401 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
1402 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
1403 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1404
1405 if (php) {
1406 actions.add(copyTtlInAction);
1407 if (Bos) {
1408 actions.add(popActionBos);
1409 actions.add(decNwTtlAction);
1410 }
1411 else {
1412 actions.add(popAction);
1413 actions.add(decMplsTtlAction);
1414 }
1415 }
1416 else {
1417 actions.add(decMplsTtlAction);
1418 }
1419
Sangho Shin402354e2014-10-27 16:53:05 -07001420 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1421 getSwId(sw.getDpid().toString()));
1422 if ((sw13 instanceof OFSwitchImplDellOSR) && isTransitRouter(sw) && !php) {
Sangho Shine842cad2014-10-24 16:07:35 -07001423 PortNumber port = pickOnePort(sw, fwdSws);
1424 if (port == null) {
1425 log.warn("Failed to get a port from NeightborSet");
1426 return null;
1427 }
1428 OutputAction outputAction = new OutputAction(port);
1429 Switch destSwitch =
1430 mutableTopology.getSwitch(new Dpid(fwdSws.get(0)));
1431 MacAddress srcMac =
1432 MacAddress.of(sw.getStringAttribute("routerMac"));
1433 MacAddress dstMac =
1434 MacAddress.of(destSwitch.getStringAttribute("routerMac"));
1435 SetSAAction setSAAction = new SetSAAction(srcMac);
1436 SetDAAction setDAAction = new SetDAAction(dstMac);
1437 actions.add(outputAction);
1438 actions.add(setSAAction);
1439 actions.add(setDAAction);
1440 }
1441 else {
1442 GroupAction groupAction = new GroupAction();
1443 for (String dpid: fwdSws)
1444 groupAction.addSwitch(new Dpid(dpid));
1445 actions.add(groupAction);
1446 }
1447
1448 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
1449 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1450 Operator operator = Operator.ADD;
1451 MatchActionOperationEntry maEntry =
1452 new MatchActionOperationEntry(operator, matchAction);
1453
1454 return maEntry;
1455 }
1456
1457 /**
1458 * Pick a router from the neighbor set and return the port
1459 * connected to the router.
1460 *
1461 * @param sw source switch
1462 * @param fwdSwDpids neighbor set of the switch
1463 * @return PortNumber connected to one of the neighbors
1464 */
1465 private PortNumber pickOnePort(Switch sw, List<String> fwdSwDpids) {
1466 for (Link link: sw.getOutgoingLinks()) {
1467 if (link.getDstSwitch().getDpid().toString().equals(fwdSwDpids.get(0)))
1468 return link.getSrcPort().getNumber();
1469 }
1470
1471 return null;
1472 }
1473
1474 /**
1475 * check if the router is the transit router or not
1476 *
1477 * @param sw router switch to check
1478 * @return true if the switch is the transit router, false otherwise
1479 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001480 public boolean isTransitRouter(Switch sw) {
Sangho Shine842cad2014-10-24 16:07:35 -07001481 int i = 0;
1482 for(Switch neighbor: sw.getNeighbors()) {
1483 i++;
1484 }
1485 if (i > 1)
1486 return true;
1487 else
1488 return false;
1489 }
1490
1491 /**
Sangho Shin55908712014-10-27 15:16:48 -07001492 * Get the forwarding Switch DPIDs to send packets to a node.
1493 * If ECMP in transit routers is not supported, only one switch needs to be
1494 * selected as the neighbor set to forward packets to.
Sangho Shin15273b62014-10-16 22:22:05 -07001495 *
Sangho Shin7330c032014-10-20 10:34:51 -07001496 * @param srcSw source switch
1497 * @param nodeId destination node Id
1498 * @return list of switch DPID to forward packets to
Sangho Shin15273b62014-10-16 22:22:05 -07001499 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001500 public List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
Sangho Shin15273b62014-10-16 22:22:05 -07001501
Sangho Shin7330c032014-10-20 10:34:51 -07001502 List<Dpid> fwdSws = new ArrayList<Dpid>();
1503 Switch destSw = null;
Sangho Shin15273b62014-10-16 22:22:05 -07001504
Sangho Shin7330c032014-10-20 10:34:51 -07001505 destSw = getSwitchFromNodeId(nodeId);
1506
1507 if (destSw == null) {
1508 log.debug("Cannot find the switch with ID {}", nodeId);
1509 return null;
1510 }
1511
1512 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1513
1514 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1515 ecmpSPG.getAllLearnedSwitchesAndVia();
1516 for (Integer itrIdx : switchVia.keySet()) {
1517 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1518 switchVia.get(itrIdx);
1519 for (Switch targetSw : swViaMap.keySet()) {
1520 String destSwDpid = destSw.getDpid().toString();
1521 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1522 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1523 if (via.isEmpty()) {
1524 fwdSws.add(destSw.getDpid());
1525 }
1526 else {
Sangho Shina000c612014-10-21 14:17:59 -07001527 Dpid firstVia = via.get(via.size()-1);
1528 fwdSws.add(firstVia);
Sangho Shinf66aa262014-10-27 16:03:42 -07001529 IOF13Switch targetSw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
1530 getSwId(targetSw.getDpid().toString()));
1531 if (targetSw13 instanceof OFSwitchImplDellOSR &&
Sangho Shin55908712014-10-27 15:16:48 -07001532 isTransitRouter(targetSw) &&
1533 isTransitRouter(mutableTopology.getSwitch(firstVia))) {
1534 return fwdSws;
1535 }
Sangho Shin7330c032014-10-20 10:34:51 -07001536 }
1537 }
1538 }
1539 }
1540 }
1541
1542 return fwdSws;
Sangho Shin15273b62014-10-16 22:22:05 -07001543 }
1544
Sangho Shin7330c032014-10-20 10:34:51 -07001545 /**
1546 * Get switch for the node Id specified
1547 *
1548 * @param nodeId node ID for switch
1549 * @return Switch
1550 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001551 public Switch getSwitchFromNodeId(String nodeId) {
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001552
Sangho Shin7330c032014-10-20 10:34:51 -07001553 for (Switch sw : mutableTopology.getSwitches()) {
1554 String id = sw.getStringAttribute("nodeSid");
1555 if (id.equals(nodeId)) {
1556 return sw;
1557 }
1558 }
1559
1560 return null;
1561 }
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001562
Sangho Shin43cee112014-09-25 16:43:34 -07001563 /**
Sangho Shin7330c032014-10-20 10:34:51 -07001564 * Convert a string DPID to its Switch Id (integer)
Sangho Shinfbc572c2014-10-02 16:37:05 -07001565 *
Sangho Shin7330c032014-10-20 10:34:51 -07001566 * @param dpid
1567 * @return
Sangho Shin43cee112014-09-25 16:43:34 -07001568 */
Sangho Shin7330c032014-10-20 10:34:51 -07001569 private long getSwId(String dpid) {
Sangho Shin43cee112014-09-25 16:43:34 -07001570
Sangho Shin7330c032014-10-20 10:34:51 -07001571 long swId = 0;
Sangho Shin43cee112014-09-25 16:43:34 -07001572
Sangho Shin7330c032014-10-20 10:34:51 -07001573 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1574 if (swIdHexStr != null)
1575 swId = Integer.decode(swIdHexStr);
Sangho Shin43cee112014-09-25 16:43:34 -07001576
Sangho Shin7330c032014-10-20 10:34:51 -07001577 return swId;
1578 }
Sangho Shin43cee112014-09-25 16:43:34 -07001579
Sangho Shin7330c032014-10-20 10:34:51 -07001580 /**
1581 * Check if the switch is the edge router or not.
1582 *
1583 * @param dpid Dpid of the switch to check
1584 * @return true if it is an edge router, otherwise false
1585 */
1586 private boolean IsEdgeRouter(String dpid) {
Sangho Shin0df01982014-09-25 17:11:18 -07001587
Sangho Shin7330c032014-10-20 10:34:51 -07001588 for (Switch sw : mutableTopology.getSwitches()) {
1589 String dpidStr = sw.getDpid().toString();
1590 if (dpid.equals(dpidStr)) {
1591 /*
1592 String subnetInfo = sw.getStringAttribute("subnets");
1593 if (subnetInfo == null || subnetInfo.equals("[]")) {
1594 return false;
1595 }
1596 else
1597 return true;
1598 */
1599 String isEdge = sw.getStringAttribute("isEdgeRouter");
1600 if (isEdge != null) {
1601 if (isEdge.equals("true"))
1602 return true;
1603 else
1604 return false;
1605 }
Sangho Shin43cee112014-09-25 16:43:34 -07001606 }
1607 }
1608
Sangho Shin7330c032014-10-20 10:34:51 -07001609 return false;
Sangho Shineb083032014-09-22 16:11:34 -07001610 }
1611
1612 /**
1613 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001614 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001615 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001616 * @return MPLS label for the switch
1617 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001618 public String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001619
1620 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001621 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001622 String dpidStr = sw.getDpid().toString();
1623 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001624 mplsLabel = sw.getStringAttribute("nodeSid");
1625 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001626 }
1627 }
1628
Sangho Shineb083032014-09-22 16:11:34 -07001629 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001630 }
1631
Sangho Shineb083032014-09-22 16:11:34 -07001632 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001633 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001634 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001635 * @param addr - subnet address to match
1636 * @param addr1 - IP address to check
1637 * @return true if the IP address matches to the subnet, otherwise false
1638 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001639 public boolean netMatch(String addr, String addr1) { // addr is subnet
1640 // address and addr1 is
1641 // ip address. Function
1642 // will return true, if
1643 // addr1 is within
1644 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001645
1646 String[] parts = addr.split("/");
1647 String ip = parts[0];
1648 int prefix;
1649
1650 if (parts.length < 2) {
1651 prefix = 0;
1652 } else {
1653 prefix = Integer.parseInt(parts[1]);
1654 }
1655
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001656 Inet4Address a = null;
1657 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001658 try {
1659 a = (Inet4Address) InetAddress.getByName(ip);
1660 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001661 } catch (UnknownHostException e) {
1662 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001663
1664 byte[] b = a.getAddress();
1665 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001666 ((b[1] & 0xFF) << 16) |
1667 ((b[2] & 0xFF) << 8) |
1668 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001669
1670 byte[] b1 = a1.getAddress();
1671 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001672 ((b1[1] & 0xFF) << 16) |
1673 ((b1[2] & 0xFF) << 8) |
1674 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001675
1676 int mask = ~((1 << (32 - prefix)) - 1);
1677
1678 if ((ipInt & mask) == (ipInt1 & mask)) {
1679 return true;
1680 }
1681 else {
1682 return false;
1683 }
1684 }
Sangho Shineb083032014-09-22 16:11:34 -07001685
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001686 /**
1687 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001688 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001689 * @param sw - Switch to add the rule
1690 * @param hostIpAddress Destination host IP address
1691 * @param hostMacAddress Destination host MAC address
1692 */
Sangho Shineb083032014-09-22 16:11:34 -07001693 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1694 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
Sangho Shineb083032014-09-22 16:11:34 -07001695 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001696
Sangho Shin463bee52014-09-29 15:14:43 -07001697 /**
1698 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001699 *
Sangho Shin463bee52014-09-29 15:14:43 -07001700 * @param ipv4
1701 */
Sangho Shin7330c032014-10-20 10:34:51 -07001702 public void addPacketToPacketBuffer(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001703 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001704 }
1705
1706 /**
1707 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001708 *
Sangho Shin463bee52014-09-29 15:14:43 -07001709 * @param destIp Destination address of packets to retrieve
1710 */
1711 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1712
1713 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1714
Sangho Shin61535402014-10-01 11:37:14 -07001715 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001716 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001717 int dest = ip.getDestinationAddress();
1718 IPv4Address ip1 = IPv4Address.of(dest);
1719 IPv4Address ip2 = IPv4Address.of(destIp);
1720 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001721 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001722 }
1723 }
1724 }
1725
1726 return bufferedPackets;
1727 }
1728
Sangho Shin7330c032014-10-20 10:34:51 -07001729 /**
1730 * Get MAC address to known hosts
1731 *
1732 * @param destinationAddress IP address to get MAC address
1733 * @return MAC Address to given IP address
1734 */
1735 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
1736
1737 // Can't we get the host IP address from the TopologyService ??
1738
1739 Iterator<ArpEntry> iterator = arpEntries.iterator();
1740
1741 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
1742 byte[] ipAddressInByte = ipAddress.getBytes();
1743
1744 while (iterator.hasNext()) {
1745 ArpEntry arpEntry = iterator.next();
1746 byte[] address = arpEntry.targetIpAddress;
1747
1748 IPv4Address a = IPv4Address.of(address);
1749 IPv4Address b = IPv4Address.of(ipAddressInByte);
1750
1751 if (a.equals(b)) {
1752 log.debug("Found an arp entry");
1753 return arpEntry.targetMacAddress;
1754 }
1755 }
1756
1757 return null;
1758 }
1759
1760 /**
1761 * Send an ARP request via ArpHandler
1762 *
1763 * @param destinationAddress
1764 * @param sw
1765 * @param inPort
1766 *
1767 */
1768 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
1769 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
1770 }
1771
Sangho Shinf65b4da2014-10-28 16:58:13 -07001772 public IOF13Switch getIOF13Switch(String dpid) {
1773
1774 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
1775 getSwId(dpid));
1776
1777 return targetSw;
1778 }
1779
1780 public Switch getSwitch(String dpid) {
1781 return mutableTopology.getSwitch(new Dpid(dpid));
1782 }
1783
1784
Sangho Shin7330c032014-10-20 10:34:51 -07001785 // ************************************
1786 // Test functions
1787 // ************************************
1788
Sangho Shin55d00e12014-10-20 12:13:07 -07001789 private void runTest() {
1790
1791 if (testMode == POLICY_ADD1) {
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001792 Integer[] routeArray = {101, 105, 110};
1793 /*List<Dpid> routeList = new ArrayList<Dpid>();
Sangho Shin55d00e12014-10-20 12:13:07 -07001794 for (int i = 0; i < routeArray.length; i++) {
1795 Dpid dpid = getSwitchFromNodeId(routeArray[i]).getDpid();
1796 routeList.add(dpid);
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001797 }*/
Sangho Shin55d00e12014-10-20 12:13:07 -07001798
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001799 if (createTunnel("1", Arrays.asList(routeArray))) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001800 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1801 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1802
1803 log.debug("Set the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001804 this.createPolicy("1", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001805 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
Sangho Shine020cc32014-10-20 13:28:02 -07001806 "1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001807 testMode = POLICY_ADD2;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001808 testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001809 }
1810 else {
1811 // retry it
1812 testTask.reschedule(5, TimeUnit.SECONDS);
1813 }
1814 }
1815 else if (testMode == POLICY_ADD2) {
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001816 Integer[] routeArray = {101, 102, 103, 104, 105, 108, 110};
Sangho Shin55d00e12014-10-20 12:13:07 -07001817
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001818 if (createTunnel("2", Arrays.asList(routeArray))) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001819 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1820 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1821
1822 log.debug("Set the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001823 this.createPolicy("2", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001824 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 20000,
Sangho Shine020cc32014-10-20 13:28:02 -07001825 "2");
Fahad Naeem Khan95aa4012014-10-21 14:07:00 -07001826 //testMode = POLICY_REMOVE2;
1827 //testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001828 }
1829 else {
1830 log.debug("Retry it");
1831 testTask.reschedule(5, TimeUnit.SECONDS);
1832 }
1833 }
1834 else if (testMode == POLICY_REMOVE2){
1835 log.debug("Remove the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001836 this.removePolicy("2");
Sangho Shin55d00e12014-10-20 12:13:07 -07001837 testMode = POLICY_REMOVE1;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001838 testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001839 }
1840 else if (testMode == POLICY_REMOVE1){
1841 log.debug("Remove the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001842 this.removePolicy("1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001843
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001844 testMode = TUNNEL_REMOVE1;
1845 testTask.reschedule(5, TimeUnit.SECONDS);
1846 }
1847 else if (testMode == TUNNEL_REMOVE1) {
1848 log.debug("Remove the tunnel 1");
1849 this.removeTunnel("1");
1850
1851 testMode = TUNNEL_REMOVE2;
1852 testTask.reschedule(5, TimeUnit.SECONDS);
1853 }
1854 else if (testMode == TUNNEL_REMOVE2) {
1855 log.debug("Remove the tunnel 2");
1856 this.removeTunnel("2");
1857 log.debug("The end of test");
1858 }
Sangho Shin55d00e12014-10-20 12:13:07 -07001859 }
Sangho Shin7330c032014-10-20 10:34:51 -07001860
1861 private void runTest1() {
1862
1863 String dpid1 = "00:00:00:00:00:00:00:01";
1864 String dpid2 = "00:00:00:00:00:00:00:0a";
1865 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1866 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1867
1868 if (srcSw == null || dstSw == null) {
1869 testTask.reschedule(1, TimeUnit.SECONDS);
1870 log.debug("Switch is gone. Reschedule the test");
1871 return;
1872 }
1873
1874 String[] routeArray = {"101", "102", "105", "108", "110"};
1875 List<String> routeList = new ArrayList<String>();
1876 for (int i = 0; i < routeArray.length; i++)
1877 routeList.add(routeArray[i]);
1878
1879 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1880
1881 log.debug("Test set is {}", routeList.toString());
1882 log.debug("Result set is {}", optimizedRoute.toString());
1883
1884
1885 }
1886
Sangho Shin7330c032014-10-20 10:34:51 -07001887
Sangho Shin7330c032014-10-20 10:34:51 -07001888
1889 /**
1890 * Debugging function to print out the Match Action Entry
1891 * @param sw13
1892 *
1893 * @param maEntry
1894 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001895 public void printMatchActionOperationEntry(
Sangho Shin7330c032014-10-20 10:34:51 -07001896 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
1897
1898 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
1899
1900 MatchAction ma = maEntry.getTarget();
1901 Match m = ma.getMatch();
1902 List<Action> actions = ma.getActions();
1903
1904 if (m instanceof Ipv4Match) {
1905 logStr.append("If the IP matches with ");
1906 IPv4Net ip = ((Ipv4Match) m).getDestination();
1907 logStr.append(ip.toString());
1908 logStr.append(" then ");
1909 }
1910 else if (m instanceof MplsMatch) {
1911 logStr.append("If the MPLS label matches with ");
1912 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1913 logStr.append(mplsLabel);
1914 logStr.append(" then ");
1915 }
1916 else if (m instanceof PacketMatch) {
Sangho Shinc5a38a02014-10-28 16:09:38 -07001917 logStr.append("if the policy match is XXX then ");
Sangho Shin7330c032014-10-20 10:34:51 -07001918 }
1919
1920 logStr.append(" do { ");
1921 for (Action action : actions) {
1922 if (action instanceof CopyTtlInAction) {
1923 logStr.append("copy ttl In, ");
1924 }
1925 else if (action instanceof CopyTtlOutAction) {
1926 logStr.append("copy ttl Out, ");
1927 }
1928 else if (action instanceof DecMplsTtlAction) {
1929 logStr.append("Dec MPLS TTL , ");
1930 }
1931 else if (action instanceof GroupAction) {
1932 logStr.append("Forward packet to < ");
1933 NeighborSet dpids = ((GroupAction) action).getDpids();
1934 logStr.append(dpids.toString() + ",");
Sangho Shin7330c032014-10-20 10:34:51 -07001935 }
1936 else if (action instanceof PopMplsAction) {
1937 logStr.append("Pop MPLS label, ");
1938 }
1939 else if (action instanceof PushMplsAction) {
1940 logStr.append("Push MPLS label, ");
1941 }
1942 else if (action instanceof SetMplsIdAction) {
1943 int id = ((SetMplsIdAction) action).getMplsId();
1944 logStr.append("Set MPLS ID as " + id + ", ");
1945 }
1946 }
1947
1948 log.debug(logStr.toString());
1949
1950 }
1951
Sangho Shin7330c032014-10-20 10:34:51 -07001952 // ************************************
1953 // Unused classes and functions
1954 // ************************************
1955
1956 /**
1957 * Temporary class to to keep ARP entry
1958 *
1959 */
1960 private class ArpEntry {
1961
1962 byte[] targetMacAddress;
1963 byte[] targetIpAddress;
1964
1965 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
1966 this.targetMacAddress = macAddress;
1967 this.targetIpAddress = ipAddress;
1968 }
1969 }
1970
1971 /**
1972 * This class is used only for link recovery optimization in
1973 * modifyEcmpRoutingRules() function.
1974 * TODO: please remove if the optimization is not used at all
1975 */
1976 private class SwitchPair {
1977 private Switch src;
1978 private Switch dst;
1979
1980 public SwitchPair(Switch src, Switch dst) {
1981 this.src = src;
1982 this.dst = dst;
1983 }
1984
1985 public Switch getSource() {
1986 return src;
1987 }
1988
1989 public Switch getDestination() {
1990 return dst;
1991 }
1992 }
1993
1994 /**
1995 * Update ARP Cache using ARP packets It is used to set destination MAC
1996 * address to forward packets to known hosts. But, it will be replace with
1997 * Host information of Topology service later.
1998 *
1999 * @param arp APR packets to use for updating ARP entries
2000 */
2001 public void updateArpCache(ARP arp) {
2002
2003 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
2004 arp.getSenderProtocolAddress());
2005 // TODO: Need to check the duplication
2006 arpEntries.add(arpEntry);
2007 }
2008
2009 /**
2010 * Modify the routing rules for the lost links
2011 * - Recompute the path if the link failed is included in the path
2012 * (including src and dest).
2013 *
2014 * @param newLink
2015 */
2016 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
2017
2018 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
2019 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
2020
2021 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
2022 Switch rootSw = ecmpSPG.getRootSwitch();
2023 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
2024 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
2025 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
2026 for (Switch destSw: p.keySet()) {
2027 ArrayList<Path> path = p.get(destSw);
2028 if (checkPath(path, linkRemoved)) {
2029 boolean found = false;
2030 for (SwitchPair pair: linksToRecompute) {
2031 if (pair.getSource().getDpid() == rootSw.getDpid() &&
2032 pair.getSource().getDpid() == destSw.getDpid()) {
2033 found = true;
2034 }
2035 }
2036 if (!found) {
2037 linksToRecompute.add(new SwitchPair(rootSw, destSw));
2038 }
2039 }
2040 }
2041 }
2042 }
2043
2044 // Recompute the path for the specific route
2045 for (SwitchPair pair: linksToRecompute) {
2046
2047 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
2048 // We need the following function for optimization
2049 //ECMPShortestPathGraph ecmpSPG =
2050 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
2051 ECMPShortestPathGraph ecmpSPG =
2052 new ECMPShortestPathGraph(pair.getSource());
2053 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
2054 }
2055 }
2056
2057 /**
2058 * Optimize the mpls label
2059 * The feature will be used only for policy of "avoid a specific switch".
2060 * Check route to each router in route backward.
2061 * If there is only one route to the router and the routers are included in
2062 * the route, remove the id from the path.
2063 * A-B-C-D-E => A-B-C-D-E -> A-E
2064 * | | => A-B-H-I -> A-I
Sangho Shin5b8f5452014-10-20 11:46:01 -07002065 * F-G-H-I => A-D-I > A-D-I
Sangho Shin7330c032014-10-20 10:34:51 -07002066 */
2067 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
2068
2069 List<String> optimizedPath = new ArrayList<String>();
2070 optimizedPath.addAll(route);
2071 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
2072
2073 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
2074 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
2075 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
2076 for (Switch s: p.keySet()) {
2077 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
2078 ArrayList<Path> ecmpPaths = p.get(s);
2079 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
2080 for (Path path: ecmpPaths) {
2081 for (LinkData link: path) {
2082 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
2083 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
2084 if (optimizedPath.contains(srcId)) {
2085 optimizedPath.remove(srcId);
2086 }
2087 if (optimizedPath.contains(dstId)) {
2088 optimizedPath.remove(dstId);
2089 }
2090 }
2091 }
2092 }
2093 }
2094 }
2095 }
2096
2097 return optimizedPath;
2098
2099 }
2100
2101 /**
2102 * Check if the path is affected from the link removed
2103 *
2104 * @param path Path to check
2105 * @param linkRemoved link removed
2106 * @return true if the path contains the link removed
2107 */
2108 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
2109
2110 for (Path ppp: path) {
2111 // TODO: need to check if this is a bidirectional or
2112 // unidirectional
2113 for (LinkData link: ppp) {
2114 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
2115 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
2116 return true;
2117 }
2118 }
2119
2120 return false;
2121 }
Sangho Shin15273b62014-10-16 22:22:05 -07002122
2123
Sangho Shinf65b4da2014-10-28 16:58:13 -07002124
Sangho Shin2f263692014-09-15 14:09:41 -07002125}