blob: 5f3e11b62e438db24206ecb33f95cd065a1fbb11 [file] [log] [blame]
Sangho Shin2f263692014-09-15 14:09:41 -07001package net.onrc.onos.apps.segmentrouting;
2
Sangho Shin9c0f4c32014-09-26 16:02:38 -07003import java.io.IOException;
Sangho Shin1aa93542014-09-22 09:49:44 -07004import java.net.Inet4Address;
5import java.net.InetAddress;
6import java.net.UnknownHostException;
Sangho Shin2f263692014-09-15 14:09:41 -07007import java.util.ArrayList;
8import java.util.Collection;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -07009import java.util.HashMap;
Sangho Shin5be3e532014-10-03 17:20:58 -070010import java.util.HashSet;
Sangho Shin2f263692014-09-15 14:09:41 -070011import java.util.Iterator;
12import java.util.List;
13import java.util.Map;
Sangho Shin5be3e532014-10-03 17:20:58 -070014import java.util.Set;
Sangho Shin61535402014-10-01 11:37:14 -070015import java.util.concurrent.ConcurrentLinkedQueue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070016import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070017import java.util.concurrent.ScheduledExecutorService;
18import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070019import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070020
21import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070022import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070023import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070024import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070025import net.floodlightcontroller.core.module.FloodlightModuleContext;
26import net.floodlightcontroller.core.module.FloodlightModuleException;
27import net.floodlightcontroller.core.module.IFloodlightModule;
28import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070029import net.floodlightcontroller.core.util.SingletonTask;
Sangho Shin7330c032014-10-20 10:34:51 -070030import net.floodlightcontroller.restserver.IRestApiService;
Sangho Shin43cee112014-09-25 16:43:34 -070031import net.floodlightcontroller.threadpool.IThreadPoolService;
Sangho Shin15273b62014-10-16 22:22:05 -070032import net.floodlightcontroller.util.MACAddress;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070033import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070034import net.onrc.onos.api.packet.IPacketService;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070035import net.onrc.onos.apps.segmentrouting.web.SegmentRoutingWebRoutable;
Sangho Shin2f263692014-09-15 14:09:41 -070036import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070037import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070038import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070039import net.onrc.onos.core.matchaction.MatchAction;
40import net.onrc.onos.core.matchaction.MatchActionId;
41import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070042import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070043import net.onrc.onos.core.matchaction.action.Action;
44import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
45import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
46import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
47import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
48import net.onrc.onos.core.matchaction.action.GroupAction;
49import net.onrc.onos.core.matchaction.action.PopMplsAction;
50import net.onrc.onos.core.matchaction.action.PushMplsAction;
51import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070052import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070053import net.onrc.onos.core.matchaction.match.Match;
54import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070055import net.onrc.onos.core.matchaction.match.PacketMatch;
56import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070057import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070058import net.onrc.onos.core.packet.Ethernet;
59import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070060import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070061import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070062import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070063import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070064import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070065import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070066import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070067import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070068import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070069import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070070import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070071import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070072import net.onrc.onos.core.util.IPv4Net;
73import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070074
Sangho Shin43cee112014-09-25 16:43:34 -070075import org.json.JSONArray;
76import org.json.JSONException;
Saurav Dasa962a692014-10-17 14:52:38 -070077import org.projectfloodlight.openflow.protocol.OFBarrierReply;
Saurav Dasbc594a42014-09-25 20:13:50 -070078import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070079import org.projectfloodlight.openflow.types.IPv4Address;
80import org.slf4j.Logger;
81import org.slf4j.LoggerFactory;
82
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070083public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -070084 ITopologyListener, IPacketListener, ISegmentRoutingService {
Sangho Shin2f263692014-09-15 14:09:41 -070085
86 private static final Logger log = LoggerFactory
87 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070088
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -070089 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070090 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070091 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070092 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070093 private IRestApiService restApi;
Sangho Shin2f263692014-09-15 14:09:41 -070094 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070095 private ArpHandler arpHandler;
96 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070097 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070098 private IThreadPoolService threadPool;
99 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -0700100 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -0700101 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700102 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700103
Sangho Shinfbc572c2014-10-02 16:37:05 -0700104 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700105 private HashMap<String, LinkData> linksDown;
106 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700107 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shine020cc32014-10-20 13:28:02 -0700108 private HashMap<String, HashMap<String, TunnelRouteInfo>> stitchInfo;
Sangho Shin81655442014-10-20 14:22:46 -0700109 //private HashMap<String, HashMap<String, Integer>> tunnelGroupMap;
Sangho Shine020cc32014-10-20 13:28:02 -0700110 private HashMap<String, PolicyInfo> policyTable;
Sangho Shin81655442014-10-20 14:22:46 -0700111 private HashMap<String, TunnelInfo> tunnelTable;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700112
113 private int testMode = 0;
114
Sangho Shinbce900e2014-10-07 17:13:23 -0700115
116 private int numOfEvents = 0;
117 private int numOfEventProcess = 0;
118 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700119 private long matchActionId = 0L;
Sangho Shin23f898d2014-10-13 16:54:00 -0700120 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700121 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700122
Sangho Shin5b8f5452014-10-20 11:46:01 -0700123
124 private final int POLICY_ADD1 = 1;
125 private final int POLICY_ADD2 = 2;
126 private final int POLICY_REMOVE1 = 3;
127 private final int POLICY_REMOVE2 = 4;
128
129
Sangho Shin7330c032014-10-20 10:34:51 -0700130 // ************************************
131 // IFloodlightModule implementation
132 // ************************************
133
Sangho Shin2f263692014-09-15 14:09:41 -0700134 @Override
135 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700136 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
137 l.add(ISegmentRoutingService.class);
138 return l;
Sangho Shin2f263692014-09-15 14:09:41 -0700139 }
140
141 @Override
142 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700143 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
144 m.put(ISegmentRoutingService.class, this);
145 return m;
Sangho Shin2f263692014-09-15 14:09:41 -0700146 }
147
148 @Override
149 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
150 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
151
152 l.add(IFloodlightProviderService.class);
153 l.add(IConfigInfoService.class);
154 l.add(ITopologyService.class);
155 l.add(IPacketService.class);
156 l.add(IFlowPusherService.class);
157 l.add(ITopologyService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700158 l.add(IRestApiService.class);
Sangho Shin2f263692014-09-15 14:09:41 -0700159
160 return l;
161
162 }
163
164 @Override
165 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700166 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700167 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700168 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700169 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700170 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700171 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700172 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700173 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700174 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700175 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700176 linksDown = new HashMap<String, LinkData>();
177 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700178 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shine020cc32014-10-20 13:28:02 -0700179 stitchInfo = new HashMap<String, HashMap<String, TunnelRouteInfo>>();
Sangho Shin15273b62014-10-16 22:22:05 -0700180 packetService = context.getServiceImpl(IPacketService.class);
Sangho Shin81655442014-10-20 14:22:46 -0700181 //tunnelGroupMap = new HashMap<String, HashMap<String, Integer>>();
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700182 restApi = context.getServiceImpl(IRestApiService.class);
Sangho Shine020cc32014-10-20 13:28:02 -0700183 policyTable = new HashMap<String, PolicyInfo>();
Sangho Shin81655442014-10-20 14:22:46 -0700184 tunnelTable = new HashMap<String, TunnelInfo>();
Sangho Shin2f263692014-09-15 14:09:41 -0700185
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700186 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700187 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700188
Sangho Shin99918bd2014-10-08 15:52:35 -0700189
Sangho Shin2f263692014-09-15 14:09:41 -0700190 }
191
192 @Override
193 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700194 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700195 restApi.addRestletRoutable(new SegmentRoutingWebRoutable());
Sangho Shin2f263692014-09-15 14:09:41 -0700196
Sangho Shinc8d2f592014-09-30 16:53:57 -0700197 discoveryTask = new SingletonTask(ses, new Runnable() {
198 @Override
199 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700200 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700201 }
202 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700203
204 linkAddTask = new SingletonTask(ses, new Runnable() {
205 @Override
206 public void run() {
207 delayedAddLink();
208 }
209 });
210
Sangho Shin15273b62014-10-16 22:22:05 -0700211 testTask = new SingletonTask(ses, new Runnable() {
212 @Override
213 public void run() {
214 runTest();
215 }
216 });
217
Sangho Shin5b8f5452014-10-20 11:46:01 -0700218 testMode = POLICY_ADD1;
219 testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700220 }
221
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700222 @Override
223 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700224 if (payload.getEtherType() == Ethernet.TYPE_ARP)
225 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700226 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Sangho Shin7330c032014-10-20 10:34:51 -0700227 addPacketToPacketBuffer((IPv4) payload.getPayload());
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700228 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
229 icmpHandler.processPacketIn(sw, inPort, payload);
230 else
231 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700232 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700233 else {
234 log.debug("{}", payload.toString());
235 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700236 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700237
Sangho Shin2f263692014-09-15 14:09:41 -0700238
Sangho Shin7330c032014-10-20 10:34:51 -0700239 // ************************************
240 // Topology event handlers
241 // ************************************
Sangho Shineb083032014-09-22 16:11:34 -0700242
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700243 /**
244 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700245 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700246 * @param topologyEvents the generated Topology Events
247 * @see TopologyEvents
248 */
249 public void topologyEvents(TopologyEvents topologyEvents)
250 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700251 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700252 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700253 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700254
Sangho Shin23f898d2014-10-13 16:54:00 -0700255 /**
256 * Process the multiple topology events with some delay (100MS at most for now)
257 *
258 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700259 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700260 numOfEventProcess ++;
261
Sangho Shin51625342014-10-17 09:30:48 -0700262 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
263 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
264 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
265 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
266 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
267 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
268 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700269
Sangho Shin5be3e532014-10-03 17:20:58 -0700270 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700271 // We should handle the events in the order of when they happen
272 // TODO: We need to simulate the final results of multiple events
273 // and shoot only the final state.
274 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
275 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700276
Sangho Shin5be3e532014-10-03 17:20:58 -0700277 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700278
279 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
280 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
281 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
282 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
283 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
284 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
285 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
286
287 linkEntriesAddedAll.addAll(linkEntriesAdded);
288 portEntriesAddedAll.addAll(portEntriesAdded);
289 portEntriesRemovedAll.addAll(portEntriesRemoved);
290 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
291 switchAddedAll.addAll(switchAdded);
292 switchRemovedAll.addAll(switchRemoved);
293 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700294 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700295
296 if (!portEntriesRemoved.isEmpty()) {
297 processPortRemoval(portEntriesRemoved);
298 }
299
300 if (!linkEntriesRemoved.isEmpty()) {
301 processLinkRemoval(linkEntriesRemoved);
302 }
303
304 if (!switchRemoved.isEmpty()) {
305 processSwitchRemoved(switchRemoved);
306 }
307
308 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700309 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700310 }
311
312 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700313 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700314 }
315
316 if (!portEntriesAdded.isEmpty()) {
317 processPortAdd(portEntriesAdded);
318 }
319
320 if (!switchAdded.isEmpty()) {
321 processSwitchAdd(switchAdded);
322 }
Sangho Shin51625342014-10-17 09:30:48 -0700323
Sangho Shinbce900e2014-10-07 17:13:23 -0700324 }
325
Sangho Shin23f898d2014-10-13 16:54:00 -0700326 // TODO: 100ms is enough to check both mastership removed events
327 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700328 if (!mastershipRemovedAll.isEmpty()) {
329 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700330 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700331 }
332 else {
333 HashMap<String, MastershipData> mastershipToRemove =
334 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700335 for (MastershipData ms: mastershipRemovedAll) {
336 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700337 // TODO: check ALL ports of the switch are dead ..
338 if (port.getDpid().equals(ms.getDpid())) {
339 mastershipToRemove.put(ms.getDpid().toString(), ms);
340 }
341 }
342 log.debug("Swtich {} is really down.", ms.getDpid());
343 }
344 processMastershipRemoved(mastershipToRemove.values());
345 }
346 }
347
Sangho Shinbce900e2014-10-07 17:13:23 -0700348 log.debug("num events {}, num of process {}, "
349 + "num of Population {}", numOfEvents, numOfEventProcess,
350 numOfPopulation);
351 }
352
353 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700354 * Process the SwitchAdded events from topologyMananger.
355 * It does nothing. When a switch is added, then link will be added too.
356 * LinkAdded event will handle process all re-computation.
357 *
358 * @param switchAdded
359 */
360 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
361
362 }
363
364 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700365 * Remove all ports connected to the switch removed
366 *
367 * @param mastershipRemoved master switch info removed
368 */
369 private void processMastershipRemoved(Collection<MastershipData>
370 mastershipRemoved) {
371 for (MastershipData mastership: mastershipRemoved) {
372 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
373 for (Link link: sw.getOutgoingLinks()) {
374 Port dstPort = link.getDstPort();
375 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
376 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700377 if (dstSw != null) {
378 dstSw.removePortFromGroups(dstPort.getNumber());
379 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
380 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700381 }
Sangho Shin61535402014-10-01 11:37:14 -0700382 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700383
384 linksToAdd.clear();
385 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700386 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700387
Sangho Shinbce900e2014-10-07 17:13:23 -0700388 /**
389 * Remove all ports connected to the switch removed
390 *
391 * @param switchRemoved Switch removed
392 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700393 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700394 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700395 }
396
Sangho Shin61535402014-10-01 11:37:14 -0700397 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700398 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700399 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700400 * @param portEntries
401 */
402 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700403 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700404 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700405 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700406
Sangho Shinfbc572c2014-10-02 16:37:05 -0700407 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700408 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700409 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700410 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700411 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700412 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700413 }
414 }
415
416 /**
417 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700418 * If the link to add was removed before, then we just schedule the add link
419 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700420 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700421 * @param linkEntries
422 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700423 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700424
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700425 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700426
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700427 SwitchPort srcPort = link.getSrc();
428 SwitchPort dstPort = link.getDst();
429
Sangho Shin23f898d2014-10-13 16:54:00 -0700430 String key = srcPort.getDpid().toString() +
431 dstPort.getDpid().toString();
432 if (!delayed) {
433 if (linksDown.containsKey(key)) {
434 linksToAdd.put(key, link);
435 linksDown.remove(key);
436 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
437 log.debug("Add link {} with 5 sec delay", link);
438 // TODO: What if we have multiple events of add link:
439 // one is new link add, the other one is link up for
440 // broken link? ECMPSPG function cannot deal with it for now
441 return;
442 }
443 }
444 else {
445 if (linksDown.containsKey(key)) {
446 linksToAdd.remove(key);
447 log.debug("Do not add the link {}: it is down again!", link);
448 return;
449 }
450 }
451
Sangho Shinfbc572c2014-10-02 16:37:05 -0700452 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700453 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700454 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700455 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700456
Sangho Shin815af0c2014-10-10 13:05:45 -0700457 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700458 continue;
459
460 srcSw.addPortToGroups(srcPort.getPortNumber());
461 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700462
Sangho Shin15273b62014-10-16 22:22:05 -0700463 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
464 // link);
465 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
466 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700467
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700468 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700469 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700470 }
471
472 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700473 * Check if all links are gone b/w the two switches. If all links are gone,
474 * then we need to recalculate the path. Otherwise, just report link failure
475 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700476 *
Sangho Shin61535402014-10-01 11:37:14 -0700477 * @param linkEntries
478 */
479 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700480 boolean recomputationRequired = false;
481
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700482 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700483 SwitchPort srcPort = link.getSrc();
484 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700485
Sangho Shinfbc572c2014-10-02 16:37:05 -0700486 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700487 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700488 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700489 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700490 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700491 /* If this link is not between two switches, ignore it */
492 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700493
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700494 srcSw.removePortFromGroups(srcPort.getPortNumber());
495 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700496 log.debug("Remove port {} from switch {}", srcPort, srcSw);
497 log.debug("Remove port {} from switch {}", dstPort, dstSw);
498
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700499 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
500 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700501 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700502 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700503 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700504 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700505 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700506 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700507
508 String key = link.getSrc().getDpid().toString()+
509 link.getDst().getDpid().toString();
510 if (!linksDown.containsKey(key)) {
511 linksDown.put(key, link);
512 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700513 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700514
515 if (recomputationRequired)
516 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700517 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700518
Sangho Shin61535402014-10-01 11:37:14 -0700519 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700520 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700521 *
Sangho Shin61535402014-10-01 11:37:14 -0700522 * @param portEntries
523 */
524 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700525 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700526 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700527
Sangho Shinfbc572c2014-10-02 16:37:05 -0700528 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700529 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700530 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700531 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700532 log.debug("Remove port {} from switch {}", port, dpid);
533 }
Sangho Shin61535402014-10-01 11:37:14 -0700534 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700535 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700536
537 /**
Sangho Shin7330c032014-10-20 10:34:51 -0700538 * Add the link immediately
539 * The function is scheduled when link add event happens and called
540 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
541 */
542 private void delayedAddLink() {
543
544 processLinkAdd(linksToAdd.values(), true);
545
546 }
547
548
549 // ************************************
550 // ECMP shorted path routing functions
551 // ************************************
552
553 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700554 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700555 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700556 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700557 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700558 private void populateEcmpRoutingRules(boolean modified) {
559 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700560 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700561 for (Switch sw : switches) {
562 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700563 graphs.put(sw, ecmpSPG);
564 //log.debug("ECMPShortestPathGraph is computed for switch {}",
565 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700566 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700567 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700568 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700569 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700570
Sangho Shin99918bd2014-10-08 15:52:35 -0700571 /**
572 * populate routing rules to forward packets from the switch given to
573 * all other switches.
574 *
575 * @param sw source switch
576 * @param ecmpSPG shortest path from the the source switch to all others
577 * @param modified modification flag
578 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700579 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700580 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700581
Sangho Shinfbc572c2014-10-02 16:37:05 -0700582 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
583 ecmpSPG.getAllLearnedSwitchesAndVia();
584 for (Integer itrIdx : switchVia.keySet()) {
585 //log.debug("ECMPShortestPathGraph:Switches learned in "
586 // + "Iteration{} from switch {}:",
587 // itrIdx,
588 // HexString.toHexString(sw.getDpid().value()));
589 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
590 switchVia.get(itrIdx);
591 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700592 //log.debug("ECMPShortestPathGraph:****switch {} via:",
593 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700594 String destSw = sw.getDpid().toString();
595 List<String> fwdToSw = new ArrayList<String>();
596
Sangho Shinfbc572c2014-10-02 16:37:05 -0700597 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700598 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700599 if (via.isEmpty()) {
600 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700601 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700602 else {
603 fwdToSw.add(via.get(0).toString());
604 }
Sangho Shin43cee112014-09-25 16:43:34 -0700605 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700606 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700607 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700608
609 // Send Barrier Message and make sure all rules are set
610 // before we set the rules to next routers
Saurav Dasa962a692014-10-17 14:52:38 -0700611 // TODO: barriers to all switches in this update stage
Sangho Shinfbc572c2014-10-02 16:37:05 -0700612 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
613 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700614 if (sw13 != null) {
Saurav Dasa962a692014-10-17 14:52:38 -0700615 OFBarrierReplyFuture replyFuture = null;
Sangho Shin5be3e532014-10-03 17:20:58 -0700616 try {
Saurav Dasa962a692014-10-17 14:52:38 -0700617 replyFuture = sw13.sendBarrier();
Sangho Shin5be3e532014-10-03 17:20:58 -0700618 } catch (IOException e) {
Saurav Dasa962a692014-10-17 14:52:38 -0700619 log.error("Error sending barrier request to switch {}",
620 sw13.getId(), e.getCause());
Sangho Shin5be3e532014-10-03 17:20:58 -0700621 }
Saurav Dasa962a692014-10-17 14:52:38 -0700622 OFBarrierReply br = null;
623 try {
624 br = replyFuture.get(2, TimeUnit.SECONDS);
625 } catch (TimeoutException | InterruptedException | ExecutionException e) {
626 // XXX for some reason these exceptions are not being thrown
627 }
628 if (br == null) {
629 log.warn("Did not receive barrier-reply from {}", sw13.getId());
630 // XXX take corrective action
631 }
632
Sangho Shinfbc572c2014-10-02 16:37:05 -0700633 }
634 }
635
636 }
637
Sangho Shinfbc572c2014-10-02 16:37:05 -0700638 /**
639 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700640 * Set routing rules in targetSw {forward packets to fwdToSw switches in
641 * order to send packets to destSw} - If the target switch is an edge router
642 * and final destnation switch is also an edge router, then set IP
643 * forwarding rules to subnets - If only the target switch is an edge
644 * router, then set IP forwarding rule to the transit router loopback IP
645 * address - If the target is a transit router, then just set the MPLS
646 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700647 *
Sangho Shin43cee112014-09-25 16:43:34 -0700648 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700649 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700650 * @param fwdToSw next hop switches
651 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700652 private void setRoutingRule(Switch targetSw, String destSw,
653 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700654
Sangho Shin43cee112014-09-25 16:43:34 -0700655 if (fwdToSw.isEmpty()) {
656 fwdToSw.add(destSw);
657 }
658
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700659 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700660 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
661 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700662 // We assume that there is at least one transit router b/w edge
663 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700664 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
665 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700666 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700667 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700668
Sangho Shin43cee112014-09-25 16:43:34 -0700669 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700670 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
671 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700672 // Edge router can be a transit router
673 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700674 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700675 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700676 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700677 // We assume that there is at least one transit router b/w edge
678 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700679 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
680 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700681 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
682 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700683 // Edge router can be a transit router
684 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700685 }
686 // if it is a transit router, then set rules in the MPLS table
687 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700688 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700689 }
690
691 }
692
Sangho Shinfbc572c2014-10-02 16:37:05 -0700693 /**
694 * Set IP forwarding rule to the gateway of each subnet of switches
695 *
696 * @param targetSw Switch to set rules
697 * @param subnets subnet information
698 * @param mplsLabel destination MPLS label
699 * @param fwdToSw router to forward packets to
700 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700701 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700702 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700703
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700704 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700705 new ArrayList<MatchActionOperationEntry>();
706
707 try {
708 JSONArray arry = new JSONArray(subnets);
709 for (int i = 0; i < arry.length(); i++) {
710 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700711 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
712 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700713 }
714 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700715 e.printStackTrace();
716 }
717
718 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700719 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700720 getSwId(targetSw.getDpid().toString()));
721
Sangho Shin721ca042014-10-09 13:03:40 -0700722 if (sw13 != null) {
723 try {
724 sw13.pushFlows(entries);
725 } catch (IOException e) {
726 e.printStackTrace();
727 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700728 }
729 }
730
731 }
732
Sangho Shin43cee112014-09-25 16:43:34 -0700733 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700734 * Set IP forwarding rule - If the destination is the next hop, then do not
735 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
736 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700737 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700738 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700739 * @param subnetIp Match IP address
740 * @param mplsLabel MPLS label of final destination router
741 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700742 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700743 */
744 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700745 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
746 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700747
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700748 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700749 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700750 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700751
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700752 // If destination SW is the same as the fwd SW, then do not push MPLS
753 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700754 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700755 PushMplsAction pushMplsAction = new PushMplsAction();
756 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
757 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700758 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700759
Sangho Shin62ce5c12014-10-08 16:24:40 -0700760 //actions.add(pushMplsAction);
761 //actions.add(copyTtlOutAction);
762 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700763 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700764 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700765 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700766 else {
767 String fwdToSw = fwdToSws.get(0);
768 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
769 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
770 actions.add(decTtlAction);
771 }
772 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700773 SetMplsIdAction setIdAction = new SetMplsIdAction(
774 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700775 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700776 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700777
Sangho Shin62ce5c12014-10-08 16:24:40 -0700778 //actions.add(pushMplsAction);
779 //actions.add(copyTtlOutAction);
780 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700781 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700782 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700783 }
784 }
Sangho Shin43cee112014-09-25 16:43:34 -0700785
Sangho Shin43cee112014-09-25 16:43:34 -0700786 for (String fwdSw : fwdToSws) {
787 groupAction.addSwitch(new Dpid(fwdSw));
788 }
789 actions.add(groupAction);
790
Sangho Shin99918bd2014-10-08 15:52:35 -0700791 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700792 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700793
Sangho Shin5be3e532014-10-03 17:20:58 -0700794 Operator operator = null;
795 if (modified)
796 operator = Operator.MODIFY;
797 else
798 operator = Operator.ADD;
799
Sangho Shin43cee112014-09-25 16:43:34 -0700800 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700801 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700802
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700803 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700804 getSwId(sw.getDpid().toString()));
805
Sangho Shin5be3e532014-10-03 17:20:58 -0700806 if (sw13 != null) {
807 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700808 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700809 if (entries != null)
810 entries.add(maEntry);
811 else
812 sw13.pushFlow(maEntry);
813 } catch (IOException e) {
814 e.printStackTrace();
815 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700816 }
817
Sangho Shin43cee112014-09-25 16:43:34 -0700818 }
819
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700820 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700821 * Set MPLS forwarding rules to MPLS table
822 * </p>
823 * If the destination is the same as the next hop to forward packets then,
824 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
825 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
826 * TTL of the another MPLS header.
827 * If the next hop is not the destination, just forward packets to next
828 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700829 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700830 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700831 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700832 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700833 * */
Sangho Shin5be3e532014-10-03 17:20:58 -0700834 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
835 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -0700836
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700837 if (fwdSws.isEmpty())
838 return;
Sangho Shin43cee112014-09-25 16:43:34 -0700839
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700840 Collection<MatchActionOperationEntry> maEntries =
841 new ArrayList<MatchActionOperationEntry>();
842 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -0700843
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700844 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
845 // One rule for Bos = 1
846 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
847 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700848
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700849 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
850 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
851 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
852
853 actions.add(copyTtlInAction);
854 actions.add(popAction);
855 actions.add(decNwTtlAction);
856
857 GroupAction groupAction = new GroupAction();
858 groupAction.addSwitch(new Dpid(fwdSw1));
859 actions.add(groupAction);
860
861 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
862 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
863 Operator operator = Operator.ADD;
864 MatchActionOperationEntry maEntry =
865 new MatchActionOperationEntry(operator, matchAction);
866 maEntries.add(maEntry);
867
868 // One rule for Bos = 0
Sangho Shin23f898d2014-10-13 16:54:00 -0700869 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700870 List<Action> actionsBos = new ArrayList<Action>();
Sangho Shin15273b62014-10-16 22:22:05 -0700871 PopMplsAction popActionBos = new PopMplsAction(EthType.MPLS_UNICAST);
872 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
873
874 actionsBos.add(copyTtlInAction);
875 actionsBos.add(popActionBos);
876 actionsBos.add(decMplsTtlAction);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700877 actionsBos.add(groupAction);
878
879 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
880 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
881 MatchActionOperationEntry maEntryBos =
882 new MatchActionOperationEntry(operator, matchActionBos);
883 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700884 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700885 else {
886 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
887 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700888
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700889 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
890 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700891
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700892 GroupAction groupAction = new GroupAction();
893 for (String fwdSw : fwdSws)
894 groupAction.addSwitch(new Dpid(fwdSw));
895 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -0700896
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700897 MatchAction matchAction = new MatchAction(new MatchActionId(
898 matchActionId++),
899 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
900 Operator operator = Operator.ADD;
901 MatchActionOperationEntry maEntry =
902 new MatchActionOperationEntry(operator, matchAction);
903 maEntries.add(maEntry);
Sangho Shine2e9bcd2014-10-13 15:14:18 -0700904
905 // BoS = 1
906 MplsMatch mplsMatchBoS = new MplsMatch(Integer.parseInt(mplsLabel), true);
907 List<Action> actionsBoS = new ArrayList<Action>();
908
909 DecMplsTtlAction decMplsTtlActionBoS = new DecMplsTtlAction(1);
910 actionsBoS.add(decMplsTtlActionBoS);
911
912 GroupAction groupActionBoS = new GroupAction();
913 for (String fwdSw : fwdSws)
914 groupActionBoS.addSwitch(new Dpid(fwdSw));
915 actionsBoS.add(groupActionBoS);
916
917 MatchAction matchActionBos = new MatchAction(new MatchActionId(
918 matchActionId++),
919 new SwitchPort((long) 0, (short) 0), mplsMatchBoS, actionsBoS);
920 MatchActionOperationEntry maEntryBoS =
921 new MatchActionOperationEntry(operator, matchActionBos);
922 maEntries.add(maEntryBoS);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700923 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700924 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700925 getSwId(sw.getDpid().toString()));
926
Sangho Shin5be3e532014-10-03 17:20:58 -0700927 if (sw13 != null) {
928 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700929 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700930 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -0700931 } catch (IOException e) {
932 e.printStackTrace();
933 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700934 }
Sangho Shin43cee112014-09-25 16:43:34 -0700935 }
936
Sangho Shin7330c032014-10-20 10:34:51 -0700937
938 // ************************************
939 // Policy routing classes and functions
940 // ************************************
941
Sangho Shin5b8f5452014-10-20 11:46:01 -0700942 class PolicyInfo {
943
Sangho Shine020cc32014-10-20 13:28:02 -0700944 String policyId;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700945 PacketMatch match;
946 int priority;
Sangho Shine020cc32014-10-20 13:28:02 -0700947 String tunnelId;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700948
Sangho Shine020cc32014-10-20 13:28:02 -0700949 PolicyInfo(String pid, PacketMatch match, int priority, String tid) {
Sangho Shin5b8f5452014-10-20 11:46:01 -0700950 this.policyId = pid;
951 this.match = match;
952 this.priority = priority;
953 this.tunnelId = tid;
954 }
955 }
956
Sangho Shin81655442014-10-20 14:22:46 -0700957 class TunnelInfo {
958 String tunnelId;
959 List<Dpid> dpids;
960 List<TunnelRouteInfo> routes;
961
962 TunnelInfo(String tid, List<Dpid> dpids, List<TunnelRouteInfo> routes) {
963 this.tunnelId = tid;
964 this.dpids = dpids;
965 this.routes = routes;
966 }
967 }
968
Sangho Shine020cc32014-10-20 13:28:02 -0700969 class TunnelRouteInfo {
Sangho Shin7330c032014-10-20 10:34:51 -0700970
971 String srcSwDpid;
972 List<Dpid> fwdSwDpids;
973 List<String> route;
974
Sangho Shine020cc32014-10-20 13:28:02 -0700975 TunnelRouteInfo() {
Sangho Shin7330c032014-10-20 10:34:51 -0700976 fwdSwDpids = new ArrayList<Dpid>();
977 route = new ArrayList<String>();
978 }
979
980 void setSrcDpid(String dpid) {
981 this.srcSwDpid = dpid;
982 }
983
984 void setFwdSwDpid(List<Dpid> dpid) {
985 this.fwdSwDpids = dpid;
986 }
987
988 void addRoute(String id) {
989 route.add(id);
990 }
991
992 void setRoute(List<String> r) {
993 this.route = r;
994 }
995
996 String getSrcSwDpid() {
997 return this.srcSwDpid;
998 }
999
1000 List<Dpid> getFwdSwDpid() {
1001 return this.fwdSwDpids;
1002 }
1003
1004 List<String> getRoute() {
1005 return this.route;
1006 }
1007 }
1008
Sangho Shin15273b62014-10-16 22:22:05 -07001009 /**
Sangho Shin81655442014-10-20 14:22:46 -07001010 * Return the Tunnel table
1011 *
1012 * @return collection of TunnelInfo
1013 */
1014 public Collection<TunnelInfo> getTunnelTable() {
1015 return tunnelTable.values();
1016 }
1017
1018 /**
Sangho Shin15273b62014-10-16 22:22:05 -07001019 * Create a tunnel for policy routing
1020 * It delivers the node IDs of tunnels to driver.
1021 * Split the node IDs if number of IDs exceeds the limit for stitching.
1022 *
1023 * @param tunnelId Node IDs for the tunnel
1024 * @param Ids tunnel ID
1025 */
Sangho Shine020cc32014-10-20 13:28:02 -07001026 public boolean createTunnel(String tunnelId, List<Dpid> dpids) {
Sangho Shin15273b62014-10-16 22:22:05 -07001027
Sangho Shin55d00e12014-10-20 12:13:07 -07001028 if (dpids.isEmpty() || dpids.size() < 2) {
Sangho Shin15273b62014-10-16 22:22:05 -07001029 log.debug("Wrong tunnel information");
1030 return false;
1031 }
1032
Sangho Shin55d00e12014-10-20 12:13:07 -07001033 List<String> Ids = new ArrayList<String>();
1034 for (Dpid dpid: dpids) {
1035 Ids.add(getMplsLabel(dpid.toString()));
1036 }
1037
Sangho Shin81655442014-10-20 14:22:46 -07001038 List<TunnelRouteInfo> stitchingRule = getStitchingRule(Ids);
Sangho Shin15273b62014-10-16 22:22:05 -07001039 if (stitchingRule == null) {
1040 log.debug("Failed to get the policy rule.");
1041 return false;
1042 }
1043 HashMap<String, Integer> switchGroupPair = new HashMap<String, Integer>();
Sangho Shin81655442014-10-20 14:22:46 -07001044 for (TunnelRouteInfo route: stitchingRule) {
Sangho Shin15273b62014-10-16 22:22:05 -07001045
1046 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin81655442014-10-20 14:22:46 -07001047 getSwId(route.srcSwDpid));
Sangho Shin15273b62014-10-16 22:22:05 -07001048
1049 if (targetSw == null) {
Sangho Shin81655442014-10-20 14:22:46 -07001050 log.debug("Switch {} is gone.", route.srcSwDpid);
Sangho Shin15273b62014-10-16 22:22:05 -07001051 return false;
1052 }
1053
1054 NeighborSet ns = new NeighborSet();
1055 for (Dpid dpid: route.getFwdSwDpid())
1056 ns.addDpid(dpid);
1057
1058 printTunnelInfo(targetSw, tunnelId, route.getRoute(), ns);
1059 int groupId = targetSw.createTunnel(tunnelId, route.getRoute(), ns);
Sangho Shin81655442014-10-20 14:22:46 -07001060 switchGroupPair.put(route.srcSwDpid.toString(), groupId);
Sangho Shin15273b62014-10-16 22:22:05 -07001061
1062 }
1063
Sangho Shin81655442014-10-20 14:22:46 -07001064 //tunnelGroupMap.put(tunnelId, switchGroupPair);
1065 TunnelInfo tunnelInfo = new TunnelInfo(tunnelId, dpids, stitchingRule);
1066 tunnelTable.put(tunnelId, tunnelInfo);
Sangho Shin15273b62014-10-16 22:22:05 -07001067
1068 return true;
1069 }
1070
1071 /**
Sangho Shine020cc32014-10-20 13:28:02 -07001072 * Return router DPIDs for the tunnel
1073 *
1074 * @param tid tunnel ID
1075 * @return List of DPID
1076 */
1077 public List<Dpid> getTunnelInfo(String tid) {
Sangho Shin81655442014-10-20 14:22:46 -07001078 TunnelInfo tunnelInfo = tunnelTable.get(tid);
1079 return tunnelInfo.dpids;
1080
Sangho Shine020cc32014-10-20 13:28:02 -07001081 }
1082
1083 /**
Sangho Shin15273b62014-10-16 22:22:05 -07001084 * Set policy table for policy routing
1085 *
1086 * @param sw
1087 * @param mplsLabel
1088 */
Sangho Shine020cc32014-10-20 13:28:02 -07001089 public void createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001090 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
Sangho Shine020cc32014-10-20 13:28:02 -07001091 Short srcTcpPort, Short dstTcpPort, int priority, String tid) {
Sangho Shin15273b62014-10-16 22:22:05 -07001092
Sangho Shin81655442014-10-20 14:22:46 -07001093 //HashMap<String, TunnelRouteInfo> routeInfo = stitchInfo.get(tid);
1094 //HashMap<String, Integer> switchGroupPair = tunnelGroupMap.get(tid);
Sangho Shin5b8f5452014-10-20 11:46:01 -07001095
1096 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1097
1098 if (srcMac != null)
1099 packetBuilder.setSrcMac(srcMac);
1100 if (dstMac != null)
1101 packetBuilder.setDstMac(dstMac);
1102 if (etherType != null)
1103 packetBuilder.setEtherType(etherType);
1104 if (srcIp != null)
1105 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1106 if (dstIp != null)
1107 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1108 if (ipProto != null)
1109 packetBuilder.setIpProto(ipProto);
1110 if (srcTcpPort > 0)
1111 packetBuilder.setSrcTcpPort(srcTcpPort);
1112 if (dstTcpPort > 0)
1113 packetBuilder.setDstTcpPort(dstTcpPort);
1114 PacketMatch policyMatch = packetBuilder.build();
Sangho Shin81655442014-10-20 14:22:46 -07001115 TunnelInfo tunnelInfo = tunnelTable.get(tid);
1116 List<TunnelRouteInfo> routes = tunnelInfo.routes;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001117
Sangho Shin81655442014-10-20 14:22:46 -07001118 for (TunnelRouteInfo route : routes) {
Sangho Shin15273b62014-10-16 22:22:05 -07001119 List<Action> actions = new ArrayList<>();
1120 GroupAction groupAction = new GroupAction();
Sangho Shin81655442014-10-20 14:22:46 -07001121 groupAction.setTunnelId(tid);
Sangho Shin15273b62014-10-16 22:22:05 -07001122 actions.add(groupAction);
1123
1124 MatchAction matchAction = new MatchAction(new MatchActionId(
1125 matchActionId++),
Sangho Shin5b8f5452014-10-20 11:46:01 -07001126 new SwitchPort((long) 0, (short) 0), policyMatch, priority,
1127 actions);
Sangho Shin15273b62014-10-16 22:22:05 -07001128 MatchActionOperationEntry maEntry =
1129 new MatchActionOperationEntry(Operator.ADD, matchAction);
1130
1131 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin81655442014-10-20 14:22:46 -07001132 getSwId(route.srcSwDpid));
Sangho Shin15273b62014-10-16 22:22:05 -07001133
1134 if (sw13 != null) {
1135 printMatchActionOperationEntry(sw13, maEntry);
1136 try {
1137 sw13.pushFlow(maEntry);
1138 } catch (IOException e) {
1139 e.printStackTrace();
1140 }
1141 }
1142 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001143
1144 PolicyInfo policyInfo = new PolicyInfo(pid, policyMatch, priority, tid);
Sangho Shine020cc32014-10-20 13:28:02 -07001145 policyTable.put(pid, policyInfo);
Sangho Shin15273b62014-10-16 22:22:05 -07001146 }
1147
1148 /**
Sangho Shin15273b62014-10-16 22:22:05 -07001149 *
1150 *
1151 * @param srcSw
1152 * @param dstSw
1153 * @param route
1154 * @return
1155 */
Sangho Shin81655442014-10-20 14:22:46 -07001156 private List<TunnelRouteInfo> getStitchingRule(List<String> route) {
Sangho Shin15273b62014-10-16 22:22:05 -07001157
1158 if (route.isEmpty() || route.size() < 2)
1159 return null;
1160
Sangho Shin81655442014-10-20 14:22:46 -07001161 List<TunnelRouteInfo> rules = new ArrayList<TunnelRouteInfo>();
Sangho Shin15273b62014-10-16 22:22:05 -07001162
1163 Switch srcSw = this.getSwitchFromNodeId(route.get(0));
1164 String srcDpid = srcSw.getDpid().toString();
1165
1166 if (route.size() <= MAX_NUM_LABELS+1) {
Sangho Shine020cc32014-10-20 13:28:02 -07001167 TunnelRouteInfo info = new TunnelRouteInfo();
Sangho Shin15273b62014-10-16 22:22:05 -07001168 info.setSrcDpid(srcSw.getDpid().toString());
1169 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, route.get(1));
1170 info.setFwdSwDpid(fwdSwDpids);
1171 route.remove(0);
1172 info.setRoute(route);
Sangho Shin81655442014-10-20 14:22:46 -07001173 rules.add(info);
Sangho Shin15273b62014-10-16 22:22:05 -07001174 return rules;
1175 }
1176
1177 int i = 0;
Sangho Shine020cc32014-10-20 13:28:02 -07001178 TunnelRouteInfo routeInfo = new TunnelRouteInfo();
Sangho Shin15273b62014-10-16 22:22:05 -07001179 String prevNodeId = null;
1180 boolean checkNeighbor = true;
1181
1182 for (String nodeId: route) {
1183 if (i == 0) {
1184 routeInfo.setSrcDpid(srcDpid);
1185 srcSw = getSwitchFromNodeId(nodeId);
1186 i++;
1187 }
1188 else if (i == 1) {
1189 if (checkNeighbor) {
1190 // Check if next node is the neighbor SW of the source SW
1191 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
1192 if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
1193 log.debug("There is no route from node {} to node {}", srcSw.getDpid(), nodeId);
1194 return null;
1195 }
1196 // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
1197 boolean match = false;
1198 for (Dpid dpid: fwdSwDpids) {
1199 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1200 List<Dpid> fwdSws = new ArrayList<Dpid>();
1201 fwdSws.add(dpid);
1202 routeInfo.setFwdSwDpid(fwdSws);
1203 match = true;
1204 break;
1205 }
1206 }
1207 if (!match) {
1208 routeInfo.addRoute(nodeId);
1209 routeInfo.setFwdSwDpid(fwdSwDpids);
1210 i++;
1211 }
1212
1213 checkNeighbor = false;
1214 }
1215 else {
1216 routeInfo.addRoute(nodeId);
1217 i++;
1218 }
1219 }
1220 else {
1221 routeInfo.addRoute(nodeId);
1222 i++;
1223 }
1224
1225 if (i == MAX_NUM_LABELS+1) {
Sangho Shin81655442014-10-20 14:22:46 -07001226 rules.add(routeInfo);
Sangho Shine020cc32014-10-20 13:28:02 -07001227 routeInfo = new TunnelRouteInfo();
Sangho Shin15273b62014-10-16 22:22:05 -07001228 srcSw = getSwitchFromNodeId(nodeId);
1229 srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
1230 routeInfo.setSrcDpid(srcDpid);
1231 i = 1;
1232 checkNeighbor = true;
1233 }
1234 }
1235
1236 if (i < MAX_NUM_LABELS+1) {
Sangho Shin81655442014-10-20 14:22:46 -07001237 rules.add(routeInfo);
Sangho Shin15273b62014-10-16 22:22:05 -07001238 }
1239
1240 return rules;
1241 }
1242
Sangho Shin5b8f5452014-10-20 11:46:01 -07001243 /**
1244 * Remove all policies applied to specific tunnel.
1245 *
1246 * @param srcMac
1247 * @param dstMac
1248 * @param etherType
1249 * @param srcIp
1250 * @param dstIp
1251 * @param ipProto
1252 * @param srcTcpPort
1253 * @param dstTcpPort
1254 * @param tid
1255 */
Sangho Shine020cc32014-10-20 13:28:02 -07001256 public void removePolicy(String pid) {
1257 PolicyInfo policyInfo = policyTable.get(pid);
Sangho Shin5b8f5452014-10-20 11:46:01 -07001258 PacketMatch policyMatch = policyInfo.match;
Sangho Shine020cc32014-10-20 13:28:02 -07001259 String tid = policyInfo.tunnelId;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001260 int priority = policyInfo.priority;
1261
1262 List<Action> actions = new ArrayList<>();
1263 int gropuId = 0; // dummy group ID
1264 GroupAction groupAction = new GroupAction();
1265 groupAction.setGroupId(gropuId);
1266 actions.add(groupAction);
1267
1268 MatchAction matchAction = new MatchAction(new MatchActionId(
1269 matchActionId++),
1270 new SwitchPort((long) 0, (short) 0), policyMatch, priority,
1271 actions);
1272 MatchActionOperationEntry maEntry =
1273 new MatchActionOperationEntry(Operator.REMOVE, matchAction);
1274
Sangho Shin81655442014-10-20 14:22:46 -07001275 //HashMap<String, Integer> groupInfo = tunnelGroupMap.get(tid);
Sangho Shin5b8f5452014-10-20 11:46:01 -07001276
Sangho Shin81655442014-10-20 14:22:46 -07001277
1278 TunnelInfo tunnelInfo = tunnelTable.get(tid);
1279 List<TunnelRouteInfo> routes = tunnelInfo.routes;
1280
1281 for (TunnelRouteInfo route : routes) {
Sangho Shin5b8f5452014-10-20 11:46:01 -07001282 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin81655442014-10-20 14:22:46 -07001283 getSwId(route.srcSwDpid));
Sangho Shin5b8f5452014-10-20 11:46:01 -07001284
1285 if (sw13 != null) {
1286 printMatchActionOperationEntry(sw13, maEntry);
1287 try {
1288 sw13.pushFlow(maEntry);
1289 } catch (IOException e) {
1290 e.printStackTrace();
1291 log.debug("policy remove failed due to pushFlow() exception");
1292 return;
1293 }
1294 }
1295 }
1296
1297 log.debug("Policy {} is removed.", pid);
Sangho Shine020cc32014-10-20 13:28:02 -07001298 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001299
Sangho Shin7330c032014-10-20 10:34:51 -07001300
Sangho Shine020cc32014-10-20 13:28:02 -07001301 public void removeTunnel(String tunnelId) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001302
1303
1304 }
1305
Sangho Shin7330c032014-10-20 10:34:51 -07001306 // ************************************
1307 // Utility functions
1308 // ************************************
1309
Sangho Shin15273b62014-10-16 22:22:05 -07001310 /**
Sangho Shin7330c032014-10-20 10:34:51 -07001311 * Get the forwarding Switch DPIDs to send packets to a node
Sangho Shin15273b62014-10-16 22:22:05 -07001312 *
Sangho Shin7330c032014-10-20 10:34:51 -07001313 * @param srcSw source switch
1314 * @param nodeId destination node Id
1315 * @return list of switch DPID to forward packets to
Sangho Shin15273b62014-10-16 22:22:05 -07001316 */
Sangho Shin7330c032014-10-20 10:34:51 -07001317 private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
Sangho Shin15273b62014-10-16 22:22:05 -07001318
Sangho Shin7330c032014-10-20 10:34:51 -07001319 List<Dpid> fwdSws = new ArrayList<Dpid>();
1320 Switch destSw = null;
Sangho Shin15273b62014-10-16 22:22:05 -07001321
Sangho Shin7330c032014-10-20 10:34:51 -07001322 destSw = getSwitchFromNodeId(nodeId);
1323
1324 if (destSw == null) {
1325 log.debug("Cannot find the switch with ID {}", nodeId);
1326 return null;
1327 }
1328
1329 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1330
1331 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1332 ecmpSPG.getAllLearnedSwitchesAndVia();
1333 for (Integer itrIdx : switchVia.keySet()) {
1334 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1335 switchVia.get(itrIdx);
1336 for (Switch targetSw : swViaMap.keySet()) {
1337 String destSwDpid = destSw.getDpid().toString();
1338 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1339 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1340 if (via.isEmpty()) {
1341 fwdSws.add(destSw.getDpid());
1342 }
1343 else {
1344 fwdSws.add(via.get(0));
1345 }
1346 }
1347 }
1348 }
1349 }
1350
1351 return fwdSws;
Sangho Shin15273b62014-10-16 22:22:05 -07001352 }
1353
Sangho Shin7330c032014-10-20 10:34:51 -07001354 /**
1355 * Get switch for the node Id specified
1356 *
1357 * @param nodeId node ID for switch
1358 * @return Switch
1359 */
1360 private Switch getSwitchFromNodeId(String nodeId) {
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001361
Sangho Shin7330c032014-10-20 10:34:51 -07001362 for (Switch sw : mutableTopology.getSwitches()) {
1363 String id = sw.getStringAttribute("nodeSid");
1364 if (id.equals(nodeId)) {
1365 return sw;
1366 }
1367 }
1368
1369 return null;
1370 }
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001371
Sangho Shin43cee112014-09-25 16:43:34 -07001372 /**
Sangho Shin7330c032014-10-20 10:34:51 -07001373 * Convert a string DPID to its Switch Id (integer)
Sangho Shinfbc572c2014-10-02 16:37:05 -07001374 *
Sangho Shin7330c032014-10-20 10:34:51 -07001375 * @param dpid
1376 * @return
Sangho Shin43cee112014-09-25 16:43:34 -07001377 */
Sangho Shin7330c032014-10-20 10:34:51 -07001378 private long getSwId(String dpid) {
Sangho Shin43cee112014-09-25 16:43:34 -07001379
Sangho Shin7330c032014-10-20 10:34:51 -07001380 long swId = 0;
Sangho Shin43cee112014-09-25 16:43:34 -07001381
Sangho Shin7330c032014-10-20 10:34:51 -07001382 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1383 if (swIdHexStr != null)
1384 swId = Integer.decode(swIdHexStr);
Sangho Shin43cee112014-09-25 16:43:34 -07001385
Sangho Shin7330c032014-10-20 10:34:51 -07001386 return swId;
1387 }
Sangho Shin43cee112014-09-25 16:43:34 -07001388
Sangho Shin7330c032014-10-20 10:34:51 -07001389 /**
1390 * Check if the switch is the edge router or not.
1391 *
1392 * @param dpid Dpid of the switch to check
1393 * @return true if it is an edge router, otherwise false
1394 */
1395 private boolean IsEdgeRouter(String dpid) {
Sangho Shin0df01982014-09-25 17:11:18 -07001396
Sangho Shin7330c032014-10-20 10:34:51 -07001397 for (Switch sw : mutableTopology.getSwitches()) {
1398 String dpidStr = sw.getDpid().toString();
1399 if (dpid.equals(dpidStr)) {
1400 /*
1401 String subnetInfo = sw.getStringAttribute("subnets");
1402 if (subnetInfo == null || subnetInfo.equals("[]")) {
1403 return false;
1404 }
1405 else
1406 return true;
1407 */
1408 String isEdge = sw.getStringAttribute("isEdgeRouter");
1409 if (isEdge != null) {
1410 if (isEdge.equals("true"))
1411 return true;
1412 else
1413 return false;
1414 }
Sangho Shin43cee112014-09-25 16:43:34 -07001415 }
1416 }
1417
Sangho Shin7330c032014-10-20 10:34:51 -07001418 return false;
Sangho Shineb083032014-09-22 16:11:34 -07001419 }
1420
1421 /**
1422 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001423 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001424 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001425 * @return MPLS label for the switch
1426 */
Sangho Shin43cee112014-09-25 16:43:34 -07001427 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001428
1429 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001430 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001431 String dpidStr = sw.getDpid().toString();
1432 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001433 mplsLabel = sw.getStringAttribute("nodeSid");
1434 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001435 }
1436 }
1437
Sangho Shineb083032014-09-22 16:11:34 -07001438 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001439 }
1440
Sangho Shineb083032014-09-22 16:11:34 -07001441 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001442 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001443 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001444 * @param addr - subnet address to match
1445 * @param addr1 - IP address to check
1446 * @return true if the IP address matches to the subnet, otherwise false
1447 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001448 public boolean netMatch(String addr, String addr1) { // addr is subnet
1449 // address and addr1 is
1450 // ip address. Function
1451 // will return true, if
1452 // addr1 is within
1453 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001454
1455 String[] parts = addr.split("/");
1456 String ip = parts[0];
1457 int prefix;
1458
1459 if (parts.length < 2) {
1460 prefix = 0;
1461 } else {
1462 prefix = Integer.parseInt(parts[1]);
1463 }
1464
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001465 Inet4Address a = null;
1466 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001467 try {
1468 a = (Inet4Address) InetAddress.getByName(ip);
1469 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001470 } catch (UnknownHostException e) {
1471 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001472
1473 byte[] b = a.getAddress();
1474 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001475 ((b[1] & 0xFF) << 16) |
1476 ((b[2] & 0xFF) << 8) |
1477 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001478
1479 byte[] b1 = a1.getAddress();
1480 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001481 ((b1[1] & 0xFF) << 16) |
1482 ((b1[2] & 0xFF) << 8) |
1483 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001484
1485 int mask = ~((1 << (32 - prefix)) - 1);
1486
1487 if ((ipInt & mask) == (ipInt1 & mask)) {
1488 return true;
1489 }
1490 else {
1491 return false;
1492 }
1493 }
Sangho Shineb083032014-09-22 16:11:34 -07001494
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001495 /**
1496 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001497 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001498 * @param sw - Switch to add the rule
1499 * @param hostIpAddress Destination host IP address
1500 * @param hostMacAddress Destination host MAC address
1501 */
Sangho Shineb083032014-09-22 16:11:34 -07001502 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1503 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
Sangho Shineb083032014-09-22 16:11:34 -07001504 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001505
Sangho Shin463bee52014-09-29 15:14:43 -07001506 /**
1507 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001508 *
Sangho Shin463bee52014-09-29 15:14:43 -07001509 * @param ipv4
1510 */
Sangho Shin7330c032014-10-20 10:34:51 -07001511 public void addPacketToPacketBuffer(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001512 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001513 }
1514
1515 /**
1516 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001517 *
Sangho Shin463bee52014-09-29 15:14:43 -07001518 * @param destIp Destination address of packets to retrieve
1519 */
1520 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1521
1522 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1523
Sangho Shin61535402014-10-01 11:37:14 -07001524 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001525 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001526 int dest = ip.getDestinationAddress();
1527 IPv4Address ip1 = IPv4Address.of(dest);
1528 IPv4Address ip2 = IPv4Address.of(destIp);
1529 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001530 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001531 }
1532 }
1533 }
1534
1535 return bufferedPackets;
1536 }
1537
Sangho Shin7330c032014-10-20 10:34:51 -07001538 /**
1539 * Get MAC address to known hosts
1540 *
1541 * @param destinationAddress IP address to get MAC address
1542 * @return MAC Address to given IP address
1543 */
1544 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
1545
1546 // Can't we get the host IP address from the TopologyService ??
1547
1548 Iterator<ArpEntry> iterator = arpEntries.iterator();
1549
1550 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
1551 byte[] ipAddressInByte = ipAddress.getBytes();
1552
1553 while (iterator.hasNext()) {
1554 ArpEntry arpEntry = iterator.next();
1555 byte[] address = arpEntry.targetIpAddress;
1556
1557 IPv4Address a = IPv4Address.of(address);
1558 IPv4Address b = IPv4Address.of(ipAddressInByte);
1559
1560 if (a.equals(b)) {
1561 log.debug("Found an arp entry");
1562 return arpEntry.targetMacAddress;
1563 }
1564 }
1565
1566 return null;
1567 }
1568
1569 /**
1570 * Send an ARP request via ArpHandler
1571 *
1572 * @param destinationAddress
1573 * @param sw
1574 * @param inPort
1575 *
1576 */
1577 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
1578 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
1579 }
1580
1581
1582 // ************************************
1583 // Test functions
1584 // ************************************
1585
Sangho Shin55d00e12014-10-20 12:13:07 -07001586 /*
Sangho Shin7330c032014-10-20 10:34:51 -07001587 private void runTest() {
1588
Sangho Shin5b8f5452014-10-20 11:46:01 -07001589 if (testMode == POLICY_ADD1) {
1590 String[] routeArray = {"101", "105", "110"};
1591 List<String> routeList = new ArrayList<String>();
1592 for (int i = 0; i < routeArray.length; i++)
1593 routeList.add(routeArray[i]);
Sangho Shin7330c032014-10-20 10:34:51 -07001594
Sangho Shin5b8f5452014-10-20 11:46:01 -07001595 if (createTunnel(1, routeList)) {
1596 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1597 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1598
1599 log.debug("Set the policy 1");
1600 this.setPolicyTable(1, null, null, Ethernet.TYPE_IPV4, srcIp,
1601 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
1602 1);
1603 testMode = POLICY_ADD2;
1604 testTask.reschedule(10, TimeUnit.SECONDS);
1605 }
1606 else {
1607 // retry it
1608 testTask.reschedule(5, TimeUnit.SECONDS);
1609 }
Sangho Shin7330c032014-10-20 10:34:51 -07001610 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001611 else if (testMode == POLICY_ADD2) {
1612 String[] routeArray = {"101", "102", "103", "104", "105", "108",
1613 "110"};
1614 List<String> routeList = new ArrayList<String>();
1615 for (int i = 0; i < routeArray.length; i++)
1616 routeList.add(routeArray[i]);
1617
1618 if (createTunnel(2, routeList)) {
1619 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1620 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1621
1622 log.debug("Set the policy 2");
1623 this.setPolicyTable(2, null, null, Ethernet.TYPE_IPV4, srcIp,
1624 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 20000,
1625 2);
1626 testMode = POLICY_REMOVE2;
1627 testTask.reschedule(10, TimeUnit.SECONDS);
1628 }
1629 else {
1630 log.debug("Retry it");
1631 testTask.reschedule(5, TimeUnit.SECONDS);
1632 }
Sangho Shin7330c032014-10-20 10:34:51 -07001633 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001634 else if (testMode == POLICY_REMOVE2){
1635 log.debug("Remove the policy 2");
1636 this.removePolicy(2);
1637 testMode = POLICY_REMOVE1;
1638 testTask.reschedule(10, TimeUnit.SECONDS);
1639 }
1640 else if (testMode == POLICY_REMOVE1){
1641 log.debug("Remove the policy 1");
1642 this.removePolicy(1);
1643 }
1644
Sangho Shin7330c032014-10-20 10:34:51 -07001645 }
Sangho Shin55d00e12014-10-20 12:13:07 -07001646 */
1647
1648 private void runTest() {
1649
1650 if (testMode == POLICY_ADD1) {
1651 String[] routeArray = {"101", "105", "110"};
1652 List<Dpid> routeList = new ArrayList<Dpid>();
1653 for (int i = 0; i < routeArray.length; i++) {
1654 Dpid dpid = getSwitchFromNodeId(routeArray[i]).getDpid();
1655 routeList.add(dpid);
1656 }
1657
1658 if (createTunnel("1", routeList)) {
1659 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1660 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1661
1662 log.debug("Set the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001663 this.createPolicy("1", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001664 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
Sangho Shine020cc32014-10-20 13:28:02 -07001665 "1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001666 testMode = POLICY_ADD2;
1667 testTask.reschedule(10, TimeUnit.SECONDS);
1668 }
1669 else {
1670 // retry it
1671 testTask.reschedule(5, TimeUnit.SECONDS);
1672 }
1673 }
1674 else if (testMode == POLICY_ADD2) {
1675 String[] routeArray = {"101", "102", "103", "104", "105", "108",
1676 "110"};
1677 List<Dpid> routeList = new ArrayList<Dpid>();
1678 for (int i = 0; i < routeArray.length; i++) {
1679 Dpid dpid = getSwitchFromNodeId(routeArray[i]).getDpid();
1680 routeList.add(dpid);
1681 }
1682
1683 if (createTunnel("2", routeList)) {
1684 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1685 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1686
1687 log.debug("Set the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001688 this.createPolicy("2", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001689 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 20000,
Sangho Shine020cc32014-10-20 13:28:02 -07001690 "2");
Sangho Shin55d00e12014-10-20 12:13:07 -07001691 testMode = POLICY_REMOVE2;
1692 testTask.reschedule(10, TimeUnit.SECONDS);
1693 }
1694 else {
1695 log.debug("Retry it");
1696 testTask.reschedule(5, TimeUnit.SECONDS);
1697 }
1698 }
1699 else if (testMode == POLICY_REMOVE2){
1700 log.debug("Remove the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001701 this.removePolicy("2");
Sangho Shin55d00e12014-10-20 12:13:07 -07001702 testMode = POLICY_REMOVE1;
1703 testTask.reschedule(10, TimeUnit.SECONDS);
1704 }
1705 else if (testMode == POLICY_REMOVE1){
1706 log.debug("Remove the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001707 this.removePolicy("1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001708 }
1709
1710 }
Sangho Shin7330c032014-10-20 10:34:51 -07001711
1712 private void runTest1() {
1713
1714 String dpid1 = "00:00:00:00:00:00:00:01";
1715 String dpid2 = "00:00:00:00:00:00:00:0a";
1716 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1717 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1718
1719 if (srcSw == null || dstSw == null) {
1720 testTask.reschedule(1, TimeUnit.SECONDS);
1721 log.debug("Switch is gone. Reschedule the test");
1722 return;
1723 }
1724
1725 String[] routeArray = {"101", "102", "105", "108", "110"};
1726 List<String> routeList = new ArrayList<String>();
1727 for (int i = 0; i < routeArray.length; i++)
1728 routeList.add(routeArray[i]);
1729
1730 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1731
1732 log.debug("Test set is {}", routeList.toString());
1733 log.debug("Result set is {}", optimizedRoute.toString());
1734
1735
1736 }
1737
1738 /**
1739 * print tunnel info - used only for debugging.
1740 * @param targetSw
1741 *
1742 * @param fwdSwDpids
1743 * @param ids
1744 * @param tunnelId
1745 */
Sangho Shine020cc32014-10-20 13:28:02 -07001746 private void printTunnelInfo(IOF13Switch targetSw, String tunnelId,
Sangho Shin7330c032014-10-20 10:34:51 -07001747 List<String> ids, NeighborSet ns) {
1748 StringBuilder logStr = new StringBuilder("In switch " +
1749 targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
1750 for (String id: ids)
1751 logStr.append(id + "-");
1752 logStr.append(" output to ");
1753 for (Dpid dpid: ns.getDpids())
1754 logStr.append(dpid + " - ");
1755
1756 log.debug(logStr.toString());
1757
1758 }
1759
1760 /**
1761 * Debugging function to print out the Match Action Entry
1762 * @param sw13
1763 *
1764 * @param maEntry
1765 */
1766 private void printMatchActionOperationEntry(
1767 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
1768
1769 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
1770
1771 MatchAction ma = maEntry.getTarget();
1772 Match m = ma.getMatch();
1773 List<Action> actions = ma.getActions();
1774
1775 if (m instanceof Ipv4Match) {
1776 logStr.append("If the IP matches with ");
1777 IPv4Net ip = ((Ipv4Match) m).getDestination();
1778 logStr.append(ip.toString());
1779 logStr.append(" then ");
1780 }
1781 else if (m instanceof MplsMatch) {
1782 logStr.append("If the MPLS label matches with ");
1783 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1784 logStr.append(mplsLabel);
1785 logStr.append(" then ");
1786 }
1787 else if (m instanceof PacketMatch) {
1788 GroupAction ga = (GroupAction)actions.get(0);
1789 logStr.append("if the policy match is XXX then go to group " +
1790 ga.getGroupId());
1791 log.debug(logStr.toString());
1792 return;
1793 }
1794
1795 logStr.append(" do { ");
1796 for (Action action : actions) {
1797 if (action instanceof CopyTtlInAction) {
1798 logStr.append("copy ttl In, ");
1799 }
1800 else if (action instanceof CopyTtlOutAction) {
1801 logStr.append("copy ttl Out, ");
1802 }
1803 else if (action instanceof DecMplsTtlAction) {
1804 logStr.append("Dec MPLS TTL , ");
1805 }
1806 else if (action instanceof GroupAction) {
1807 logStr.append("Forward packet to < ");
1808 NeighborSet dpids = ((GroupAction) action).getDpids();
1809 logStr.append(dpids.toString() + ",");
1810
1811 }
1812 else if (action instanceof PopMplsAction) {
1813 logStr.append("Pop MPLS label, ");
1814 }
1815 else if (action instanceof PushMplsAction) {
1816 logStr.append("Push MPLS label, ");
1817 }
1818 else if (action instanceof SetMplsIdAction) {
1819 int id = ((SetMplsIdAction) action).getMplsId();
1820 logStr.append("Set MPLS ID as " + id + ", ");
1821 }
1822 }
1823
1824 log.debug(logStr.toString());
1825
1826 }
1827
1828
1829 // ************************************
1830 // Unused classes and functions
1831 // ************************************
1832
1833 /**
1834 * Temporary class to to keep ARP entry
1835 *
1836 */
1837 private class ArpEntry {
1838
1839 byte[] targetMacAddress;
1840 byte[] targetIpAddress;
1841
1842 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
1843 this.targetMacAddress = macAddress;
1844 this.targetIpAddress = ipAddress;
1845 }
1846 }
1847
1848 /**
1849 * This class is used only for link recovery optimization in
1850 * modifyEcmpRoutingRules() function.
1851 * TODO: please remove if the optimization is not used at all
1852 */
1853 private class SwitchPair {
1854 private Switch src;
1855 private Switch dst;
1856
1857 public SwitchPair(Switch src, Switch dst) {
1858 this.src = src;
1859 this.dst = dst;
1860 }
1861
1862 public Switch getSource() {
1863 return src;
1864 }
1865
1866 public Switch getDestination() {
1867 return dst;
1868 }
1869 }
1870
1871 /**
1872 * Update ARP Cache using ARP packets It is used to set destination MAC
1873 * address to forward packets to known hosts. But, it will be replace with
1874 * Host information of Topology service later.
1875 *
1876 * @param arp APR packets to use for updating ARP entries
1877 */
1878 public void updateArpCache(ARP arp) {
1879
1880 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
1881 arp.getSenderProtocolAddress());
1882 // TODO: Need to check the duplication
1883 arpEntries.add(arpEntry);
1884 }
1885
1886 /**
1887 * Modify the routing rules for the lost links
1888 * - Recompute the path if the link failed is included in the path
1889 * (including src and dest).
1890 *
1891 * @param newLink
1892 */
1893 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
1894
1895 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
1896 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
1897
1898 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
1899 Switch rootSw = ecmpSPG.getRootSwitch();
1900 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
1901 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
1902 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
1903 for (Switch destSw: p.keySet()) {
1904 ArrayList<Path> path = p.get(destSw);
1905 if (checkPath(path, linkRemoved)) {
1906 boolean found = false;
1907 for (SwitchPair pair: linksToRecompute) {
1908 if (pair.getSource().getDpid() == rootSw.getDpid() &&
1909 pair.getSource().getDpid() == destSw.getDpid()) {
1910 found = true;
1911 }
1912 }
1913 if (!found) {
1914 linksToRecompute.add(new SwitchPair(rootSw, destSw));
1915 }
1916 }
1917 }
1918 }
1919 }
1920
1921 // Recompute the path for the specific route
1922 for (SwitchPair pair: linksToRecompute) {
1923
1924 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
1925 // We need the following function for optimization
1926 //ECMPShortestPathGraph ecmpSPG =
1927 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
1928 ECMPShortestPathGraph ecmpSPG =
1929 new ECMPShortestPathGraph(pair.getSource());
1930 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
1931 }
1932 }
1933
1934 /**
1935 * Optimize the mpls label
1936 * The feature will be used only for policy of "avoid a specific switch".
1937 * Check route to each router in route backward.
1938 * If there is only one route to the router and the routers are included in
1939 * the route, remove the id from the path.
1940 * A-B-C-D-E => A-B-C-D-E -> A-E
1941 * | | => A-B-H-I -> A-I
Sangho Shin5b8f5452014-10-20 11:46:01 -07001942 * F-G-H-I => A-D-I > A-D-I
Sangho Shin7330c032014-10-20 10:34:51 -07001943 */
1944 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
1945
1946 List<String> optimizedPath = new ArrayList<String>();
1947 optimizedPath.addAll(route);
1948 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1949
1950 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
1951 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
1952 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
1953 for (Switch s: p.keySet()) {
1954 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
1955 ArrayList<Path> ecmpPaths = p.get(s);
1956 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
1957 for (Path path: ecmpPaths) {
1958 for (LinkData link: path) {
1959 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
1960 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
1961 if (optimizedPath.contains(srcId)) {
1962 optimizedPath.remove(srcId);
1963 }
1964 if (optimizedPath.contains(dstId)) {
1965 optimizedPath.remove(dstId);
1966 }
1967 }
1968 }
1969 }
1970 }
1971 }
1972 }
1973
1974 return optimizedPath;
1975
1976 }
1977
1978 /**
1979 * Check if the path is affected from the link removed
1980 *
1981 * @param path Path to check
1982 * @param linkRemoved link removed
1983 * @return true if the path contains the link removed
1984 */
1985 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
1986
1987 for (Path ppp: path) {
1988 // TODO: need to check if this is a bidirectional or
1989 // unidirectional
1990 for (LinkData link: ppp) {
1991 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
1992 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
1993 return true;
1994 }
1995 }
1996
1997 return false;
1998 }
Sangho Shin15273b62014-10-16 22:22:05 -07001999
2000
Sangho Shin2f263692014-09-15 14:09:41 -07002001}