blob: 93e535231178162661e5390188cc301c4c8b2b14 [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;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070036import net.onrc.onos.apps.segmentrouting.web.SegmentRoutingWebRoutable;
Sangho Shin2f263692014-09-15 14:09:41 -070037import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070038import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070039import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070040import net.onrc.onos.core.matchaction.MatchAction;
41import net.onrc.onos.core.matchaction.MatchActionId;
42import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070043import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070044import net.onrc.onos.core.matchaction.action.Action;
45import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
46import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
47import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
48import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
49import net.onrc.onos.core.matchaction.action.GroupAction;
Sangho Shin6d3c2f02014-10-22 10:10:55 -070050import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
51import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
52import net.onrc.onos.core.matchaction.action.OutputAction;
Sangho Shin43cee112014-09-25 16:43:34 -070053import net.onrc.onos.core.matchaction.action.PopMplsAction;
54import net.onrc.onos.core.matchaction.action.PushMplsAction;
55import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070056import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070057import net.onrc.onos.core.matchaction.match.Match;
58import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070059import net.onrc.onos.core.matchaction.match.PacketMatch;
60import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070061import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070062import net.onrc.onos.core.packet.Ethernet;
63import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070064import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070065import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070066import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070067import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070068import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070069import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070070import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070071import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070072import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070073import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070074import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070075import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070076import net.onrc.onos.core.util.IPv4Net;
Sangho Shin6d3c2f02014-10-22 10:10:55 -070077import net.onrc.onos.core.util.PortNumber;
Sangho Shin43cee112014-09-25 16:43:34 -070078import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070079
Sangho Shin43cee112014-09-25 16:43:34 -070080import org.json.JSONArray;
81import org.json.JSONException;
Saurav Dasa962a692014-10-17 14:52:38 -070082import org.projectfloodlight.openflow.protocol.OFBarrierReply;
Saurav Dasbc594a42014-09-25 20:13:50 -070083import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070084import org.projectfloodlight.openflow.types.IPv4Address;
85import org.slf4j.Logger;
86import org.slf4j.LoggerFactory;
87
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070088public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -070089 ITopologyListener, IPacketListener, ISegmentRoutingService {
Sangho Shin2f263692014-09-15 14:09:41 -070090
91 private static final Logger log = LoggerFactory
92 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070093
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -070094 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070095 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070096 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070097 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070098 private IRestApiService restApi;
Sangho Shin2f263692014-09-15 14:09:41 -070099 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -0700100 private ArpHandler arpHandler;
101 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700102 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -0700103 private IThreadPoolService threadPool;
104 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -0700105 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -0700106 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700107 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700108
Sangho Shinfbc572c2014-10-02 16:37:05 -0700109 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700110 private HashMap<String, LinkData> linksDown;
111 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700112 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shine020cc32014-10-20 13:28:02 -0700113 private HashMap<String, PolicyInfo> policyTable;
Sangho Shin81655442014-10-20 14:22:46 -0700114 private HashMap<String, TunnelInfo> tunnelTable;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700115
116 private int testMode = 0;
117
Sangho Shinbce900e2014-10-07 17:13:23 -0700118
119 private int numOfEvents = 0;
120 private int numOfEventProcess = 0;
121 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700122 private long matchActionId = 0L;
Sangho Shin58182672014-10-21 13:23:38 -0700123
Sangho Shin23f898d2014-10-13 16:54:00 -0700124 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700125 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700126
Sangho Shin5b8f5452014-10-20 11:46:01 -0700127 private final int POLICY_ADD1 = 1;
128 private final int POLICY_ADD2 = 2;
129 private final int POLICY_REMOVE1 = 3;
130 private final int POLICY_REMOVE2 = 4;
Sangho Shin4b46bcd2014-10-20 15:48:47 -0700131 private final int TUNNEL_REMOVE1 = 5;
132 private final int TUNNEL_REMOVE2 = 6;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700133
134
Sangho Shin7330c032014-10-20 10:34:51 -0700135 // ************************************
136 // IFloodlightModule implementation
137 // ************************************
138
Sangho Shin2f263692014-09-15 14:09:41 -0700139 @Override
140 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700141 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
142 l.add(ISegmentRoutingService.class);
143 return l;
Sangho Shin2f263692014-09-15 14:09:41 -0700144 }
145
146 @Override
147 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700148 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
149 m.put(ISegmentRoutingService.class, this);
150 return m;
Sangho Shin2f263692014-09-15 14:09:41 -0700151 }
152
153 @Override
154 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
155 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
156
157 l.add(IFloodlightProviderService.class);
158 l.add(IConfigInfoService.class);
159 l.add(ITopologyService.class);
160 l.add(IPacketService.class);
161 l.add(IFlowPusherService.class);
162 l.add(ITopologyService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700163 l.add(IRestApiService.class);
Sangho Shin2f263692014-09-15 14:09:41 -0700164
165 return l;
166
167 }
168
169 @Override
170 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700171 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700172 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700173 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700174 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700175 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700176 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700177 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700178 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700179 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700180 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700181 linksDown = new HashMap<String, LinkData>();
182 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700183 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700184 packetService = context.getServiceImpl(IPacketService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700185 restApi = context.getServiceImpl(IRestApiService.class);
Sangho Shine020cc32014-10-20 13:28:02 -0700186 policyTable = new HashMap<String, PolicyInfo>();
Sangho Shin81655442014-10-20 14:22:46 -0700187 tunnelTable = new HashMap<String, TunnelInfo>();
Sangho Shin2f263692014-09-15 14:09:41 -0700188
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700189 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700190 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700191
Sangho Shin99918bd2014-10-08 15:52:35 -0700192
Sangho Shin2f263692014-09-15 14:09:41 -0700193 }
194
195 @Override
196 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700197 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700198 restApi.addRestletRoutable(new SegmentRoutingWebRoutable());
Sangho Shin2f263692014-09-15 14:09:41 -0700199
Sangho Shinc8d2f592014-09-30 16:53:57 -0700200 discoveryTask = new SingletonTask(ses, new Runnable() {
201 @Override
202 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700203 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700204 }
205 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700206
207 linkAddTask = new SingletonTask(ses, new Runnable() {
208 @Override
209 public void run() {
210 delayedAddLink();
211 }
212 });
213
Sangho Shin15273b62014-10-16 22:22:05 -0700214 testTask = new SingletonTask(ses, new Runnable() {
215 @Override
216 public void run() {
217 runTest();
218 }
219 });
220
Sangho Shin5b8f5452014-10-20 11:46:01 -0700221 testMode = POLICY_ADD1;
Fahad Naeem Khan95aa4012014-10-21 14:07:00 -0700222 testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700223 }
224
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700225 @Override
226 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700227 if (payload.getEtherType() == Ethernet.TYPE_ARP)
228 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700229 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Sangho Shin7330c032014-10-20 10:34:51 -0700230 addPacketToPacketBuffer((IPv4) payload.getPayload());
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700231 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
232 icmpHandler.processPacketIn(sw, inPort, payload);
233 else
234 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700235 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700236 else {
237 log.debug("{}", payload.toString());
238 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700239 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700240
Sangho Shin2f263692014-09-15 14:09:41 -0700241
Sangho Shin7330c032014-10-20 10:34:51 -0700242 // ************************************
243 // Topology event handlers
244 // ************************************
Sangho Shineb083032014-09-22 16:11:34 -0700245
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700246 /**
247 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700248 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700249 * @param topologyEvents the generated Topology Events
250 * @see TopologyEvents
251 */
252 public void topologyEvents(TopologyEvents topologyEvents)
253 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700254 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700255 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700256 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700257
Sangho Shin23f898d2014-10-13 16:54:00 -0700258 /**
259 * Process the multiple topology events with some delay (100MS at most for now)
260 *
261 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700262 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700263 numOfEventProcess ++;
264
Sangho Shin51625342014-10-17 09:30:48 -0700265 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
266 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
267 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
268 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
269 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
270 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
271 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700272
Sangho Shin5be3e532014-10-03 17:20:58 -0700273 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700274 // We should handle the events in the order of when they happen
275 // TODO: We need to simulate the final results of multiple events
276 // and shoot only the final state.
277 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
278 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700279
Sangho Shin5be3e532014-10-03 17:20:58 -0700280 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700281
282 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
283 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
284 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
285 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
286 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
287 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
288 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
289
290 linkEntriesAddedAll.addAll(linkEntriesAdded);
291 portEntriesAddedAll.addAll(portEntriesAdded);
292 portEntriesRemovedAll.addAll(portEntriesRemoved);
293 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
294 switchAddedAll.addAll(switchAdded);
295 switchRemovedAll.addAll(switchRemoved);
296 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700297 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700298
299 if (!portEntriesRemoved.isEmpty()) {
300 processPortRemoval(portEntriesRemoved);
301 }
302
303 if (!linkEntriesRemoved.isEmpty()) {
304 processLinkRemoval(linkEntriesRemoved);
305 }
306
307 if (!switchRemoved.isEmpty()) {
308 processSwitchRemoved(switchRemoved);
309 }
310
311 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700312 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700313 }
314
315 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700316 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700317 }
318
319 if (!portEntriesAdded.isEmpty()) {
320 processPortAdd(portEntriesAdded);
321 }
322
323 if (!switchAdded.isEmpty()) {
324 processSwitchAdd(switchAdded);
325 }
Sangho Shin51625342014-10-17 09:30:48 -0700326
Sangho Shinbce900e2014-10-07 17:13:23 -0700327 }
328
Sangho Shin23f898d2014-10-13 16:54:00 -0700329 // TODO: 100ms is enough to check both mastership removed events
330 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700331 if (!mastershipRemovedAll.isEmpty()) {
332 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700333 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700334 }
335 else {
336 HashMap<String, MastershipData> mastershipToRemove =
337 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700338 for (MastershipData ms: mastershipRemovedAll) {
339 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700340 // TODO: check ALL ports of the switch are dead ..
341 if (port.getDpid().equals(ms.getDpid())) {
342 mastershipToRemove.put(ms.getDpid().toString(), ms);
343 }
344 }
345 log.debug("Swtich {} is really down.", ms.getDpid());
346 }
347 processMastershipRemoved(mastershipToRemove.values());
348 }
349 }
350
Sangho Shinbce900e2014-10-07 17:13:23 -0700351 log.debug("num events {}, num of process {}, "
352 + "num of Population {}", numOfEvents, numOfEventProcess,
353 numOfPopulation);
354 }
355
356 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700357 * Process the SwitchAdded events from topologyMananger.
358 * It does nothing. When a switch is added, then link will be added too.
359 * LinkAdded event will handle process all re-computation.
360 *
361 * @param switchAdded
362 */
363 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
364
365 }
366
367 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700368 * Remove all ports connected to the switch removed
369 *
370 * @param mastershipRemoved master switch info removed
371 */
372 private void processMastershipRemoved(Collection<MastershipData>
373 mastershipRemoved) {
374 for (MastershipData mastership: mastershipRemoved) {
375 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
376 for (Link link: sw.getOutgoingLinks()) {
377 Port dstPort = link.getDstPort();
378 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
379 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700380 if (dstSw != null) {
381 dstSw.removePortFromGroups(dstPort.getNumber());
382 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
383 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700384 }
Sangho Shin61535402014-10-01 11:37:14 -0700385 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700386
387 linksToAdd.clear();
388 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700389 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700390
Sangho Shinbce900e2014-10-07 17:13:23 -0700391 /**
392 * Remove all ports connected to the switch removed
393 *
394 * @param switchRemoved Switch removed
395 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700396 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700397 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700398 }
399
Sangho Shin61535402014-10-01 11:37:14 -0700400 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700401 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700402 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700403 * @param portEntries
404 */
405 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700406 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700407 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700408 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700409
Sangho Shinfbc572c2014-10-02 16:37:05 -0700410 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700411 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700412 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700413 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700414 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700415 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700416 }
417 }
418
419 /**
420 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700421 * If the link to add was removed before, then we just schedule the add link
422 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700423 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700424 * @param linkEntries
425 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700426 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700427
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700428 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700429
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700430 SwitchPort srcPort = link.getSrc();
431 SwitchPort dstPort = link.getDst();
432
Sangho Shin23f898d2014-10-13 16:54:00 -0700433 String key = srcPort.getDpid().toString() +
434 dstPort.getDpid().toString();
435 if (!delayed) {
436 if (linksDown.containsKey(key)) {
437 linksToAdd.put(key, link);
438 linksDown.remove(key);
439 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
440 log.debug("Add link {} with 5 sec delay", link);
441 // TODO: What if we have multiple events of add link:
442 // one is new link add, the other one is link up for
443 // broken link? ECMPSPG function cannot deal with it for now
444 return;
445 }
446 }
447 else {
448 if (linksDown.containsKey(key)) {
449 linksToAdd.remove(key);
450 log.debug("Do not add the link {}: it is down again!", link);
451 return;
452 }
453 }
454
Sangho Shinfbc572c2014-10-02 16:37:05 -0700455 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700456 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700457 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700458 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700459
Sangho Shin815af0c2014-10-10 13:05:45 -0700460 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700461 continue;
462
463 srcSw.addPortToGroups(srcPort.getPortNumber());
464 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700465
Sangho Shin15273b62014-10-16 22:22:05 -0700466 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
467 // link);
468 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
469 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700470
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700471 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700472 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700473 }
474
475 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700476 * Check if all links are gone b/w the two switches. If all links are gone,
477 * then we need to recalculate the path. Otherwise, just report link failure
478 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700479 *
Sangho Shin61535402014-10-01 11:37:14 -0700480 * @param linkEntries
481 */
482 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700483 boolean recomputationRequired = false;
484
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700485 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700486 SwitchPort srcPort = link.getSrc();
487 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700488
Sangho Shinfbc572c2014-10-02 16:37:05 -0700489 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700490 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700491 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700492 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700493 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700494 /* If this link is not between two switches, ignore it */
495 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700496
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700497 srcSw.removePortFromGroups(srcPort.getPortNumber());
498 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700499 log.debug("Remove port {} from switch {}", srcPort, srcSw);
500 log.debug("Remove port {} from switch {}", dstPort, dstSw);
501
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700502 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
503 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700504 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700505 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700506 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700507 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700508 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700509 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700510
511 String key = link.getSrc().getDpid().toString()+
512 link.getDst().getDpid().toString();
513 if (!linksDown.containsKey(key)) {
514 linksDown.put(key, link);
515 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700516 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700517
518 if (recomputationRequired)
519 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700520 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700521
Sangho Shin61535402014-10-01 11:37:14 -0700522 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700523 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700524 *
Sangho Shin61535402014-10-01 11:37:14 -0700525 * @param portEntries
526 */
527 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700528 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700529 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700530
Sangho Shinfbc572c2014-10-02 16:37:05 -0700531 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700532 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700533 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700534 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700535 log.debug("Remove port {} from switch {}", port, dpid);
536 }
Sangho Shin61535402014-10-01 11:37:14 -0700537 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700538 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700539
540 /**
Sangho Shin7330c032014-10-20 10:34:51 -0700541 * Add the link immediately
542 * The function is scheduled when link add event happens and called
543 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
544 */
545 private void delayedAddLink() {
546
547 processLinkAdd(linksToAdd.values(), true);
548
549 }
550
551
552 // ************************************
553 // ECMP shorted path routing functions
554 // ************************************
555
556 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700557 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700558 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700559 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700560 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700561 private void populateEcmpRoutingRules(boolean modified) {
562 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700563 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700564 for (Switch sw : switches) {
565 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700566 graphs.put(sw, ecmpSPG);
567 //log.debug("ECMPShortestPathGraph is computed for switch {}",
568 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700569 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700570
571 // Set adjacency routing rule for all switches
572 try {
573 populateAdjacencyncyRule(sw);
574 } catch (JSONException e) {
575 // TODO Auto-generated catch block
576 e.printStackTrace();
577 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700578 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700579 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700580 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700581
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700582 private void populateAdjacencyncyRule(Switch sw) throws JSONException {
583 String adjInfo = sw.getStringAttribute("adjacencySids");
584 String srcMac = sw.getStringAttribute("routerMac");
585 if (adjInfo == null || srcMac == null)
586 return;
587
588 JSONArray arry = new JSONArray(adjInfo);
589 for (int i = 0; i < arry.length(); i++) {
590 Object a = arry.getJSONObject(i);
591 Integer adjId = (Integer) arry.getJSONObject(i).get("adjSid");
592 Integer portNo = (Integer) arry.getJSONObject(i).get("portNo");
593 if (adjId == null || portNo == null)
594 continue;
595
596 Dpid dstDpid = null;
597 for (Link link: sw.getOutgoingLinks()) {
598 if (link.getSrcPort().getPortNumber().value() == portNo) {
599 dstDpid = link.getDstPort().getDpid();
600 break;
601 }
602 }
603 if (dstDpid == null) {
604 log.debug("Cannot find the destination switch for the adjacency ID {}", adjId);
605 continue;
606 }
607 Switch dstSw = mutableTopology.getSwitch(dstDpid);
608 String dstMac = null;
609 if (dstSw == null) {
610 log.debug("Cannot find SW {}", dstDpid.toString());
611 continue;
612 }
613 else {
614 dstMac = dstSw.getStringAttribute("routerMac");
615 }
616
617 setAdjRule(sw, adjId, srcMac, dstMac, portNo, true); // BoS = 1
618 setAdjRule(sw, adjId, srcMac, dstMac, portNo, false); // BoS = 0
619 }
620
621 }
622
623
624 private void setAdjRule(Switch sw, int id, String srcMac, String dstMac, int portNo,
625 boolean bos) {
626
627 MplsMatch mplsMatch = new MplsMatch(id, bos);
628 List<Action> actions = new ArrayList<Action>();
629
630 if (bos) {
631 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
632 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
633 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
634 actions.add(copyTtlInAction);
635 actions.add(popAction);
636 actions.add(decNwTtlAction);
637 }
638 else {
639 PopMplsAction popAction = new PopMplsAction(EthType.MPLS_UNICAST);
640 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
641 actions.add(popAction);
642 actions.add(decMplsTtlAction);
643 }
644
645 ModifyDstMacAction setDstAction = new ModifyDstMacAction(MACAddress.valueOf(srcMac));
646 ModifySrcMacAction setSrcAction = new ModifySrcMacAction(MACAddress.valueOf(dstMac));
647 OutputAction outportAction = new OutputAction(PortNumber.uint32(portNo));
648
649 actions.add(setDstAction);
650 actions.add(setSrcAction);
651 actions.add(outportAction);
652
653 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
654 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
655 Operator operator = Operator.ADD;
656 MatchActionOperationEntry maEntry =
657 new MatchActionOperationEntry(operator, matchAction);
658
659 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
660 getSwId(sw.getDpid().toString()));
661
662 if (sw13 != null) {
663 try {
664 //printMatchActionOperationEntry(sw, maEntry);
665 sw13.pushFlow(maEntry);
666 } catch (IOException e) {
667 e.printStackTrace();
668 }
669 }
670 }
671
672
Sangho Shin99918bd2014-10-08 15:52:35 -0700673 /**
674 * populate routing rules to forward packets from the switch given to
675 * all other switches.
676 *
677 * @param sw source switch
678 * @param ecmpSPG shortest path from the the source switch to all others
679 * @param modified modification flag
680 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700681 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700682 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700683
Sangho Shinfbc572c2014-10-02 16:37:05 -0700684 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
685 ecmpSPG.getAllLearnedSwitchesAndVia();
686 for (Integer itrIdx : switchVia.keySet()) {
687 //log.debug("ECMPShortestPathGraph:Switches learned in "
688 // + "Iteration{} from switch {}:",
689 // itrIdx,
690 // HexString.toHexString(sw.getDpid().value()));
691 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
692 switchVia.get(itrIdx);
693 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700694 //log.debug("ECMPShortestPathGraph:****switch {} via:",
695 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700696 String destSw = sw.getDpid().toString();
697 List<String> fwdToSw = new ArrayList<String>();
698
Sangho Shinfbc572c2014-10-02 16:37:05 -0700699 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700700 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700701 if (via.isEmpty()) {
702 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700703 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700704 else {
705 fwdToSw.add(via.get(0).toString());
706 }
Sangho Shin43cee112014-09-25 16:43:34 -0700707 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700708 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700709 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700710
711 // Send Barrier Message and make sure all rules are set
712 // before we set the rules to next routers
Saurav Dasa962a692014-10-17 14:52:38 -0700713 // TODO: barriers to all switches in this update stage
Sangho Shinfbc572c2014-10-02 16:37:05 -0700714 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
715 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700716 if (sw13 != null) {
Saurav Dasa962a692014-10-17 14:52:38 -0700717 OFBarrierReplyFuture replyFuture = null;
Sangho Shin5be3e532014-10-03 17:20:58 -0700718 try {
Saurav Dasa962a692014-10-17 14:52:38 -0700719 replyFuture = sw13.sendBarrier();
Sangho Shin5be3e532014-10-03 17:20:58 -0700720 } catch (IOException e) {
Saurav Dasa962a692014-10-17 14:52:38 -0700721 log.error("Error sending barrier request to switch {}",
722 sw13.getId(), e.getCause());
Sangho Shin5be3e532014-10-03 17:20:58 -0700723 }
Saurav Dasa962a692014-10-17 14:52:38 -0700724 OFBarrierReply br = null;
725 try {
726 br = replyFuture.get(2, TimeUnit.SECONDS);
727 } catch (TimeoutException | InterruptedException | ExecutionException e) {
728 // XXX for some reason these exceptions are not being thrown
729 }
730 if (br == null) {
731 log.warn("Did not receive barrier-reply from {}", sw13.getId());
732 // XXX take corrective action
733 }
734
Sangho Shinfbc572c2014-10-02 16:37:05 -0700735 }
736 }
737
738 }
739
Sangho Shinfbc572c2014-10-02 16:37:05 -0700740 /**
741 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700742 * Set routing rules in targetSw {forward packets to fwdToSw switches in
743 * order to send packets to destSw} - If the target switch is an edge router
744 * and final destnation switch is also an edge router, then set IP
745 * forwarding rules to subnets - If only the target switch is an edge
746 * router, then set IP forwarding rule to the transit router loopback IP
747 * address - If the target is a transit router, then just set the MPLS
748 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700749 *
Sangho Shin43cee112014-09-25 16:43:34 -0700750 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700751 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700752 * @param fwdToSw next hop switches
753 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700754 private void setRoutingRule(Switch targetSw, String destSw,
755 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700756
Sangho Shin43cee112014-09-25 16:43:34 -0700757 if (fwdToSw.isEmpty()) {
758 fwdToSw.add(destSw);
759 }
760
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700761 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700762 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
763 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700764 // We assume that there is at least one transit router b/w edge
765 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700766 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
767 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700768 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700769 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700770
Sangho Shin43cee112014-09-25 16:43:34 -0700771 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700772 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
773 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700774 // Edge router can be a transit router
775 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700776 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700777 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700778 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700779 // We assume that there is at least one transit router b/w edge
780 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700781 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
782 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700783 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
784 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700785 // Edge router can be a transit router
786 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700787 }
788 // if it is a transit router, then set rules in the MPLS table
789 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700790 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700791 }
792
793 }
794
Sangho Shinfbc572c2014-10-02 16:37:05 -0700795 /**
796 * Set IP forwarding rule to the gateway of each subnet of switches
797 *
798 * @param targetSw Switch to set rules
799 * @param subnets subnet information
800 * @param mplsLabel destination MPLS label
801 * @param fwdToSw router to forward packets to
802 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700803 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700804 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700805
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700806 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700807 new ArrayList<MatchActionOperationEntry>();
808
809 try {
810 JSONArray arry = new JSONArray(subnets);
811 for (int i = 0; i < arry.length(); i++) {
812 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700813 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
814 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700815 }
816 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700817 e.printStackTrace();
818 }
819
820 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700821 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700822 getSwId(targetSw.getDpid().toString()));
823
Sangho Shin721ca042014-10-09 13:03:40 -0700824 if (sw13 != null) {
825 try {
826 sw13.pushFlows(entries);
827 } catch (IOException e) {
828 e.printStackTrace();
829 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700830 }
831 }
832
833 }
834
Sangho Shin43cee112014-09-25 16:43:34 -0700835 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700836 * Set IP forwarding rule - If the destination is the next hop, then do not
837 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
838 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700839 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700840 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700841 * @param subnetIp Match IP address
842 * @param mplsLabel MPLS label of final destination router
843 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700844 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700845 */
846 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700847 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
848 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700849
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700850 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700851 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700852 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700853
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700854 // If destination SW is the same as the fwd SW, then do not push MPLS
855 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700856 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700857 PushMplsAction pushMplsAction = new PushMplsAction();
858 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
859 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700860 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700861
Sangho Shin62ce5c12014-10-08 16:24:40 -0700862 //actions.add(pushMplsAction);
863 //actions.add(copyTtlOutAction);
864 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700865 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700866 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700867 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700868 else {
869 String fwdToSw = fwdToSws.get(0);
870 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
871 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
872 actions.add(decTtlAction);
873 }
874 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700875 SetMplsIdAction setIdAction = new SetMplsIdAction(
876 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700877 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700878 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700879
Sangho Shin62ce5c12014-10-08 16:24:40 -0700880 //actions.add(pushMplsAction);
881 //actions.add(copyTtlOutAction);
882 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700883 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700884 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700885 }
886 }
Sangho Shin43cee112014-09-25 16:43:34 -0700887
Sangho Shin43cee112014-09-25 16:43:34 -0700888 for (String fwdSw : fwdToSws) {
889 groupAction.addSwitch(new Dpid(fwdSw));
890 }
891 actions.add(groupAction);
892
Sangho Shin99918bd2014-10-08 15:52:35 -0700893 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700894 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700895
Sangho Shin5be3e532014-10-03 17:20:58 -0700896 Operator operator = null;
897 if (modified)
898 operator = Operator.MODIFY;
899 else
900 operator = Operator.ADD;
901
Sangho Shin43cee112014-09-25 16:43:34 -0700902 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700903 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700904
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700905 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700906 getSwId(sw.getDpid().toString()));
907
Sangho Shin5be3e532014-10-03 17:20:58 -0700908 if (sw13 != null) {
909 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700910 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700911 if (entries != null)
912 entries.add(maEntry);
913 else
914 sw13.pushFlow(maEntry);
915 } catch (IOException e) {
916 e.printStackTrace();
917 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700918 }
919
Sangho Shin43cee112014-09-25 16:43:34 -0700920 }
921
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700922 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700923 * Set MPLS forwarding rules to MPLS table
924 * </p>
925 * If the destination is the same as the next hop to forward packets then,
926 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
927 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
928 * TTL of the another MPLS header.
929 * If the next hop is not the destination, just forward packets to next
930 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700931 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700932 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700933 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700934 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700935 * */
Sangho Shin5be3e532014-10-03 17:20:58 -0700936 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
937 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -0700938
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700939 if (fwdSws.isEmpty())
940 return;
Sangho Shin43cee112014-09-25 16:43:34 -0700941
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700942 Collection<MatchActionOperationEntry> maEntries =
943 new ArrayList<MatchActionOperationEntry>();
944 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -0700945
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700946 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
947 // One rule for Bos = 1
948 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
949 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700950
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700951 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
952 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
953 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
954
955 actions.add(copyTtlInAction);
956 actions.add(popAction);
957 actions.add(decNwTtlAction);
958
959 GroupAction groupAction = new GroupAction();
960 groupAction.addSwitch(new Dpid(fwdSw1));
961 actions.add(groupAction);
962
963 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
964 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
965 Operator operator = Operator.ADD;
966 MatchActionOperationEntry maEntry =
967 new MatchActionOperationEntry(operator, matchAction);
968 maEntries.add(maEntry);
969
970 // One rule for Bos = 0
Sangho Shin23f898d2014-10-13 16:54:00 -0700971 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700972 List<Action> actionsBos = new ArrayList<Action>();
Sangho Shin15273b62014-10-16 22:22:05 -0700973 PopMplsAction popActionBos = new PopMplsAction(EthType.MPLS_UNICAST);
974 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
975
976 actionsBos.add(copyTtlInAction);
977 actionsBos.add(popActionBos);
978 actionsBos.add(decMplsTtlAction);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700979 actionsBos.add(groupAction);
980
981 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
982 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
983 MatchActionOperationEntry maEntryBos =
984 new MatchActionOperationEntry(operator, matchActionBos);
985 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700986 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700987 else {
988 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
989 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700990
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700991 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
992 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700993
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700994 GroupAction groupAction = new GroupAction();
995 for (String fwdSw : fwdSws)
996 groupAction.addSwitch(new Dpid(fwdSw));
997 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -0700998
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700999 MatchAction matchAction = new MatchAction(new MatchActionId(
1000 matchActionId++),
1001 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1002 Operator operator = Operator.ADD;
1003 MatchActionOperationEntry maEntry =
1004 new MatchActionOperationEntry(operator, matchAction);
1005 maEntries.add(maEntry);
Sangho Shine2e9bcd2014-10-13 15:14:18 -07001006
1007 // BoS = 1
1008 MplsMatch mplsMatchBoS = new MplsMatch(Integer.parseInt(mplsLabel), true);
1009 List<Action> actionsBoS = new ArrayList<Action>();
1010
1011 DecMplsTtlAction decMplsTtlActionBoS = new DecMplsTtlAction(1);
1012 actionsBoS.add(decMplsTtlActionBoS);
1013
1014 GroupAction groupActionBoS = new GroupAction();
1015 for (String fwdSw : fwdSws)
1016 groupActionBoS.addSwitch(new Dpid(fwdSw));
1017 actionsBoS.add(groupActionBoS);
1018
1019 MatchAction matchActionBos = new MatchAction(new MatchActionId(
1020 matchActionId++),
1021 new SwitchPort((long) 0, (short) 0), mplsMatchBoS, actionsBoS);
1022 MatchActionOperationEntry maEntryBoS =
1023 new MatchActionOperationEntry(operator, matchActionBos);
1024 maEntries.add(maEntryBoS);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001025 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001026 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001027 getSwId(sw.getDpid().toString()));
1028
Sangho Shin5be3e532014-10-03 17:20:58 -07001029 if (sw13 != null) {
1030 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001031 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001032 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001033 } catch (IOException e) {
1034 e.printStackTrace();
1035 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001036 }
Sangho Shin43cee112014-09-25 16:43:34 -07001037 }
1038
Sangho Shin7330c032014-10-20 10:34:51 -07001039
1040 // ************************************
1041 // Policy routing classes and functions
1042 // ************************************
1043
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001044 public class PolicyInfo {
Sangho Shin5b8f5452014-10-20 11:46:01 -07001045
Sangho Shin58182672014-10-21 13:23:38 -07001046 public final int TYPE_EXPLICIT = 1;
1047 public final int TYPE_AVOID = 2;
1048
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001049 private String policyId;
1050 private PacketMatch match;
1051 private int priority;
1052 private String tunnelId;
Sangho Shin58182672014-10-21 13:23:38 -07001053 private int type;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001054
Sangho Shin58182672014-10-21 13:23:38 -07001055 public PolicyInfo(String pid, int type, PacketMatch match, int priority,
1056 String tid) {
1057 this.policyId = pid;
1058 this.match = match;
1059 this.priority = priority;
1060 this.tunnelId = tid;
1061 this.type = type;
1062 }
Fahad Naeem Khan95aa4012014-10-21 14:07:00 -07001063
1064 public PolicyInfo(String pid, PacketMatch match, int priority,
1065 String tid) {
1066 this.policyId = pid;
1067 this.match = match;
1068 this.priority = priority;
1069 this.tunnelId = tid;
Fahad Naeem Khan788895c2014-10-21 19:00:24 -07001070 this.type = 0;
Fahad Naeem Khan95aa4012014-10-21 14:07:00 -07001071 }
1072 public String getPolicyId(){
1073 return this.policyId;
1074 }
1075 public PacketMatch getMatch(){
1076 return this.match;
1077 }
1078 public int getPriority(){
1079 return this.priority;
1080 }
1081 public String getTunnelId(){
1082 return this.tunnelId;
1083 }
1084 public int getType(){
1085 return this.type;
1086 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001087 }
1088
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001089 public class TunnelInfo {
1090 private String tunnelId;
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001091 private List<Integer> labelIds;
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001092 private List<TunnelRouteInfo> routes;
Sangho Shin81655442014-10-20 14:22:46 -07001093
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001094 public TunnelInfo(String tid, List<Integer> labelIds, List<TunnelRouteInfo> routes) {
Sangho Shin81655442014-10-20 14:22:46 -07001095 this.tunnelId = tid;
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001096 this.labelIds = labelIds;
Sangho Shin81655442014-10-20 14:22:46 -07001097 this.routes = routes;
1098 }
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001099 public String getTunnelId(){
1100 return this.tunnelId;
1101 }
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001102
1103 public List<Integer> getLabelids() {
1104 return this.labelIds;
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001105 }
1106 public List<TunnelRouteInfo> getRoutes(){
1107 return this.routes;
1108 }
Sangho Shin81655442014-10-20 14:22:46 -07001109 }
1110
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001111 public class TunnelRouteInfo {
Sangho Shin7330c032014-10-20 10:34:51 -07001112
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001113 private String srcSwDpid;
1114 private List<Dpid> fwdSwDpids;
1115 private List<String> route;
Sangho Shin7330c032014-10-20 10:34:51 -07001116
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001117 public TunnelRouteInfo() {
Sangho Shin7330c032014-10-20 10:34:51 -07001118 fwdSwDpids = new ArrayList<Dpid>();
1119 route = new ArrayList<String>();
1120 }
1121
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001122 private void setSrcDpid(String dpid) {
Sangho Shin7330c032014-10-20 10:34:51 -07001123 this.srcSwDpid = dpid;
1124 }
1125
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001126 private void setFwdSwDpid(List<Dpid> dpid) {
Sangho Shin7330c032014-10-20 10:34:51 -07001127 this.fwdSwDpids = dpid;
1128 }
1129
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001130 private void addRoute(String id) {
Sangho Shin7330c032014-10-20 10:34:51 -07001131 route.add(id);
1132 }
1133
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001134 private void setRoute(List<String> r) {
Sangho Shin7330c032014-10-20 10:34:51 -07001135 this.route = r;
1136 }
1137
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001138 public String getSrcSwDpid() {
Sangho Shin7330c032014-10-20 10:34:51 -07001139 return this.srcSwDpid;
1140 }
1141
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001142 public List<Dpid> getFwdSwDpid() {
Sangho Shin7330c032014-10-20 10:34:51 -07001143 return this.fwdSwDpids;
1144 }
1145
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001146 public List<String> getRoute() {
Sangho Shin7330c032014-10-20 10:34:51 -07001147 return this.route;
1148 }
1149 }
1150
Sangho Shin15273b62014-10-16 22:22:05 -07001151 /**
Sangho Shin81655442014-10-20 14:22:46 -07001152 * Return the Tunnel table
1153 *
1154 * @return collection of TunnelInfo
1155 */
1156 public Collection<TunnelInfo> getTunnelTable() {
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001157 return this.tunnelTable.values();
Sangho Shin81655442014-10-20 14:22:46 -07001158 }
Fahad Naeem Khan12fa63a2014-10-21 17:01:27 -07001159
1160 public Collection<PolicyInfo> getPoclicyTable() {
1161 return this.policyTable.values();
1162 }
Sangho Shin81655442014-10-20 14:22:46 -07001163
1164 /**
Sangho Shin5671cbb2014-10-20 22:35:41 -07001165 * Return router DPIDs for the tunnel
1166 *
1167 * @param tid tunnel ID
1168 * @return List of DPID
1169 */
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001170 public List<Integer> getTunnelInfo(String tid) {
Sangho Shin5671cbb2014-10-20 22:35:41 -07001171 TunnelInfo tunnelInfo = tunnelTable.get(tid);
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001172 return tunnelInfo.labelIds;
Sangho Shin5671cbb2014-10-20 22:35:41 -07001173
1174 }
1175
1176 /**
1177 * Get the first group ID for the tunnel for specific source router
1178 * If Segment Stitching was required to create the tunnel, there are
1179 * mutiple source routers.
1180 *
1181 * @param tunnelId ID for the tunnel
1182 * @param dpid source router DPID
1183 * @return the first group ID of the tunnel
1184 */
1185 public int getTunnelGroupId(String tunnelId, String dpid) {
1186 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1187 getSwId(dpid));
1188
1189 if (sw13 == null) {
1190 return -1;
1191 }
1192 else {
1193 return sw13.getTunnelGroupId(tunnelId);
1194 }
1195 }
1196
1197 /**
Sangho Shin15273b62014-10-16 22:22:05 -07001198 * Create a tunnel for policy routing
1199 * It delivers the node IDs of tunnels to driver.
1200 * Split the node IDs if number of IDs exceeds the limit for stitching.
1201 *
1202 * @param tunnelId Node IDs for the tunnel
1203 * @param Ids tunnel ID
1204 */
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001205 public boolean createTunnel(String tunnelId, List<Integer> labelIds) {
Sangho Shin15273b62014-10-16 22:22:05 -07001206
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001207 if (labelIds.isEmpty() || labelIds.size() < 2) {
Sangho Shin15273b62014-10-16 22:22:05 -07001208 log.debug("Wrong tunnel information");
1209 return false;
1210 }
1211
Sangho Shin55d00e12014-10-20 12:13:07 -07001212 List<String> Ids = new ArrayList<String>();
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001213 for (Integer label : labelIds) {
1214 Ids.add(label.toString());
Sangho Shin55d00e12014-10-20 12:13:07 -07001215 }
1216
Sangho Shin81655442014-10-20 14:22:46 -07001217 List<TunnelRouteInfo> stitchingRule = getStitchingRule(Ids);
Sangho Shin15273b62014-10-16 22:22:05 -07001218 if (stitchingRule == null) {
1219 log.debug("Failed to get the policy rule.");
1220 return false;
1221 }
Sangho Shin81655442014-10-20 14:22:46 -07001222 for (TunnelRouteInfo route: stitchingRule) {
Sangho Shin15273b62014-10-16 22:22:05 -07001223
1224 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin81655442014-10-20 14:22:46 -07001225 getSwId(route.srcSwDpid));
Sangho Shin15273b62014-10-16 22:22:05 -07001226
1227 if (targetSw == null) {
Sangho Shin81655442014-10-20 14:22:46 -07001228 log.debug("Switch {} is gone.", route.srcSwDpid);
Sangho Shin15273b62014-10-16 22:22:05 -07001229 return false;
1230 }
1231
1232 NeighborSet ns = new NeighborSet();
1233 for (Dpid dpid: route.getFwdSwDpid())
1234 ns.addDpid(dpid);
1235
1236 printTunnelInfo(targetSw, tunnelId, route.getRoute(), ns);
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001237 targetSw.createTunnel(tunnelId, route.getRoute(), ns);
Sangho Shin15273b62014-10-16 22:22:05 -07001238 }
1239
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001240 TunnelInfo tunnelInfo = new TunnelInfo(tunnelId, labelIds, stitchingRule);
Sangho Shin81655442014-10-20 14:22:46 -07001241 tunnelTable.put(tunnelId, tunnelInfo);
Sangho Shin15273b62014-10-16 22:22:05 -07001242
1243 return true;
1244 }
1245
1246 /**
1247 * Set policy table for policy routing
1248 *
1249 * @param sw
1250 * @param mplsLabel
Sangho Shin306633a2014-10-20 14:26:55 -07001251 * @return
Sangho Shin15273b62014-10-16 22:22:05 -07001252 */
Sangho Shin306633a2014-10-20 14:26:55 -07001253 public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001254 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
Sangho Shine020cc32014-10-20 13:28:02 -07001255 Short srcTcpPort, Short dstTcpPort, int priority, String tid) {
Sangho Shin15273b62014-10-16 22:22:05 -07001256
Sangho Shin5b8f5452014-10-20 11:46:01 -07001257 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1258
1259 if (srcMac != null)
1260 packetBuilder.setSrcMac(srcMac);
1261 if (dstMac != null)
1262 packetBuilder.setDstMac(dstMac);
Sangho Shin58182672014-10-21 13:23:38 -07001263 if (etherType == null) // Cqpd requires the type of IPV4
1264 packetBuilder.setEtherType(Ethernet.TYPE_IPV4);
1265 else
Sangho Shin5b8f5452014-10-20 11:46:01 -07001266 packetBuilder.setEtherType(etherType);
1267 if (srcIp != null)
1268 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1269 if (dstIp != null)
1270 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1271 if (ipProto != null)
1272 packetBuilder.setIpProto(ipProto);
1273 if (srcTcpPort > 0)
1274 packetBuilder.setSrcTcpPort(srcTcpPort);
1275 if (dstTcpPort > 0)
1276 packetBuilder.setDstTcpPort(dstTcpPort);
1277 PacketMatch policyMatch = packetBuilder.build();
Sangho Shin81655442014-10-20 14:22:46 -07001278 TunnelInfo tunnelInfo = tunnelTable.get(tid);
1279 List<TunnelRouteInfo> routes = tunnelInfo.routes;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001280
Sangho Shin81655442014-10-20 14:22:46 -07001281 for (TunnelRouteInfo route : routes) {
Sangho Shin15273b62014-10-16 22:22:05 -07001282 List<Action> actions = new ArrayList<>();
1283 GroupAction groupAction = new GroupAction();
Sangho Shin81655442014-10-20 14:22:46 -07001284 groupAction.setTunnelId(tid);
Sangho Shin15273b62014-10-16 22:22:05 -07001285 actions.add(groupAction);
1286
1287 MatchAction matchAction = new MatchAction(new MatchActionId(
1288 matchActionId++),
Sangho Shin5b8f5452014-10-20 11:46:01 -07001289 new SwitchPort((long) 0, (short) 0), policyMatch, priority,
1290 actions);
Sangho Shin15273b62014-10-16 22:22:05 -07001291 MatchActionOperationEntry maEntry =
1292 new MatchActionOperationEntry(Operator.ADD, matchAction);
1293
1294 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin81655442014-10-20 14:22:46 -07001295 getSwId(route.srcSwDpid));
Sangho Shin15273b62014-10-16 22:22:05 -07001296
1297 if (sw13 != null) {
1298 printMatchActionOperationEntry(sw13, maEntry);
1299 try {
1300 sw13.pushFlow(maEntry);
1301 } catch (IOException e) {
1302 e.printStackTrace();
Sangho Shin306633a2014-10-20 14:26:55 -07001303 return false;
Sangho Shin15273b62014-10-16 22:22:05 -07001304 }
1305 }
1306 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001307
1308 PolicyInfo policyInfo = new PolicyInfo(pid, policyMatch, priority, tid);
Sangho Shine020cc32014-10-20 13:28:02 -07001309 policyTable.put(pid, policyInfo);
Sangho Shin306633a2014-10-20 14:26:55 -07001310
1311 return true;
Sangho Shin15273b62014-10-16 22:22:05 -07001312 }
1313
1314 /**
Sangho Shin1ad7be02014-10-20 16:56:49 -07001315 * Split the nodes IDs into multiple tunnel if Segment Stitching is required.
1316 * We assume that the first node ID is the one of source router, and the last
1317 * node ID is that of the destination router.
Sangho Shin15273b62014-10-16 22:22:05 -07001318 *
Sangho Shin1ad7be02014-10-20 16:56:49 -07001319 * @param route list of node IDs
1320 * @return List of the TunnelRoutInfo
Sangho Shin15273b62014-10-16 22:22:05 -07001321 */
Sangho Shin81655442014-10-20 14:22:46 -07001322 private List<TunnelRouteInfo> getStitchingRule(List<String> route) {
Sangho Shin15273b62014-10-16 22:22:05 -07001323
1324 if (route.isEmpty() || route.size() < 2)
1325 return null;
1326
Sangho Shin81655442014-10-20 14:22:46 -07001327 List<TunnelRouteInfo> rules = new ArrayList<TunnelRouteInfo>();
Sangho Shin15273b62014-10-16 22:22:05 -07001328
1329 Switch srcSw = this.getSwitchFromNodeId(route.get(0));
1330 String srcDpid = srcSw.getDpid().toString();
1331
1332 if (route.size() <= MAX_NUM_LABELS+1) {
Sangho Shin58182672014-10-21 13:23:38 -07001333 boolean match =false;
1334 TunnelRouteInfo routeInfo = new TunnelRouteInfo();
1335 routeInfo.setSrcDpid(srcSw.getDpid().toString());
1336 String nodeId = route.get(1);
Sangho Shina000c612014-10-21 14:17:59 -07001337 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
Fahad Naeem Khan95aa4012014-10-21 14:07:00 -07001338 if (fwdSwDpids == null){
1339 return null;
1340 }
Sangho Shin58182672014-10-21 13:23:38 -07001341 for (Dpid dpid: fwdSwDpids) {
1342 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1343 List<Dpid> fwdSws = new ArrayList<Dpid>();
1344 fwdSws.add(dpid);
1345 routeInfo.setFwdSwDpid(fwdSws);
1346 match = true;
1347 break;
1348 }
1349 }
1350 route.remove(0); // remove source router from the list
1351 if (match) {
1352 route.remove(0);
1353 }
1354 else {
1355 routeInfo.setFwdSwDpid(fwdSwDpids);
1356 }
1357 routeInfo.setRoute(route);
1358 rules.add(routeInfo);
Sangho Shin15273b62014-10-16 22:22:05 -07001359 return rules;
1360 }
1361
1362 int i = 0;
Sangho Shine020cc32014-10-20 13:28:02 -07001363 TunnelRouteInfo routeInfo = new TunnelRouteInfo();
Sangho Shin15273b62014-10-16 22:22:05 -07001364 boolean checkNeighbor = true;
1365
1366 for (String nodeId: route) {
Sangho Shin1ad7be02014-10-20 16:56:49 -07001367 // First node ID is always the source router
Sangho Shin15273b62014-10-16 22:22:05 -07001368 if (i == 0) {
1369 routeInfo.setSrcDpid(srcDpid);
1370 srcSw = getSwitchFromNodeId(nodeId);
1371 i++;
1372 }
Sangho Shin58182672014-10-21 13:23:38 -07001373 else if (i == 1 && checkNeighbor) {
1374 // Check if next node is the neighbor SW of the source SW
1375 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw,
1376 nodeId);
1377 if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
1378 log.debug("There is no route from node {} to node {}",
1379 srcSw.getDpid(), nodeId);
1380 return null;
Sangho Shin15273b62014-10-16 22:22:05 -07001381 }
Sangho Shin58182672014-10-21 13:23:38 -07001382 // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
1383 boolean match = false;
1384 for (Dpid dpid: fwdSwDpids) {
1385 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1386 List<Dpid> fwdSws = new ArrayList<Dpid>();
1387 fwdSws.add(dpid);
1388 routeInfo.setFwdSwDpid(fwdSws);
1389 match = true;
1390 break;
1391 }
1392 }
1393 if (!match) {
Sangho Shin15273b62014-10-16 22:22:05 -07001394 routeInfo.addRoute(nodeId);
Sangho Shin58182672014-10-21 13:23:38 -07001395 routeInfo.setFwdSwDpid(fwdSwDpids);
Sangho Shin15273b62014-10-16 22:22:05 -07001396 i++;
1397 }
Sangho Shin58182672014-10-21 13:23:38 -07001398 // we check only the next node ID of the source router
1399 checkNeighbor = false;
Sangho Shin15273b62014-10-16 22:22:05 -07001400 }
1401 else {
1402 routeInfo.addRoute(nodeId);
1403 i++;
1404 }
1405
Sangho Shin1ad7be02014-10-20 16:56:49 -07001406 // If the number of labels reaches the limit, start over the procedure
Sangho Shin15273b62014-10-16 22:22:05 -07001407 if (i == MAX_NUM_LABELS+1) {
Sangho Shin81655442014-10-20 14:22:46 -07001408 rules.add(routeInfo);
Sangho Shine020cc32014-10-20 13:28:02 -07001409 routeInfo = new TunnelRouteInfo();
Sangho Shin15273b62014-10-16 22:22:05 -07001410 srcSw = getSwitchFromNodeId(nodeId);
1411 srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
1412 routeInfo.setSrcDpid(srcDpid);
1413 i = 1;
1414 checkNeighbor = true;
1415 }
1416 }
1417
1418 if (i < MAX_NUM_LABELS+1) {
Sangho Shin81655442014-10-20 14:22:46 -07001419 rules.add(routeInfo);
Sangho Shin15273b62014-10-16 22:22:05 -07001420 }
1421
1422 return rules;
1423 }
1424
Sangho Shin5b8f5452014-10-20 11:46:01 -07001425 /**
1426 * Remove all policies applied to specific tunnel.
1427 *
1428 * @param srcMac
1429 * @param dstMac
1430 * @param etherType
1431 * @param srcIp
1432 * @param dstIp
1433 * @param ipProto
1434 * @param srcTcpPort
1435 * @param dstTcpPort
1436 * @param tid
Sangho Shin306633a2014-10-20 14:26:55 -07001437 * @return
Sangho Shin5b8f5452014-10-20 11:46:01 -07001438 */
Sangho Shin306633a2014-10-20 14:26:55 -07001439 public boolean removePolicy(String pid) {
Sangho Shine020cc32014-10-20 13:28:02 -07001440 PolicyInfo policyInfo = policyTable.get(pid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001441 if (policyInfo == null)
1442 return false;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001443 PacketMatch policyMatch = policyInfo.match;
Sangho Shine020cc32014-10-20 13:28:02 -07001444 String tid = policyInfo.tunnelId;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001445 int priority = policyInfo.priority;
1446
1447 List<Action> actions = new ArrayList<>();
1448 int gropuId = 0; // dummy group ID
1449 GroupAction groupAction = new GroupAction();
1450 groupAction.setGroupId(gropuId);
1451 actions.add(groupAction);
1452
1453 MatchAction matchAction = new MatchAction(new MatchActionId(
1454 matchActionId++),
1455 new SwitchPort((long) 0, (short) 0), policyMatch, priority,
1456 actions);
1457 MatchActionOperationEntry maEntry =
1458 new MatchActionOperationEntry(Operator.REMOVE, matchAction);
1459
Sangho Shin81655442014-10-20 14:22:46 -07001460 TunnelInfo tunnelInfo = tunnelTable.get(tid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001461 if (tunnelInfo == null)
1462 return false;
Sangho Shin81655442014-10-20 14:22:46 -07001463 List<TunnelRouteInfo> routes = tunnelInfo.routes;
1464
1465 for (TunnelRouteInfo route : routes) {
Sangho Shin5b8f5452014-10-20 11:46:01 -07001466 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin81655442014-10-20 14:22:46 -07001467 getSwId(route.srcSwDpid));
Sangho Shin5b8f5452014-10-20 11:46:01 -07001468
Sangho Shin5671cbb2014-10-20 22:35:41 -07001469 if (sw13 == null) {
1470 return false;
1471 }
1472 else {
Sangho Shin5b8f5452014-10-20 11:46:01 -07001473 printMatchActionOperationEntry(sw13, maEntry);
1474 try {
1475 sw13.pushFlow(maEntry);
1476 } catch (IOException e) {
1477 e.printStackTrace();
1478 log.debug("policy remove failed due to pushFlow() exception");
Sangho Shin306633a2014-10-20 14:26:55 -07001479 return false;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001480 }
1481 }
1482 }
1483
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001484 policyTable.remove(pid);
Sangho Shin5b8f5452014-10-20 11:46:01 -07001485 log.debug("Policy {} is removed.", pid);
Sangho Shin306633a2014-10-20 14:26:55 -07001486 return true;
Sangho Shine020cc32014-10-20 13:28:02 -07001487 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001488
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001489 /**
1490 * Remove a tunnel
1491 * It removes all groups for the tunnel if the tunnel is not used for any
1492 * policy.
1493 *
1494 * @param tunnelId tunnel ID to remove
1495 */
Sangho Shin306633a2014-10-20 14:26:55 -07001496 public boolean removeTunnel(String tunnelId) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001497
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001498 // Check if the tunnel is used for any policy
1499 for (PolicyInfo policyInfo: policyTable.values()) {
Sangho Shina000c612014-10-21 14:17:59 -07001500 if (policyInfo.tunnelId.equals(tunnelId)) {
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001501 log.debug("Tunnel {} is still used for the policy {}.",
1502 policyInfo.policyId, tunnelId);
1503 return false;
1504 }
1505 }
1506
1507 TunnelInfo tunnelInfo = tunnelTable.get(tunnelId);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001508 if (tunnelInfo == null)
1509 return false;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001510
1511 List<TunnelRouteInfo> routes = tunnelInfo.routes;
1512 for (TunnelRouteInfo route: routes) {
1513 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1514 getSwId(route.srcSwDpid));
1515
Sangho Shin5671cbb2014-10-20 22:35:41 -07001516 if (sw13 == null) {
1517 return false;
1518 }
1519 else {
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001520 sw13.removeTunnel(tunnelId);
1521 }
1522 }
1523
1524 tunnelTable.remove(tunnelId);
1525 log.debug("Tunnel {} was removed ", tunnelId);
1526
Sangho Shin306633a2014-10-20 14:26:55 -07001527 return true;
Sangho Shin55d00e12014-10-20 12:13:07 -07001528 }
1529
Sangho Shin7330c032014-10-20 10:34:51 -07001530 // ************************************
1531 // Utility functions
1532 // ************************************
1533
Sangho Shin15273b62014-10-16 22:22:05 -07001534 /**
Sangho Shin7330c032014-10-20 10:34:51 -07001535 * Get the forwarding Switch DPIDs to send packets to a node
Sangho Shin15273b62014-10-16 22:22:05 -07001536 *
Sangho Shin7330c032014-10-20 10:34:51 -07001537 * @param srcSw source switch
1538 * @param nodeId destination node Id
1539 * @return list of switch DPID to forward packets to
Sangho Shin15273b62014-10-16 22:22:05 -07001540 */
Sangho Shin7330c032014-10-20 10:34:51 -07001541 private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
Sangho Shin15273b62014-10-16 22:22:05 -07001542
Sangho Shin7330c032014-10-20 10:34:51 -07001543 List<Dpid> fwdSws = new ArrayList<Dpid>();
1544 Switch destSw = null;
Sangho Shin15273b62014-10-16 22:22:05 -07001545
Sangho Shin7330c032014-10-20 10:34:51 -07001546 destSw = getSwitchFromNodeId(nodeId);
1547
1548 if (destSw == null) {
1549 log.debug("Cannot find the switch with ID {}", nodeId);
1550 return null;
1551 }
1552
1553 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1554
1555 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1556 ecmpSPG.getAllLearnedSwitchesAndVia();
1557 for (Integer itrIdx : switchVia.keySet()) {
1558 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1559 switchVia.get(itrIdx);
1560 for (Switch targetSw : swViaMap.keySet()) {
1561 String destSwDpid = destSw.getDpid().toString();
1562 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1563 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1564 if (via.isEmpty()) {
1565 fwdSws.add(destSw.getDpid());
1566 }
1567 else {
Sangho Shina000c612014-10-21 14:17:59 -07001568 Dpid firstVia = via.get(via.size()-1);
1569 fwdSws.add(firstVia);
Sangho Shin7330c032014-10-20 10:34:51 -07001570 }
1571 }
1572 }
1573 }
1574 }
1575
1576 return fwdSws;
Sangho Shin15273b62014-10-16 22:22:05 -07001577 }
1578
Sangho Shin7330c032014-10-20 10:34:51 -07001579 /**
1580 * Get switch for the node Id specified
1581 *
1582 * @param nodeId node ID for switch
1583 * @return Switch
1584 */
1585 private Switch getSwitchFromNodeId(String nodeId) {
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001586
Sangho Shin7330c032014-10-20 10:34:51 -07001587 for (Switch sw : mutableTopology.getSwitches()) {
1588 String id = sw.getStringAttribute("nodeSid");
1589 if (id.equals(nodeId)) {
1590 return sw;
1591 }
1592 }
1593
1594 return null;
1595 }
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001596
Sangho Shin43cee112014-09-25 16:43:34 -07001597 /**
Sangho Shin7330c032014-10-20 10:34:51 -07001598 * Convert a string DPID to its Switch Id (integer)
Sangho Shinfbc572c2014-10-02 16:37:05 -07001599 *
Sangho Shin7330c032014-10-20 10:34:51 -07001600 * @param dpid
1601 * @return
Sangho Shin43cee112014-09-25 16:43:34 -07001602 */
Sangho Shin7330c032014-10-20 10:34:51 -07001603 private long getSwId(String dpid) {
Sangho Shin43cee112014-09-25 16:43:34 -07001604
Sangho Shin7330c032014-10-20 10:34:51 -07001605 long swId = 0;
Sangho Shin43cee112014-09-25 16:43:34 -07001606
Sangho Shin7330c032014-10-20 10:34:51 -07001607 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1608 if (swIdHexStr != null)
1609 swId = Integer.decode(swIdHexStr);
Sangho Shin43cee112014-09-25 16:43:34 -07001610
Sangho Shin7330c032014-10-20 10:34:51 -07001611 return swId;
1612 }
Sangho Shin43cee112014-09-25 16:43:34 -07001613
Sangho Shin7330c032014-10-20 10:34:51 -07001614 /**
1615 * Check if the switch is the edge router or not.
1616 *
1617 * @param dpid Dpid of the switch to check
1618 * @return true if it is an edge router, otherwise false
1619 */
1620 private boolean IsEdgeRouter(String dpid) {
Sangho Shin0df01982014-09-25 17:11:18 -07001621
Sangho Shin7330c032014-10-20 10:34:51 -07001622 for (Switch sw : mutableTopology.getSwitches()) {
1623 String dpidStr = sw.getDpid().toString();
1624 if (dpid.equals(dpidStr)) {
1625 /*
1626 String subnetInfo = sw.getStringAttribute("subnets");
1627 if (subnetInfo == null || subnetInfo.equals("[]")) {
1628 return false;
1629 }
1630 else
1631 return true;
1632 */
1633 String isEdge = sw.getStringAttribute("isEdgeRouter");
1634 if (isEdge != null) {
1635 if (isEdge.equals("true"))
1636 return true;
1637 else
1638 return false;
1639 }
Sangho Shin43cee112014-09-25 16:43:34 -07001640 }
1641 }
1642
Sangho Shin7330c032014-10-20 10:34:51 -07001643 return false;
Sangho Shineb083032014-09-22 16:11:34 -07001644 }
1645
1646 /**
1647 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001648 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001649 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001650 * @return MPLS label for the switch
1651 */
Sangho Shin43cee112014-09-25 16:43:34 -07001652 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001653
1654 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001655 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001656 String dpidStr = sw.getDpid().toString();
1657 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001658 mplsLabel = sw.getStringAttribute("nodeSid");
1659 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001660 }
1661 }
1662
Sangho Shineb083032014-09-22 16:11:34 -07001663 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001664 }
1665
Sangho Shineb083032014-09-22 16:11:34 -07001666 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001667 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001668 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001669 * @param addr - subnet address to match
1670 * @param addr1 - IP address to check
1671 * @return true if the IP address matches to the subnet, otherwise false
1672 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001673 public boolean netMatch(String addr, String addr1) { // addr is subnet
1674 // address and addr1 is
1675 // ip address. Function
1676 // will return true, if
1677 // addr1 is within
1678 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001679
1680 String[] parts = addr.split("/");
1681 String ip = parts[0];
1682 int prefix;
1683
1684 if (parts.length < 2) {
1685 prefix = 0;
1686 } else {
1687 prefix = Integer.parseInt(parts[1]);
1688 }
1689
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001690 Inet4Address a = null;
1691 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001692 try {
1693 a = (Inet4Address) InetAddress.getByName(ip);
1694 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001695 } catch (UnknownHostException e) {
1696 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001697
1698 byte[] b = a.getAddress();
1699 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001700 ((b[1] & 0xFF) << 16) |
1701 ((b[2] & 0xFF) << 8) |
1702 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001703
1704 byte[] b1 = a1.getAddress();
1705 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001706 ((b1[1] & 0xFF) << 16) |
1707 ((b1[2] & 0xFF) << 8) |
1708 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001709
1710 int mask = ~((1 << (32 - prefix)) - 1);
1711
1712 if ((ipInt & mask) == (ipInt1 & mask)) {
1713 return true;
1714 }
1715 else {
1716 return false;
1717 }
1718 }
Sangho Shineb083032014-09-22 16:11:34 -07001719
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001720 /**
1721 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001722 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001723 * @param sw - Switch to add the rule
1724 * @param hostIpAddress Destination host IP address
1725 * @param hostMacAddress Destination host MAC address
1726 */
Sangho Shineb083032014-09-22 16:11:34 -07001727 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1728 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
Sangho Shineb083032014-09-22 16:11:34 -07001729 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001730
Sangho Shin463bee52014-09-29 15:14:43 -07001731 /**
1732 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001733 *
Sangho Shin463bee52014-09-29 15:14:43 -07001734 * @param ipv4
1735 */
Sangho Shin7330c032014-10-20 10:34:51 -07001736 public void addPacketToPacketBuffer(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001737 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001738 }
1739
1740 /**
1741 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001742 *
Sangho Shin463bee52014-09-29 15:14:43 -07001743 * @param destIp Destination address of packets to retrieve
1744 */
1745 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1746
1747 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1748
Sangho Shin61535402014-10-01 11:37:14 -07001749 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001750 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001751 int dest = ip.getDestinationAddress();
1752 IPv4Address ip1 = IPv4Address.of(dest);
1753 IPv4Address ip2 = IPv4Address.of(destIp);
1754 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001755 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001756 }
1757 }
1758 }
1759
1760 return bufferedPackets;
1761 }
1762
Sangho Shin7330c032014-10-20 10:34:51 -07001763 /**
1764 * Get MAC address to known hosts
1765 *
1766 * @param destinationAddress IP address to get MAC address
1767 * @return MAC Address to given IP address
1768 */
1769 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
1770
1771 // Can't we get the host IP address from the TopologyService ??
1772
1773 Iterator<ArpEntry> iterator = arpEntries.iterator();
1774
1775 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
1776 byte[] ipAddressInByte = ipAddress.getBytes();
1777
1778 while (iterator.hasNext()) {
1779 ArpEntry arpEntry = iterator.next();
1780 byte[] address = arpEntry.targetIpAddress;
1781
1782 IPv4Address a = IPv4Address.of(address);
1783 IPv4Address b = IPv4Address.of(ipAddressInByte);
1784
1785 if (a.equals(b)) {
1786 log.debug("Found an arp entry");
1787 return arpEntry.targetMacAddress;
1788 }
1789 }
1790
1791 return null;
1792 }
1793
1794 /**
1795 * Send an ARP request via ArpHandler
1796 *
1797 * @param destinationAddress
1798 * @param sw
1799 * @param inPort
1800 *
1801 */
1802 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
1803 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
1804 }
1805
1806
1807 // ************************************
1808 // Test functions
1809 // ************************************
1810
Sangho Shin55d00e12014-10-20 12:13:07 -07001811 private void runTest() {
1812
1813 if (testMode == POLICY_ADD1) {
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001814 Integer[] routeArray = {101, 105, 110};
1815 /*List<Dpid> routeList = new ArrayList<Dpid>();
Sangho Shin55d00e12014-10-20 12:13:07 -07001816 for (int i = 0; i < routeArray.length; i++) {
1817 Dpid dpid = getSwitchFromNodeId(routeArray[i]).getDpid();
1818 routeList.add(dpid);
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001819 }*/
Sangho Shin55d00e12014-10-20 12:13:07 -07001820
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001821 if (createTunnel("1", Arrays.asList(routeArray))) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001822 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1823 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1824
1825 log.debug("Set the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001826 this.createPolicy("1", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001827 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
Sangho Shine020cc32014-10-20 13:28:02 -07001828 "1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001829 testMode = POLICY_ADD2;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001830 testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001831 }
1832 else {
1833 // retry it
1834 testTask.reschedule(5, TimeUnit.SECONDS);
1835 }
1836 }
1837 else if (testMode == POLICY_ADD2) {
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001838 Integer[] routeArray = {101, 102, 103, 104, 105, 108, 110};
Sangho Shin55d00e12014-10-20 12:13:07 -07001839
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001840 if (createTunnel("2", Arrays.asList(routeArray))) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001841 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1842 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1843
1844 log.debug("Set the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001845 this.createPolicy("2", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001846 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 20000,
Sangho Shine020cc32014-10-20 13:28:02 -07001847 "2");
Fahad Naeem Khan95aa4012014-10-21 14:07:00 -07001848 //testMode = POLICY_REMOVE2;
1849 //testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001850 }
1851 else {
1852 log.debug("Retry it");
1853 testTask.reschedule(5, TimeUnit.SECONDS);
1854 }
1855 }
1856 else if (testMode == POLICY_REMOVE2){
1857 log.debug("Remove the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001858 this.removePolicy("2");
Sangho Shin55d00e12014-10-20 12:13:07 -07001859 testMode = POLICY_REMOVE1;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001860 testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001861 }
1862 else if (testMode == POLICY_REMOVE1){
1863 log.debug("Remove the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001864 this.removePolicy("1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001865
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001866 testMode = TUNNEL_REMOVE1;
1867 testTask.reschedule(5, TimeUnit.SECONDS);
1868 }
1869 else if (testMode == TUNNEL_REMOVE1) {
1870 log.debug("Remove the tunnel 1");
1871 this.removeTunnel("1");
1872
1873 testMode = TUNNEL_REMOVE2;
1874 testTask.reschedule(5, TimeUnit.SECONDS);
1875 }
1876 else if (testMode == TUNNEL_REMOVE2) {
1877 log.debug("Remove the tunnel 2");
1878 this.removeTunnel("2");
1879 log.debug("The end of test");
1880 }
Sangho Shin55d00e12014-10-20 12:13:07 -07001881 }
Sangho Shin7330c032014-10-20 10:34:51 -07001882
1883 private void runTest1() {
1884
1885 String dpid1 = "00:00:00:00:00:00:00:01";
1886 String dpid2 = "00:00:00:00:00:00:00:0a";
1887 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1888 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1889
1890 if (srcSw == null || dstSw == null) {
1891 testTask.reschedule(1, TimeUnit.SECONDS);
1892 log.debug("Switch is gone. Reschedule the test");
1893 return;
1894 }
1895
1896 String[] routeArray = {"101", "102", "105", "108", "110"};
1897 List<String> routeList = new ArrayList<String>();
1898 for (int i = 0; i < routeArray.length; i++)
1899 routeList.add(routeArray[i]);
1900
1901 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1902
1903 log.debug("Test set is {}", routeList.toString());
1904 log.debug("Result set is {}", optimizedRoute.toString());
1905
1906
1907 }
1908
1909 /**
1910 * print tunnel info - used only for debugging.
1911 * @param targetSw
1912 *
1913 * @param fwdSwDpids
1914 * @param ids
1915 * @param tunnelId
1916 */
Sangho Shine020cc32014-10-20 13:28:02 -07001917 private void printTunnelInfo(IOF13Switch targetSw, String tunnelId,
Sangho Shin7330c032014-10-20 10:34:51 -07001918 List<String> ids, NeighborSet ns) {
1919 StringBuilder logStr = new StringBuilder("In switch " +
1920 targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
1921 for (String id: ids)
1922 logStr.append(id + "-");
1923 logStr.append(" output to ");
1924 for (Dpid dpid: ns.getDpids())
1925 logStr.append(dpid + " - ");
1926
1927 log.debug(logStr.toString());
1928
1929 }
1930
1931 /**
1932 * Debugging function to print out the Match Action Entry
1933 * @param sw13
1934 *
1935 * @param maEntry
1936 */
1937 private void printMatchActionOperationEntry(
1938 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
1939
1940 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
1941
1942 MatchAction ma = maEntry.getTarget();
1943 Match m = ma.getMatch();
1944 List<Action> actions = ma.getActions();
1945
1946 if (m instanceof Ipv4Match) {
1947 logStr.append("If the IP matches with ");
1948 IPv4Net ip = ((Ipv4Match) m).getDestination();
1949 logStr.append(ip.toString());
1950 logStr.append(" then ");
1951 }
1952 else if (m instanceof MplsMatch) {
1953 logStr.append("If the MPLS label matches with ");
1954 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1955 logStr.append(mplsLabel);
1956 logStr.append(" then ");
1957 }
1958 else if (m instanceof PacketMatch) {
1959 GroupAction ga = (GroupAction)actions.get(0);
1960 logStr.append("if the policy match is XXX then go to group " +
1961 ga.getGroupId());
1962 log.debug(logStr.toString());
1963 return;
1964 }
1965
1966 logStr.append(" do { ");
1967 for (Action action : actions) {
1968 if (action instanceof CopyTtlInAction) {
1969 logStr.append("copy ttl In, ");
1970 }
1971 else if (action instanceof CopyTtlOutAction) {
1972 logStr.append("copy ttl Out, ");
1973 }
1974 else if (action instanceof DecMplsTtlAction) {
1975 logStr.append("Dec MPLS TTL , ");
1976 }
1977 else if (action instanceof GroupAction) {
1978 logStr.append("Forward packet to < ");
1979 NeighborSet dpids = ((GroupAction) action).getDpids();
1980 logStr.append(dpids.toString() + ",");
1981
1982 }
1983 else if (action instanceof PopMplsAction) {
1984 logStr.append("Pop MPLS label, ");
1985 }
1986 else if (action instanceof PushMplsAction) {
1987 logStr.append("Push MPLS label, ");
1988 }
1989 else if (action instanceof SetMplsIdAction) {
1990 int id = ((SetMplsIdAction) action).getMplsId();
1991 logStr.append("Set MPLS ID as " + id + ", ");
1992 }
1993 }
1994
1995 log.debug(logStr.toString());
1996
1997 }
1998
1999
2000 // ************************************
2001 // Unused classes and functions
2002 // ************************************
2003
2004 /**
2005 * Temporary class to to keep ARP entry
2006 *
2007 */
2008 private class ArpEntry {
2009
2010 byte[] targetMacAddress;
2011 byte[] targetIpAddress;
2012
2013 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
2014 this.targetMacAddress = macAddress;
2015 this.targetIpAddress = ipAddress;
2016 }
2017 }
2018
2019 /**
2020 * This class is used only for link recovery optimization in
2021 * modifyEcmpRoutingRules() function.
2022 * TODO: please remove if the optimization is not used at all
2023 */
2024 private class SwitchPair {
2025 private Switch src;
2026 private Switch dst;
2027
2028 public SwitchPair(Switch src, Switch dst) {
2029 this.src = src;
2030 this.dst = dst;
2031 }
2032
2033 public Switch getSource() {
2034 return src;
2035 }
2036
2037 public Switch getDestination() {
2038 return dst;
2039 }
2040 }
2041
2042 /**
2043 * Update ARP Cache using ARP packets It is used to set destination MAC
2044 * address to forward packets to known hosts. But, it will be replace with
2045 * Host information of Topology service later.
2046 *
2047 * @param arp APR packets to use for updating ARP entries
2048 */
2049 public void updateArpCache(ARP arp) {
2050
2051 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
2052 arp.getSenderProtocolAddress());
2053 // TODO: Need to check the duplication
2054 arpEntries.add(arpEntry);
2055 }
2056
2057 /**
2058 * Modify the routing rules for the lost links
2059 * - Recompute the path if the link failed is included in the path
2060 * (including src and dest).
2061 *
2062 * @param newLink
2063 */
2064 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
2065
2066 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
2067 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
2068
2069 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
2070 Switch rootSw = ecmpSPG.getRootSwitch();
2071 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
2072 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
2073 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
2074 for (Switch destSw: p.keySet()) {
2075 ArrayList<Path> path = p.get(destSw);
2076 if (checkPath(path, linkRemoved)) {
2077 boolean found = false;
2078 for (SwitchPair pair: linksToRecompute) {
2079 if (pair.getSource().getDpid() == rootSw.getDpid() &&
2080 pair.getSource().getDpid() == destSw.getDpid()) {
2081 found = true;
2082 }
2083 }
2084 if (!found) {
2085 linksToRecompute.add(new SwitchPair(rootSw, destSw));
2086 }
2087 }
2088 }
2089 }
2090 }
2091
2092 // Recompute the path for the specific route
2093 for (SwitchPair pair: linksToRecompute) {
2094
2095 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
2096 // We need the following function for optimization
2097 //ECMPShortestPathGraph ecmpSPG =
2098 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
2099 ECMPShortestPathGraph ecmpSPG =
2100 new ECMPShortestPathGraph(pair.getSource());
2101 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
2102 }
2103 }
2104
2105 /**
2106 * Optimize the mpls label
2107 * The feature will be used only for policy of "avoid a specific switch".
2108 * Check route to each router in route backward.
2109 * If there is only one route to the router and the routers are included in
2110 * the route, remove the id from the path.
2111 * A-B-C-D-E => A-B-C-D-E -> A-E
2112 * | | => A-B-H-I -> A-I
Sangho Shin5b8f5452014-10-20 11:46:01 -07002113 * F-G-H-I => A-D-I > A-D-I
Sangho Shin7330c032014-10-20 10:34:51 -07002114 */
2115 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
2116
2117 List<String> optimizedPath = new ArrayList<String>();
2118 optimizedPath.addAll(route);
2119 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
2120
2121 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
2122 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
2123 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
2124 for (Switch s: p.keySet()) {
2125 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
2126 ArrayList<Path> ecmpPaths = p.get(s);
2127 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
2128 for (Path path: ecmpPaths) {
2129 for (LinkData link: path) {
2130 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
2131 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
2132 if (optimizedPath.contains(srcId)) {
2133 optimizedPath.remove(srcId);
2134 }
2135 if (optimizedPath.contains(dstId)) {
2136 optimizedPath.remove(dstId);
2137 }
2138 }
2139 }
2140 }
2141 }
2142 }
2143 }
2144
2145 return optimizedPath;
2146
2147 }
2148
2149 /**
2150 * Check if the path is affected from the link removed
2151 *
2152 * @param path Path to check
2153 * @param linkRemoved link removed
2154 * @return true if the path contains the link removed
2155 */
2156 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
2157
2158 for (Path ppp: path) {
2159 // TODO: need to check if this is a bidirectional or
2160 // unidirectional
2161 for (LinkData link: ppp) {
2162 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
2163 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
2164 return true;
2165 }
2166 }
2167
2168 return false;
2169 }
Sangho Shin15273b62014-10-16 22:22:05 -07002170
2171
Sangho Shin2f263692014-09-15 14:09:41 -07002172}