blob: cb5fa32ffe818511fd4402758e5e0cbbdfd415e8 [file] [log] [blame]
Sangho Shin2f263692014-09-15 14:09:41 -07001package net.onrc.onos.apps.segmentrouting;
2
Sangho Shin9c0f4c32014-09-26 16:02:38 -07003import java.io.IOException;
Sangho Shin1aa93542014-09-22 09:49:44 -07004import java.net.Inet4Address;
5import java.net.InetAddress;
6import java.net.UnknownHostException;
Sangho Shin2f263692014-09-15 14:09:41 -07007import java.util.ArrayList;
8import java.util.Collection;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -07009import java.util.HashMap;
Sangho Shin5be3e532014-10-03 17:20:58 -070010import java.util.HashSet;
Sangho Shin2f263692014-09-15 14:09:41 -070011import java.util.Iterator;
12import java.util.List;
13import java.util.Map;
Sangho Shin5be3e532014-10-03 17:20:58 -070014import java.util.Set;
Sangho Shin61535402014-10-01 11:37:14 -070015import java.util.concurrent.ConcurrentLinkedQueue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070016import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070017import java.util.concurrent.ScheduledExecutorService;
18import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070019import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070020
21import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070022import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070023import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070024import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070025import net.floodlightcontroller.core.module.FloodlightModuleContext;
26import net.floodlightcontroller.core.module.FloodlightModuleException;
27import net.floodlightcontroller.core.module.IFloodlightModule;
28import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070029import net.floodlightcontroller.core.util.SingletonTask;
30import net.floodlightcontroller.threadpool.IThreadPoolService;
Sangho Shin15273b62014-10-16 22:22:05 -070031import net.floodlightcontroller.util.MACAddress;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070032import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070033import net.onrc.onos.api.packet.IPacketService;
34import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070035import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070036import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070037import net.onrc.onos.core.matchaction.MatchAction;
38import net.onrc.onos.core.matchaction.MatchActionId;
39import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070040import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070041import net.onrc.onos.core.matchaction.action.Action;
42import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
43import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
44import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
45import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
46import net.onrc.onos.core.matchaction.action.GroupAction;
47import net.onrc.onos.core.matchaction.action.PopMplsAction;
48import net.onrc.onos.core.matchaction.action.PushMplsAction;
49import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070050import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070051import net.onrc.onos.core.matchaction.match.Match;
52import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070053import net.onrc.onos.core.matchaction.match.PacketMatch;
54import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070055import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070056import net.onrc.onos.core.packet.Ethernet;
57import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070058import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070059import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070060import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070061import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070062import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070063import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070064import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070065import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070066import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070067import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070068import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070069import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070070import net.onrc.onos.core.util.IPv4Net;
71import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070072
Sangho Shin43cee112014-09-25 16:43:34 -070073import org.json.JSONArray;
74import org.json.JSONException;
Saurav Dasa962a692014-10-17 14:52:38 -070075import org.projectfloodlight.openflow.protocol.OFBarrierReply;
Saurav Dasbc594a42014-09-25 20:13:50 -070076import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070077import org.projectfloodlight.openflow.types.IPv4Address;
78import org.slf4j.Logger;
79import org.slf4j.LoggerFactory;
80
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070081public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070082 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070083
84 private static final Logger log = LoggerFactory
85 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070086
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -070087 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070088 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070089 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -070090 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070091
92 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070093 private ArpHandler arpHandler;
94 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070095 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070096 private IThreadPoolService threadPool;
97 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -070098 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -070099 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700100 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700101
Sangho Shinfbc572c2014-10-02 16:37:05 -0700102 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700103 private HashMap<String, LinkData> linksDown;
104 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700105 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shin15273b62014-10-16 22:22:05 -0700106 private HashMap<Integer, HashMap<String, PolicyRouteInfo>> stitchInfo;
107 private HashMap<Integer, HashMap<String, Integer>> tunnelGroupMap;
Sangho Shin6f47dd32014-10-17 23:10:39 -0700108 private HashMap<Integer, PolicyInfo> policyTable;
Sangho Shinbb2b8362014-10-17 21:07:16 -0700109
110 private int testMode = 0;
Sangho Shinbce900e2014-10-07 17:13:23 -0700111
112 private int numOfEvents = 0;
113 private int numOfEventProcess = 0;
114 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700115 private long matchActionId = 0L;
Sangho Shin23f898d2014-10-13 16:54:00 -0700116 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700117 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700118
Sangho Shin6f47dd32014-10-17 23:10:39 -0700119 private final int POLICY_ADD1 = 1;
120 private final int POLICY_ADD2 = 2;
121 private final int POLICY_REMOVE1 = 3;
122 private final int POLICY_REMOVE2 = 4;
Sangho Shinbb2b8362014-10-17 21:07:16 -0700123
Sangho Shin2f263692014-09-15 14:09:41 -0700124 @Override
125 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
126 // TODO Auto-generated method stub
127 return null;
128 }
129
130 @Override
131 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
132 // TODO Auto-generated method stub
133 return null;
134 }
135
136 @Override
137 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
138 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
139
140 l.add(IFloodlightProviderService.class);
141 l.add(IConfigInfoService.class);
142 l.add(ITopologyService.class);
143 l.add(IPacketService.class);
144 l.add(IFlowPusherService.class);
145 l.add(ITopologyService.class);
146
147 return l;
148
149 }
150
151 @Override
152 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700153 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700154 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700155 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700156 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700157 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700158 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700159 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700160 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700161 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700162 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700163 linksDown = new HashMap<String, LinkData>();
164 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700165 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700166 stitchInfo = new HashMap<Integer, HashMap<String, PolicyRouteInfo>>();
167 packetService = context.getServiceImpl(IPacketService.class);
168 tunnelGroupMap = new HashMap<Integer, HashMap<String, Integer>>();
Sangho Shin6f47dd32014-10-17 23:10:39 -0700169 policyTable = new HashMap<Integer, PolicyInfo>();
Sangho Shin2f263692014-09-15 14:09:41 -0700170
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700171 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700172 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700173
Sangho Shin99918bd2014-10-08 15:52:35 -0700174
Sangho Shin2f263692014-09-15 14:09:41 -0700175 }
176
177 @Override
178 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700179 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700180
Sangho Shinc8d2f592014-09-30 16:53:57 -0700181 discoveryTask = new SingletonTask(ses, new Runnable() {
182 @Override
183 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700184 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700185 }
186 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700187
188 linkAddTask = new SingletonTask(ses, new Runnable() {
189 @Override
190 public void run() {
191 delayedAddLink();
192 }
193 });
194
Sangho Shin15273b62014-10-16 22:22:05 -0700195 testTask = new SingletonTask(ses, new Runnable() {
196 @Override
197 public void run() {
198 runTest();
199 }
200 });
201
Sangho Shinbb2b8362014-10-17 21:07:16 -0700202 //policy routing test task
Sangho Shin6f47dd32014-10-17 23:10:39 -0700203 testMode = POLICY_ADD1;
Sangho Shinbb2b8362014-10-17 21:07:16 -0700204 testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700205 }
206
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700207 @Override
208 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700209 if (payload.getEtherType() == Ethernet.TYPE_ARP)
210 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700211 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700212 addPacket((IPv4) payload.getPayload());
213 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
214 icmpHandler.processPacketIn(sw, inPort, payload);
215 else
216 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700217 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700218 else {
219 log.debug("{}", payload.toString());
220 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700221 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700222
Sangho Shin2f263692014-09-15 14:09:41 -0700223 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700224 * Update ARP Cache using ARP packets It is used to set destination MAC
225 * address to forward packets to known hosts. But, it will be replace with
226 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700227 *
Sangho Shin2f263692014-09-15 14:09:41 -0700228 * @param arp APR packets to use for updating ARP entries
229 */
230 public void updateArpCache(ARP arp) {
231
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700232 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
233 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700234 // TODO: Need to check the duplication
235 arpEntries.add(arpEntry);
236 }
237
238 /**
239 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700240 *
Sangho Shin2f263692014-09-15 14:09:41 -0700241 * @param destinationAddress IP address to get MAC address
242 * @return MAC Address to given IP address
243 */
244 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
245
246 // Can't we get the host IP address from the TopologyService ??
247
248 Iterator<ArpEntry> iterator = arpEntries.iterator();
249
250 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
251 byte[] ipAddressInByte = ipAddress.getBytes();
252
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700253 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700254 ArpEntry arpEntry = iterator.next();
255 byte[] address = arpEntry.targetIpAddress;
256
257 IPv4Address a = IPv4Address.of(address);
258 IPv4Address b = IPv4Address.of(ipAddressInByte);
259
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700260 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700261 log.debug("Found an arp entry");
262 return arpEntry.targetMacAddress;
263 }
264 }
265
266 return null;
267 }
268
Sangho Shineb083032014-09-22 16:11:34 -0700269 /**
270 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700271 *
Sangho Shineb083032014-09-22 16:11:34 -0700272 * @param destinationAddress
273 * @param sw
274 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700275 *
Sangho Shineb083032014-09-22 16:11:34 -0700276 */
277 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
278 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
279 }
Sangho Shin2f263692014-09-15 14:09:41 -0700280
281 /**
282 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700283 *
Sangho Shin2f263692014-09-15 14:09:41 -0700284 */
285 private class ArpEntry {
286
287 byte[] targetMacAddress;
288 byte[] targetIpAddress;
289
290 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
291 this.targetMacAddress = macAddress;
292 this.targetIpAddress = ipAddress;
293 }
Sangho Shin2f263692014-09-15 14:09:41 -0700294 }
Sangho Shineb083032014-09-22 16:11:34 -0700295
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700296 /**
297 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700298 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700299 * @param topologyEvents the generated Topology Events
300 * @see TopologyEvents
301 */
302 public void topologyEvents(TopologyEvents topologyEvents)
303 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700304 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700305 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700306 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700307
Sangho Shin23f898d2014-10-13 16:54:00 -0700308 /**
309 * Process the multiple topology events with some delay (100MS at most for now)
310 *
311 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700312 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700313 numOfEventProcess ++;
314
Sangho Shin51625342014-10-17 09:30:48 -0700315 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
316 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
317 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
318 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
319 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
320 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
321 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700322
Sangho Shin5be3e532014-10-03 17:20:58 -0700323 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700324 // We should handle the events in the order of when they happen
325 // TODO: We need to simulate the final results of multiple events
326 // and shoot only the final state.
327 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
328 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700329
Sangho Shin5be3e532014-10-03 17:20:58 -0700330 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700331
332 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
333 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
334 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
335 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
336 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
337 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
338 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
339
340 linkEntriesAddedAll.addAll(linkEntriesAdded);
341 portEntriesAddedAll.addAll(portEntriesAdded);
342 portEntriesRemovedAll.addAll(portEntriesRemoved);
343 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
344 switchAddedAll.addAll(switchAdded);
345 switchRemovedAll.addAll(switchRemoved);
346 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700347 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700348
349 if (!portEntriesRemoved.isEmpty()) {
350 processPortRemoval(portEntriesRemoved);
351 }
352
353 if (!linkEntriesRemoved.isEmpty()) {
354 processLinkRemoval(linkEntriesRemoved);
355 }
356
357 if (!switchRemoved.isEmpty()) {
358 processSwitchRemoved(switchRemoved);
359 }
360
361 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700362 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700363 }
364
365 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700366 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700367 }
368
369 if (!portEntriesAdded.isEmpty()) {
370 processPortAdd(portEntriesAdded);
371 }
372
373 if (!switchAdded.isEmpty()) {
374 processSwitchAdd(switchAdded);
375 }
Sangho Shin51625342014-10-17 09:30:48 -0700376
Sangho Shinbce900e2014-10-07 17:13:23 -0700377 }
378
Sangho Shin23f898d2014-10-13 16:54:00 -0700379 // TODO: 100ms is enough to check both mastership removed events
380 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700381 if (!mastershipRemovedAll.isEmpty()) {
382 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700383 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700384 }
385 else {
386 HashMap<String, MastershipData> mastershipToRemove =
387 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700388 for (MastershipData ms: mastershipRemovedAll) {
389 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700390 // TODO: check ALL ports of the switch are dead ..
391 if (port.getDpid().equals(ms.getDpid())) {
392 mastershipToRemove.put(ms.getDpid().toString(), ms);
393 }
394 }
395 log.debug("Swtich {} is really down.", ms.getDpid());
396 }
397 processMastershipRemoved(mastershipToRemove.values());
398 }
399 }
400
Sangho Shinbce900e2014-10-07 17:13:23 -0700401 log.debug("num events {}, num of process {}, "
402 + "num of Population {}", numOfEvents, numOfEventProcess,
403 numOfPopulation);
404 }
405
406 /**
Sangho Shin23f898d2014-10-13 16:54:00 -0700407 * Add the link immediately
408 * The function is scheduled when link add event happens and called
409 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
410 */
411 private void delayedAddLink() {
412
413 processLinkAdd(linksToAdd.values(), true);
414
415 }
416
417 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700418 * Process the SwitchAdded events from topologyMananger.
419 * It does nothing. When a switch is added, then link will be added too.
420 * LinkAdded event will handle process all re-computation.
421 *
422 * @param switchAdded
423 */
424 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
425
426 }
427
428 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700429 * Remove all ports connected to the switch removed
430 *
431 * @param mastershipRemoved master switch info removed
432 */
433 private void processMastershipRemoved(Collection<MastershipData>
434 mastershipRemoved) {
435 for (MastershipData mastership: mastershipRemoved) {
436 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
437 for (Link link: sw.getOutgoingLinks()) {
438 Port dstPort = link.getDstPort();
439 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
440 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700441 if (dstSw != null) {
442 dstSw.removePortFromGroups(dstPort.getNumber());
443 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
444 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700445 }
Sangho Shin61535402014-10-01 11:37:14 -0700446 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700447
448 linksToAdd.clear();
449 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700450 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700451
Sangho Shinbce900e2014-10-07 17:13:23 -0700452 /**
453 * Remove all ports connected to the switch removed
454 *
455 * @param switchRemoved Switch removed
456 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700457 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700458 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700459 }
460
Sangho Shin61535402014-10-01 11:37:14 -0700461 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700462 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700463 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700464 * @param portEntries
465 */
466 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700467 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700468 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700469 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700470
Sangho Shinfbc572c2014-10-02 16:37:05 -0700471 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700472 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700473 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700474 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700475 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700476 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700477 }
478 }
479
480 /**
481 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700482 * If the link to add was removed before, then we just schedule the add link
483 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700484 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700485 * @param linkEntries
486 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700487 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700488
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700489 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700490
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700491 SwitchPort srcPort = link.getSrc();
492 SwitchPort dstPort = link.getDst();
493
Sangho Shin23f898d2014-10-13 16:54:00 -0700494 String key = srcPort.getDpid().toString() +
495 dstPort.getDpid().toString();
496 if (!delayed) {
497 if (linksDown.containsKey(key)) {
498 linksToAdd.put(key, link);
499 linksDown.remove(key);
500 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
501 log.debug("Add link {} with 5 sec delay", link);
502 // TODO: What if we have multiple events of add link:
503 // one is new link add, the other one is link up for
504 // broken link? ECMPSPG function cannot deal with it for now
505 return;
506 }
507 }
508 else {
509 if (linksDown.containsKey(key)) {
510 linksToAdd.remove(key);
511 log.debug("Do not add the link {}: it is down again!", link);
512 return;
513 }
514 }
515
Sangho Shinfbc572c2014-10-02 16:37:05 -0700516 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700517 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700518 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700519 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700520
Sangho Shin815af0c2014-10-10 13:05:45 -0700521 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700522 continue;
523
524 srcSw.addPortToGroups(srcPort.getPortNumber());
525 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700526
Sangho Shin15273b62014-10-16 22:22:05 -0700527 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
528 // link);
529 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
530 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700531
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700532 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700533 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700534 }
535
536 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700537 * Check if all links are gone b/w the two switches. If all links are gone,
538 * then we need to recalculate the path. Otherwise, just report link failure
539 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700540 *
Sangho Shin61535402014-10-01 11:37:14 -0700541 * @param linkEntries
542 */
543 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700544 boolean recomputationRequired = false;
545
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700546 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700547 SwitchPort srcPort = link.getSrc();
548 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700549
Sangho Shinfbc572c2014-10-02 16:37:05 -0700550 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700551 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700552 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700553 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700554 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700555 /* If this link is not between two switches, ignore it */
556 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700557
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700558 srcSw.removePortFromGroups(srcPort.getPortNumber());
559 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700560 log.debug("Remove port {} from switch {}", srcPort, srcSw);
561 log.debug("Remove port {} from switch {}", dstPort, dstSw);
562
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700563 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
564 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700565 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700566 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700567 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700568 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700569 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700570 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700571
572 String key = link.getSrc().getDpid().toString()+
573 link.getDst().getDpid().toString();
574 if (!linksDown.containsKey(key)) {
575 linksDown.put(key, link);
576 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700577 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700578
579 if (recomputationRequired)
580 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700581 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700582
Sangho Shin61535402014-10-01 11:37:14 -0700583 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700584 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700585 *
Sangho Shin61535402014-10-01 11:37:14 -0700586 * @param portEntries
587 */
588 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700589 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700590 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700591
Sangho Shinfbc572c2014-10-02 16:37:05 -0700592 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700593 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700594 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700595 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700596 log.debug("Remove port {} from switch {}", port, dpid);
597 }
Sangho Shin61535402014-10-01 11:37:14 -0700598 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700599 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700600
601 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700602 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700603 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700604 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700605 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700606 private void populateEcmpRoutingRules(boolean modified) {
607 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700608 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700609 for (Switch sw : switches) {
610 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700611 graphs.put(sw, ecmpSPG);
612 //log.debug("ECMPShortestPathGraph is computed for switch {}",
613 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700614 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700615 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700616 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700617 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700618
Sangho Shin99918bd2014-10-08 15:52:35 -0700619 /**
620 * populate routing rules to forward packets from the switch given to
621 * all other switches.
622 *
623 * @param sw source switch
624 * @param ecmpSPG shortest path from the the source switch to all others
625 * @param modified modification flag
626 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700627 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700628 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700629
Sangho Shinfbc572c2014-10-02 16:37:05 -0700630 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
631 ecmpSPG.getAllLearnedSwitchesAndVia();
632 for (Integer itrIdx : switchVia.keySet()) {
633 //log.debug("ECMPShortestPathGraph:Switches learned in "
634 // + "Iteration{} from switch {}:",
635 // itrIdx,
636 // HexString.toHexString(sw.getDpid().value()));
637 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
638 switchVia.get(itrIdx);
639 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700640 //log.debug("ECMPShortestPathGraph:****switch {} via:",
641 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700642 String destSw = sw.getDpid().toString();
643 List<String> fwdToSw = new ArrayList<String>();
644
Sangho Shinfbc572c2014-10-02 16:37:05 -0700645 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700646 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700647 if (via.isEmpty()) {
648 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700649 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700650 else {
651 fwdToSw.add(via.get(0).toString());
652 }
Sangho Shin43cee112014-09-25 16:43:34 -0700653 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700654 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700655 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700656
657 // Send Barrier Message and make sure all rules are set
658 // before we set the rules to next routers
Saurav Dasa962a692014-10-17 14:52:38 -0700659 // TODO: barriers to all switches in this update stage
Sangho Shinfbc572c2014-10-02 16:37:05 -0700660 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
661 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700662 if (sw13 != null) {
Saurav Dasa962a692014-10-17 14:52:38 -0700663 OFBarrierReplyFuture replyFuture = null;
Sangho Shin5be3e532014-10-03 17:20:58 -0700664 try {
Saurav Dasa962a692014-10-17 14:52:38 -0700665 replyFuture = sw13.sendBarrier();
Sangho Shin5be3e532014-10-03 17:20:58 -0700666 } catch (IOException e) {
Saurav Dasa962a692014-10-17 14:52:38 -0700667 log.error("Error sending barrier request to switch {}",
668 sw13.getId(), e.getCause());
Sangho Shin5be3e532014-10-03 17:20:58 -0700669 }
Saurav Dasa962a692014-10-17 14:52:38 -0700670 OFBarrierReply br = null;
671 try {
672 br = replyFuture.get(2, TimeUnit.SECONDS);
673 } catch (TimeoutException | InterruptedException | ExecutionException e) {
674 // XXX for some reason these exceptions are not being thrown
675 }
676 if (br == null) {
677 log.warn("Did not receive barrier-reply from {}", sw13.getId());
678 // XXX take corrective action
679 }
680
Sangho Shinfbc572c2014-10-02 16:37:05 -0700681 }
682 }
683
684 }
685
Sangho Shin99918bd2014-10-08 15:52:35 -0700686 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700687 * This class is used only for link recovery optimization in
688 * modifyEcmpRoutingRules() function.
Sangho Shin99918bd2014-10-08 15:52:35 -0700689 * TODO: please remove if the optimization is not used at all
Sangho Shinbce900e2014-10-07 17:13:23 -0700690 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700691 private class SwitchPair {
692 private Switch src;
693 private Switch dst;
694
695 public SwitchPair(Switch src, Switch dst) {
696 this.src = src;
697 this.dst = dst;
698 }
699
700 public Switch getSource() {
701 return src;
702 }
703
704 public Switch getDestination() {
705 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700706 }
Sangho Shin43cee112014-09-25 16:43:34 -0700707 }
708
709 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700710 * Modify the routing rules for the lost links
711 * - Recompute the path if the link failed is included in the path
712 * (including src and dest).
713 *
714 * @param newLink
715 */
716 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
717
718 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700719 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700720
721 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
722 Switch rootSw = ecmpSPG.getRootSwitch();
723 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
724 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
725 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
726 for (Switch destSw: p.keySet()) {
727 ArrayList<Path> path = p.get(destSw);
728 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700729 boolean found = false;
730 for (SwitchPair pair: linksToRecompute) {
731 if (pair.getSource().getDpid() == rootSw.getDpid() &&
732 pair.getSource().getDpid() == destSw.getDpid()) {
733 found = true;
734 }
735 }
736 if (!found) {
737 linksToRecompute.add(new SwitchPair(rootSw, destSw));
738 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700739 }
740 }
741 }
742 }
743
744 // Recompute the path for the specific route
745 for (SwitchPair pair: linksToRecompute) {
746
747 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
Sangho Shin99918bd2014-10-08 15:52:35 -0700748 // We need the following function for optimization
Sangho Shinfbc572c2014-10-02 16:37:05 -0700749 //ECMPShortestPathGraph ecmpSPG =
750 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
751 ECMPShortestPathGraph ecmpSPG =
752 new ECMPShortestPathGraph(pair.getSource());
Sangho Shin5be3e532014-10-03 17:20:58 -0700753 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700754 }
755 }
756
757 /**
758 * Check if the path is affected from the link removed
759 *
760 * @param path Path to check
761 * @param linkRemoved link removed
762 * @return true if the path contains the link removed
763 */
764 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
765
766 for (Path ppp: path) {
767 // TODO: need to check if this is a bidirectional or
768 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700769 for (LinkData link: ppp) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700770 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
771 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
772 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700773 }
774 }
775
776 return false;
777 }
778
779 /**
780 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700781 * Set routing rules in targetSw {forward packets to fwdToSw switches in
782 * order to send packets to destSw} - If the target switch is an edge router
783 * and final destnation switch is also an edge router, then set IP
784 * forwarding rules to subnets - If only the target switch is an edge
785 * router, then set IP forwarding rule to the transit router loopback IP
786 * address - If the target is a transit router, then just set the MPLS
787 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700788 *
Sangho Shin43cee112014-09-25 16:43:34 -0700789 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700790 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700791 * @param fwdToSw next hop switches
792 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700793 private void setRoutingRule(Switch targetSw, String destSw,
794 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700795
Sangho Shin43cee112014-09-25 16:43:34 -0700796 if (fwdToSw.isEmpty()) {
797 fwdToSw.add(destSw);
798 }
799
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700800 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700801 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
802 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700803 // We assume that there is at least one transit router b/w edge
804 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700805 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
806 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700807 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700808 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700809
Sangho Shin43cee112014-09-25 16:43:34 -0700810 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700811 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
812 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700813 // Edge router can be a transit router
814 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700815 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700816 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700817 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700818 // We assume that there is at least one transit router b/w edge
819 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700820 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
821 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700822 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
823 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700824 // Edge router can be a transit router
825 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700826 }
827 // if it is a transit router, then set rules in the MPLS table
828 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700829 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700830 }
831
832 }
833
Sangho Shinfbc572c2014-10-02 16:37:05 -0700834 /**
835 * Set IP forwarding rule to the gateway of each subnet of switches
836 *
837 * @param targetSw Switch to set rules
838 * @param subnets subnet information
839 * @param mplsLabel destination MPLS label
840 * @param fwdToSw router to forward packets to
841 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700842 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700843 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700844
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700845 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700846 new ArrayList<MatchActionOperationEntry>();
847
848 try {
849 JSONArray arry = new JSONArray(subnets);
850 for (int i = 0; i < arry.length(); i++) {
851 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700852 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
853 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700854 }
855 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700856 e.printStackTrace();
857 }
858
859 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700860 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700861 getSwId(targetSw.getDpid().toString()));
862
Sangho Shin721ca042014-10-09 13:03:40 -0700863 if (sw13 != null) {
864 try {
865 sw13.pushFlows(entries);
866 } catch (IOException e) {
867 e.printStackTrace();
868 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700869 }
870 }
871
872 }
873
Sangho Shin43cee112014-09-25 16:43:34 -0700874 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700875 * Check if the switch is the edge router or not.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700876 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700877 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700878 * @return true if it is an edge router, otherwise false
879 */
880 private boolean IsEdgeRouter(String dpid) {
881
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700882 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700883 String dpidStr = sw.getDpid().toString();
884 if (dpid.equals(dpidStr)) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700885 /*
Sangho Shin43cee112014-09-25 16:43:34 -0700886 String subnetInfo = sw.getStringAttribute("subnets");
887 if (subnetInfo == null || subnetInfo.equals("[]")) {
888 return false;
889 }
890 else
891 return true;
Sangho Shinbce900e2014-10-07 17:13:23 -0700892 */
893 String isEdge = sw.getStringAttribute("isEdgeRouter");
894 if (isEdge != null) {
895 if (isEdge.equals("true"))
896 return true;
897 else
898 return false;
899 }
Sangho Shin43cee112014-09-25 16:43:34 -0700900 }
901 }
902
903 return false;
904 }
905
906 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700907 * Set IP forwarding rule - If the destination is the next hop, then do not
908 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
909 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700910 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700911 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700912 * @param subnetIp Match IP address
913 * @param mplsLabel MPLS label of final destination router
914 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700915 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700916 */
917 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700918 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
919 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700920
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700921 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700922 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700923 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700924
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700925 // If destination SW is the same as the fwd SW, then do not push MPLS
926 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700927 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700928 PushMplsAction pushMplsAction = new PushMplsAction();
929 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
930 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700931 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700932
Sangho Shin62ce5c12014-10-08 16:24:40 -0700933 //actions.add(pushMplsAction);
934 //actions.add(copyTtlOutAction);
935 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700936 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700937 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700938 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700939 else {
940 String fwdToSw = fwdToSws.get(0);
941 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
942 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
943 actions.add(decTtlAction);
944 }
945 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700946 SetMplsIdAction setIdAction = new SetMplsIdAction(
947 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700948 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700949 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700950
Sangho Shin62ce5c12014-10-08 16:24:40 -0700951 //actions.add(pushMplsAction);
952 //actions.add(copyTtlOutAction);
953 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700954 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700955 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700956 }
957 }
Sangho Shin43cee112014-09-25 16:43:34 -0700958
Sangho Shin43cee112014-09-25 16:43:34 -0700959 for (String fwdSw : fwdToSws) {
960 groupAction.addSwitch(new Dpid(fwdSw));
961 }
962 actions.add(groupAction);
963
Sangho Shin99918bd2014-10-08 15:52:35 -0700964 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700965 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700966
Sangho Shin5be3e532014-10-03 17:20:58 -0700967 Operator operator = null;
968 if (modified)
969 operator = Operator.MODIFY;
970 else
971 operator = Operator.ADD;
972
Sangho Shin43cee112014-09-25 16:43:34 -0700973 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700974 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700975
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700976 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700977 getSwId(sw.getDpid().toString()));
978
Sangho Shin5be3e532014-10-03 17:20:58 -0700979 if (sw13 != null) {
980 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700981 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700982 if (entries != null)
983 entries.add(maEntry);
984 else
985 sw13.pushFlow(maEntry);
986 } catch (IOException e) {
987 e.printStackTrace();
988 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700989 }
990
Sangho Shin43cee112014-09-25 16:43:34 -0700991 }
992
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700993 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700994 * Set MPLS forwarding rules to MPLS table
995 * </p>
996 * If the destination is the same as the next hop to forward packets then,
997 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
998 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
999 * TTL of the another MPLS header.
1000 * If the next hop is not the destination, just forward packets to next
1001 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001002 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001003 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -07001004 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001005 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001006 * */
Sangho Shin5be3e532014-10-03 17:20:58 -07001007 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
1008 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -07001009
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001010 if (fwdSws.isEmpty())
1011 return;
Sangho Shin43cee112014-09-25 16:43:34 -07001012
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001013 Collection<MatchActionOperationEntry> maEntries =
1014 new ArrayList<MatchActionOperationEntry>();
1015 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -07001016
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001017 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
1018 // One rule for Bos = 1
1019 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
1020 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001021
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001022 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
1023 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
1024 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
1025
1026 actions.add(copyTtlInAction);
1027 actions.add(popAction);
1028 actions.add(decNwTtlAction);
1029
1030 GroupAction groupAction = new GroupAction();
1031 groupAction.addSwitch(new Dpid(fwdSw1));
1032 actions.add(groupAction);
1033
1034 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
1035 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1036 Operator operator = Operator.ADD;
1037 MatchActionOperationEntry maEntry =
1038 new MatchActionOperationEntry(operator, matchAction);
1039 maEntries.add(maEntry);
1040
1041 // One rule for Bos = 0
Sangho Shin23f898d2014-10-13 16:54:00 -07001042 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001043 List<Action> actionsBos = new ArrayList<Action>();
Sangho Shin15273b62014-10-16 22:22:05 -07001044 PopMplsAction popActionBos = new PopMplsAction(EthType.MPLS_UNICAST);
1045 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1046
1047 actionsBos.add(copyTtlInAction);
1048 actionsBos.add(popActionBos);
1049 actionsBos.add(decMplsTtlAction);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001050 actionsBos.add(groupAction);
1051
1052 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
1053 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
1054 MatchActionOperationEntry maEntryBos =
1055 new MatchActionOperationEntry(operator, matchActionBos);
1056 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001057 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001058 else {
1059 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
1060 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -07001061
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001062 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1063 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -07001064
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001065 GroupAction groupAction = new GroupAction();
1066 for (String fwdSw : fwdSws)
1067 groupAction.addSwitch(new Dpid(fwdSw));
1068 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -07001069
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001070 MatchAction matchAction = new MatchAction(new MatchActionId(
1071 matchActionId++),
1072 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1073 Operator operator = Operator.ADD;
1074 MatchActionOperationEntry maEntry =
1075 new MatchActionOperationEntry(operator, matchAction);
1076 maEntries.add(maEntry);
Sangho Shine2e9bcd2014-10-13 15:14:18 -07001077
1078 // BoS = 1
1079 MplsMatch mplsMatchBoS = new MplsMatch(Integer.parseInt(mplsLabel), true);
1080 List<Action> actionsBoS = new ArrayList<Action>();
1081
1082 DecMplsTtlAction decMplsTtlActionBoS = new DecMplsTtlAction(1);
1083 actionsBoS.add(decMplsTtlActionBoS);
1084
1085 GroupAction groupActionBoS = new GroupAction();
1086 for (String fwdSw : fwdSws)
1087 groupActionBoS.addSwitch(new Dpid(fwdSw));
1088 actionsBoS.add(groupActionBoS);
1089
1090 MatchAction matchActionBos = new MatchAction(new MatchActionId(
1091 matchActionId++),
1092 new SwitchPort((long) 0, (short) 0), mplsMatchBoS, actionsBoS);
1093 MatchActionOperationEntry maEntryBoS =
1094 new MatchActionOperationEntry(operator, matchActionBos);
1095 maEntries.add(maEntryBoS);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001096 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001097 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001098 getSwId(sw.getDpid().toString()));
1099
Sangho Shin5be3e532014-10-03 17:20:58 -07001100 if (sw13 != null) {
1101 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001102 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001103 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001104 } catch (IOException e) {
1105 e.printStackTrace();
1106 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001107 }
Sangho Shin43cee112014-09-25 16:43:34 -07001108 }
1109
Sangho Shin15273b62014-10-16 22:22:05 -07001110 /**
1111 * Create a tunnel for policy routing
1112 * It delivers the node IDs of tunnels to driver.
1113 * Split the node IDs if number of IDs exceeds the limit for stitching.
1114 *
1115 * @param tunnelId Node IDs for the tunnel
1116 * @param Ids tunnel ID
1117 */
1118 public boolean createTunnel(int tunnelId, List<String> Ids) {
1119
1120 if (tunnelId < 0) {
1121 log.debug("Tunnel ID should be posivtive integer.");
1122 return false;
1123 }
1124
1125 if (Ids.isEmpty() || Ids.size() < 2) {
1126 log.debug("Wrong tunnel information");
1127 return false;
1128 }
1129
1130 HashMap<String, PolicyRouteInfo> stitchingRule = getStitchingRule(Ids);
1131 stitchInfo.put(Integer.valueOf(tunnelId), stitchingRule);
1132 if (stitchingRule == null) {
1133 log.debug("Failed to get the policy rule.");
1134 return false;
1135 }
1136 HashMap<String, Integer> switchGroupPair = new HashMap<String, Integer>();
1137 for (String targetDpid: stitchingRule.keySet()) {
1138 PolicyRouteInfo route = stitchingRule.get(targetDpid);
1139
1140 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
1141 getSwId(targetDpid.toString()));
1142
1143 if (targetSw == null) {
1144 log.debug("Switch {} is gone.", targetDpid);
1145 return false;
1146 }
1147
1148 NeighborSet ns = new NeighborSet();
1149 for (Dpid dpid: route.getFwdSwDpid())
1150 ns.addDpid(dpid);
1151
1152 printTunnelInfo(targetSw, tunnelId, route.getRoute(), ns);
1153 int groupId = targetSw.createTunnel(tunnelId, route.getRoute(), ns);
1154 switchGroupPair.put(targetDpid.toString(), groupId);
1155
1156 }
1157
1158 tunnelGroupMap.put(Integer.valueOf(tunnelId), switchGroupPair);
1159
1160 return true;
1161 }
1162
Sangho Shinbb2b8362014-10-17 21:07:16 -07001163 public void removeTunnel(int tunnelId) {
1164
1165 }
1166
Sangho Shin6f47dd32014-10-17 23:10:39 -07001167
1168 class PolicyInfo {
1169
1170 int policyId;
1171 PacketMatch match;
1172 int priority;
1173 int tunnelId;
1174
1175 PolicyInfo(int pid, PacketMatch match, int priority, int tid) {
1176 this.policyId = pid;
1177 this.match = match;
1178 this.priority = priority;
1179 this.tunnelId = tid;
1180 }
1181 }
1182
Sangho Shin15273b62014-10-16 22:22:05 -07001183 /**
1184 * Set policy table for policy routing
1185 *
1186 * @param sw
1187 * @param mplsLabel
1188 */
Sangho Shinbb2b8362014-10-17 21:07:16 -07001189 public void setPolicyTable(int pid, MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001190 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
Sangho Shin6f47dd32014-10-17 23:10:39 -07001191 Short srcTcpPort, Short dstTcpPort, int priority, int tid) {
Sangho Shin15273b62014-10-16 22:22:05 -07001192
1193 HashMap<String, PolicyRouteInfo> routeInfo = stitchInfo.get(Integer.valueOf(tid));
1194 HashMap<String, Integer> switchGroupPair = tunnelGroupMap.get(Integer.valueOf(tid));
Sangho Shinbb2b8362014-10-17 21:07:16 -07001195
1196 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1197
1198 if (srcMac != null)
1199 packetBuilder.setSrcMac(srcMac);
1200 if (dstMac != null)
1201 packetBuilder.setDstMac(dstMac);
1202 if (etherType != null)
1203 packetBuilder.setEtherType(etherType);
1204 if (srcIp != null)
1205 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1206 if (dstIp != null)
1207 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1208 if (ipProto != null)
1209 packetBuilder.setIpProto(ipProto);
1210 if (srcTcpPort > 0)
1211 packetBuilder.setSrcTcpPort(srcTcpPort);
1212 if (dstTcpPort > 0)
1213 packetBuilder.setDstTcpPort(dstTcpPort);
1214 PacketMatch packetMatch = packetBuilder.build();
1215
Sangho Shin15273b62014-10-16 22:22:05 -07001216 for (String srcDpid: routeInfo.keySet()) {
Sangho Shin15273b62014-10-16 22:22:05 -07001217 List<Action> actions = new ArrayList<>();
1218 GroupAction groupAction = new GroupAction();
1219 int gropuId = switchGroupPair.get(srcDpid);
1220 groupAction.setGroupId(gropuId);
1221 actions.add(groupAction);
1222
1223 MatchAction matchAction = new MatchAction(new MatchActionId(
1224 matchActionId++),
Sangho Shin6f47dd32014-10-17 23:10:39 -07001225 new SwitchPort((long) 0, (short) 0), packetMatch, priority,
1226 actions);
Sangho Shin15273b62014-10-16 22:22:05 -07001227 MatchActionOperationEntry maEntry =
1228 new MatchActionOperationEntry(Operator.ADD, matchAction);
1229
1230 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1231 getSwId(srcDpid));
1232
1233 if (sw13 != null) {
1234 printMatchActionOperationEntry(sw13, maEntry);
1235 try {
1236 sw13.pushFlow(maEntry);
1237 } catch (IOException e) {
1238 e.printStackTrace();
Sangho Shinbb2b8362014-10-17 21:07:16 -07001239 log.debug("Policy was not set due to pushFlow() error");
Sangho Shin15273b62014-10-16 22:22:05 -07001240 }
1241 }
1242 }
Sangho Shin6f47dd32014-10-17 23:10:39 -07001243
1244 PolicyInfo policyInfo = new PolicyInfo(pid, packetMatch, priority, tid);
1245 policyTable.put(Integer.valueOf(pid), policyInfo);
Sangho Shinbb2b8362014-10-17 21:07:16 -07001246 }
1247
1248 /**
1249 * Remove all policies applied to specific tunnel.
1250 *
1251 * @param srcMac
1252 * @param dstMac
1253 * @param etherType
1254 * @param srcIp
1255 * @param dstIp
1256 * @param ipProto
1257 * @param srcTcpPort
1258 * @param dstTcpPort
1259 * @param tid
1260 */
1261 public void removePolicy(int pid) {
1262
Sangho Shin6f47dd32014-10-17 23:10:39 -07001263 PolicyInfo policyInfo = policyTable.get(Integer.valueOf(pid));
1264 PacketMatch policyMatch = policyInfo.match;
1265 int tid = policyInfo.tunnelId;
1266 int priority = policyInfo.priority;
Sangho Shinbb2b8362014-10-17 21:07:16 -07001267
1268 List<Action> actions = new ArrayList<>();
1269 int gropuId = 0; // dummy group ID
1270 GroupAction groupAction = new GroupAction();
1271 groupAction.setGroupId(gropuId);
1272 actions.add(groupAction);
1273
1274 MatchAction matchAction = new MatchAction(new MatchActionId(
1275 matchActionId++),
Sangho Shin6f47dd32014-10-17 23:10:39 -07001276 new SwitchPort((long) 0, (short) 0), policyMatch, priority,
1277 actions);
Sangho Shinbb2b8362014-10-17 21:07:16 -07001278 MatchActionOperationEntry maEntry =
1279 new MatchActionOperationEntry(Operator.REMOVE, matchAction);
1280
1281 HashMap<String, Integer> groupInfo = tunnelGroupMap.get(
1282 Integer.valueOf(tid));
1283
1284 for (String dpid: groupInfo.keySet()) {
1285 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1286 getSwId(dpid));
1287
1288 if (sw13 != null) {
1289 printMatchActionOperationEntry(sw13, maEntry);
1290 try {
1291 sw13.pushFlow(maEntry);
1292 } catch (IOException e) {
1293 e.printStackTrace();
1294 log.debug("policy remove failed due to pushFlow() exception");
1295 return;
1296 }
1297 }
1298 }
1299
1300 log.debug("Policy {} is removed.", pid);
Sangho Shin15273b62014-10-16 22:22:05 -07001301 }
1302
1303 /**
1304 * Get the forwarding Switch DPIDs to send packets to a node
1305 *
1306 * @param srcSw source switch
1307 * @param nodeId destination node Id
1308 * @return list of switch DPID to forward packets to
1309 */
1310
1311 private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
1312
1313 List<Dpid> fwdSws = new ArrayList<Dpid>();
1314 Switch destSw = null;
1315
1316 destSw = getSwitchFromNodeId(nodeId);
1317
1318 if (destSw == null) {
1319 log.debug("Cannot find the switch with ID {}", nodeId);
1320 return null;
1321 }
1322
1323 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1324
1325 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1326 ecmpSPG.getAllLearnedSwitchesAndVia();
1327 for (Integer itrIdx : switchVia.keySet()) {
1328 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1329 switchVia.get(itrIdx);
1330 for (Switch targetSw : swViaMap.keySet()) {
1331 String destSwDpid = destSw.getDpid().toString();
1332 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1333 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1334 if (via.isEmpty()) {
1335 fwdSws.add(destSw.getDpid());
1336 }
1337 else {
1338 fwdSws.add(via.get(0));
1339 }
1340 }
1341 }
1342 }
1343 }
1344
1345 return fwdSws;
1346 }
1347
1348 /**
1349 * Get switch for the node Id specified
1350 *
1351 * @param nodeId node ID for switch
1352 * @return Switch
1353 */
1354 private Switch getSwitchFromNodeId(String nodeId) {
1355
1356 for (Switch sw : mutableTopology.getSwitches()) {
1357 String id = sw.getStringAttribute("nodeSid");
1358 if (id.equals(nodeId)) {
1359 return sw;
1360 }
1361 }
1362
1363 return null;
1364 }
1365
1366 /**
1367 * Convert a string DPID to its Switch Id (integer)
1368 *
1369 * @param dpid
1370 * @return
1371 */
1372 private long getSwId(String dpid) {
1373
1374 long swId = 0;
1375
1376 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1377 if (swIdHexStr != null)
1378 swId = Integer.decode(swIdHexStr);
1379
1380 return swId;
1381 }
1382
1383 private void runTest() {
1384
Sangho Shin6f47dd32014-10-17 23:10:39 -07001385 if (testMode == POLICY_ADD1) {
1386 String[] routeArray = {"101", "105", "110"};
Sangho Shinbb2b8362014-10-17 21:07:16 -07001387 List<String> routeList = new ArrayList<String>();
1388 for (int i = 0; i < routeArray.length; i++)
1389 routeList.add(routeArray[i]);
Sangho Shin15273b62014-10-16 22:22:05 -07001390
Sangho Shinbb2b8362014-10-17 21:07:16 -07001391 if (createTunnel(1, routeList)) {
1392 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1393 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
Sangho Shin15273b62014-10-16 22:22:05 -07001394
Sangho Shin6f47dd32014-10-17 23:10:39 -07001395 log.debug("Set the policy 1");
Sangho Shinbb2b8362014-10-17 21:07:16 -07001396 this.setPolicyTable(1, null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin6f47dd32014-10-17 23:10:39 -07001397 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
1398 1);
1399 testMode = POLICY_ADD2;
Sangho Shinbb2b8362014-10-17 21:07:16 -07001400 testTask.reschedule(10, TimeUnit.SECONDS);
1401 }
1402 else {
Sangho Shin6f47dd32014-10-17 23:10:39 -07001403 // retry it
Sangho Shinbb2b8362014-10-17 21:07:16 -07001404 testTask.reschedule(5, TimeUnit.SECONDS);
1405 }
Sangho Shin15273b62014-10-16 22:22:05 -07001406 }
Sangho Shin6f47dd32014-10-17 23:10:39 -07001407 else if (testMode == POLICY_ADD2) {
1408 String[] routeArray = {"101", "102", "103", "104", "105", "108",
1409 "110"};
1410 List<String> routeList = new ArrayList<String>();
1411 for (int i = 0; i < routeArray.length; i++)
1412 routeList.add(routeArray[i]);
1413
1414 if (createTunnel(2, routeList)) {
1415 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1416 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1417
1418 log.debug("Set the policy 2");
1419 this.setPolicyTable(2, null, null, Ethernet.TYPE_IPV4, srcIp,
1420 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 20000,
1421 2);
1422 testMode = POLICY_REMOVE1;
1423 testTask.reschedule(10, TimeUnit.SECONDS);
1424 }
1425 else {
1426 log.debug("Retry it");
1427 testTask.reschedule(5, TimeUnit.SECONDS);
1428 }
1429 }
1430 else if (testMode == POLICY_REMOVE1){
1431 log.debug("Remove the policy 1");
1432 this.removePolicy(2);
1433 testMode = POLICY_REMOVE2;
1434 testTask.reschedule(10, TimeUnit.SECONDS);
1435 }
1436 else if (testMode == POLICY_REMOVE2) {
1437 log.debug("Remove the policy 2");
Sangho Shinbb2b8362014-10-17 21:07:16 -07001438 this.removePolicy(1);
Sangho Shin15273b62014-10-16 22:22:05 -07001439 }
1440 }
1441
1442 private void runTest1() {
1443
1444 String dpid1 = "00:00:00:00:00:00:00:01";
1445 String dpid2 = "00:00:00:00:00:00:00:0a";
1446 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1447 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1448
1449 if (srcSw == null || dstSw == null) {
1450 testTask.reschedule(1, TimeUnit.SECONDS);
1451 log.debug("Switch is gone. Reschedule the test");
1452 return;
1453 }
1454
1455 String[] routeArray = {"101", "102", "105", "108", "110"};
1456 List<String> routeList = new ArrayList<String>();
1457 for (int i = 0; i < routeArray.length; i++)
1458 routeList.add(routeArray[i]);
1459
1460 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1461
1462 log.debug("Test set is {}", routeList.toString());
1463 log.debug("Result set is {}", optimizedRoute.toString());
1464
1465
1466 }
1467
1468 /**
1469 * Optimize the mpls label
1470 * The feature will be used only for policy of "avoid a specific switch".
1471 * Check route to each router in route backward.
1472 * If there is only one route to the router and the routers are included in
1473 * the route, remove the id from the path.
1474 * A-B-C-D-E => A-B-C-D-E -> A-E
1475 * | | => A-B-H-I -> A-I
1476 * F-G-H-I => A-D-I -> A-D-I
1477 */
1478 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
1479
1480 List<String> optimizedPath = new ArrayList<String>();
1481 optimizedPath.addAll(route);
1482 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1483
1484 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
1485 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
1486 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
1487 for (Switch s: p.keySet()) {
1488 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
1489 ArrayList<Path> ecmpPaths = p.get(s);
1490 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
1491 for (Path path: ecmpPaths) {
1492 for (LinkData link: path) {
1493 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
1494 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
1495 if (optimizedPath.contains(srcId)) {
1496 optimizedPath.remove(srcId);
1497 }
1498 if (optimizedPath.contains(dstId)) {
1499 optimizedPath.remove(dstId);
1500 }
1501 }
1502 }
1503 }
1504 }
1505 }
1506 }
1507
1508 return optimizedPath;
1509
1510 }
1511
Sangho Shinbb2b8362014-10-17 21:07:16 -07001512 /**
1513 * Strore policy routing info
1514 */
Sangho Shin15273b62014-10-16 22:22:05 -07001515 class PolicyRouteInfo {
1516
1517 String srcSwDpid;
1518 List<Dpid> fwdSwDpids;
1519 List<String> route;
1520
1521 PolicyRouteInfo() {
1522 fwdSwDpids = new ArrayList<Dpid>();
1523 route = new ArrayList<String>();
1524 }
1525
1526 void setSrcDpid(String dpid) {
1527 this.srcSwDpid = dpid;
1528 }
1529
1530 void setFwdSwDpid(List<Dpid> dpid) {
1531 this.fwdSwDpids = dpid;
1532 }
1533
1534 void addRoute(String id) {
1535 route.add(id);
1536 }
1537
1538 void setRoute(List<String> r) {
1539 this.route = r;
1540 }
1541
1542 String getSrcSwDpid() {
1543 return this.srcSwDpid;
1544 }
1545
1546 List<Dpid> getFwdSwDpid() {
1547 return this.fwdSwDpids;
1548 }
1549
1550 List<String> getRoute() {
1551 return this.route;
1552 }
1553 }
1554
Sangho Shin15273b62014-10-16 22:22:05 -07001555 /**
1556 *
1557 *
1558 * @param srcSw
1559 * @param dstSw
1560 * @param route
1561 * @return
1562 */
1563 private HashMap<String, PolicyRouteInfo> getStitchingRule(List<String> route) {
1564
1565 if (route.isEmpty() || route.size() < 2)
1566 return null;
1567
1568 HashMap<String, PolicyRouteInfo> rules = new HashMap<String, PolicyRouteInfo>();
1569
1570 Switch srcSw = this.getSwitchFromNodeId(route.get(0));
1571 String srcDpid = srcSw.getDpid().toString();
1572
1573 if (route.size() <= MAX_NUM_LABELS+1) {
1574 PolicyRouteInfo info = new PolicyRouteInfo();
1575 info.setSrcDpid(srcSw.getDpid().toString());
1576 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, route.get(1));
1577 info.setFwdSwDpid(fwdSwDpids);
1578 route.remove(0);
1579 info.setRoute(route);
1580 rules.put(srcDpid, info);
1581 return rules;
1582 }
1583
1584 int i = 0;
1585 PolicyRouteInfo routeInfo = new PolicyRouteInfo();
1586 String prevNodeId = null;
1587 boolean checkNeighbor = true;
1588
1589 for (String nodeId: route) {
1590 if (i == 0) {
1591 routeInfo.setSrcDpid(srcDpid);
1592 srcSw = getSwitchFromNodeId(nodeId);
1593 i++;
1594 }
1595 else if (i == 1) {
1596 if (checkNeighbor) {
1597 // Check if next node is the neighbor SW of the source SW
1598 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
1599 if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
1600 log.debug("There is no route from node {} to node {}", srcSw.getDpid(), nodeId);
1601 return null;
1602 }
1603 // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
1604 boolean match = false;
1605 for (Dpid dpid: fwdSwDpids) {
1606 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1607 List<Dpid> fwdSws = new ArrayList<Dpid>();
1608 fwdSws.add(dpid);
1609 routeInfo.setFwdSwDpid(fwdSws);
1610 match = true;
1611 break;
1612 }
1613 }
1614 if (!match) {
1615 routeInfo.addRoute(nodeId);
1616 routeInfo.setFwdSwDpid(fwdSwDpids);
1617 i++;
1618 }
1619
1620 checkNeighbor = false;
1621 }
1622 else {
1623 routeInfo.addRoute(nodeId);
1624 i++;
1625 }
1626 }
1627 else {
1628 routeInfo.addRoute(nodeId);
1629 i++;
1630 }
1631
1632 if (i == MAX_NUM_LABELS+1) {
1633 rules.put(srcDpid, routeInfo);
1634 routeInfo = new PolicyRouteInfo();
1635 srcSw = getSwitchFromNodeId(nodeId);
1636 srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
1637 routeInfo.setSrcDpid(srcDpid);
1638 i = 1;
1639 checkNeighbor = true;
1640 }
1641 }
1642
1643 if (i < MAX_NUM_LABELS+1) {
1644 rules.put(srcDpid, routeInfo);
1645 }
1646
1647 return rules;
1648 }
1649
1650 /**
1651 * print tunnel info - used only for debugging.
1652 * @param targetSw
1653 *
1654 * @param fwdSwDpids
1655 * @param ids
1656 * @param tunnelId
1657 */
1658 private void printTunnelInfo(IOF13Switch targetSw, int tunnelId,
1659 List<String> ids, NeighborSet ns) {
1660 StringBuilder logStr = new StringBuilder("In switch " +
1661 targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
1662 for (String id: ids)
1663 logStr.append(id + "-");
1664 logStr.append(" output to ");
1665 for (Dpid dpid: ns.getDpids())
1666 logStr.append(dpid + " - ");
1667
1668 log.debug(logStr.toString());
1669
1670 }
1671
Sangho Shin43cee112014-09-25 16:43:34 -07001672 /**
1673 * Debugging function to print out the Match Action Entry
Sangho Shin15273b62014-10-16 22:22:05 -07001674 * @param sw13
Sangho Shinfbc572c2014-10-02 16:37:05 -07001675 *
Sangho Shin43cee112014-09-25 16:43:34 -07001676 * @param maEntry
1677 */
Sangho Shin15273b62014-10-16 22:22:05 -07001678 private void printMatchActionOperationEntry(
1679 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -07001680
Sangho Shin15273b62014-10-16 22:22:05 -07001681 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001682
1683 MatchAction ma = maEntry.getTarget();
1684 Match m = ma.getMatch();
1685 List<Action> actions = ma.getActions();
1686
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001687 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -07001688 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001689 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -07001690 logStr.append(ip.toString());
1691 logStr.append(" then ");
1692 }
1693 else if (m instanceof MplsMatch) {
1694 logStr.append("If the MPLS label matches with ");
1695 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1696 logStr.append(mplsLabel);
1697 logStr.append(" then ");
1698 }
Sangho Shin15273b62014-10-16 22:22:05 -07001699 else if (m instanceof PacketMatch) {
1700 GroupAction ga = (GroupAction)actions.get(0);
1701 logStr.append("if the policy match is XXX then go to group " +
1702 ga.getGroupId());
1703 log.debug(logStr.toString());
1704 return;
1705 }
Sangho Shin43cee112014-09-25 16:43:34 -07001706
1707 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001708 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -07001709 if (action instanceof CopyTtlInAction) {
1710 logStr.append("copy ttl In, ");
1711 }
1712 else if (action instanceof CopyTtlOutAction) {
1713 logStr.append("copy ttl Out, ");
1714 }
1715 else if (action instanceof DecMplsTtlAction) {
1716 logStr.append("Dec MPLS TTL , ");
1717 }
1718 else if (action instanceof GroupAction) {
1719 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001720 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -07001721 logStr.append(dpids.toString() + ",");
1722
Sangho Shin43cee112014-09-25 16:43:34 -07001723 }
1724 else if (action instanceof PopMplsAction) {
1725 logStr.append("Pop MPLS label, ");
1726 }
1727 else if (action instanceof PushMplsAction) {
1728 logStr.append("Push MPLS label, ");
1729 }
1730 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001731 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -07001732 logStr.append("Set MPLS ID as " + id + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001733 }
1734 }
1735
1736 log.debug(logStr.toString());
1737
Sangho Shineb083032014-09-22 16:11:34 -07001738 }
1739
1740 /**
1741 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001742 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001743 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001744 * @return MPLS label for the switch
1745 */
1746
Sangho Shin43cee112014-09-25 16:43:34 -07001747 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001748
1749 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001750 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001751 String dpidStr = sw.getDpid().toString();
1752 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001753 mplsLabel = sw.getStringAttribute("nodeSid");
1754 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001755 }
1756 }
1757
Sangho Shineb083032014-09-22 16:11:34 -07001758 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001759 }
1760
Sangho Shineb083032014-09-22 16:11:34 -07001761 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001762 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001763 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001764 * @param addr - subnet address to match
1765 * @param addr1 - IP address to check
1766 * @return true if the IP address matches to the subnet, otherwise false
1767 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001768 public boolean netMatch(String addr, String addr1) { // addr is subnet
1769 // address and addr1 is
1770 // ip address. Function
1771 // will return true, if
1772 // addr1 is within
1773 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001774
1775 String[] parts = addr.split("/");
1776 String ip = parts[0];
1777 int prefix;
1778
1779 if (parts.length < 2) {
1780 prefix = 0;
1781 } else {
1782 prefix = Integer.parseInt(parts[1]);
1783 }
1784
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001785 Inet4Address a = null;
1786 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001787 try {
1788 a = (Inet4Address) InetAddress.getByName(ip);
1789 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001790 } catch (UnknownHostException e) {
1791 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001792
1793 byte[] b = a.getAddress();
1794 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001795 ((b[1] & 0xFF) << 16) |
1796 ((b[2] & 0xFF) << 8) |
1797 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001798
1799 byte[] b1 = a1.getAddress();
1800 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001801 ((b1[1] & 0xFF) << 16) |
1802 ((b1[2] & 0xFF) << 8) |
1803 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001804
1805 int mask = ~((1 << (32 - prefix)) - 1);
1806
1807 if ((ipInt & mask) == (ipInt1 & mask)) {
1808 return true;
1809 }
1810 else {
1811 return false;
1812 }
1813 }
Sangho Shineb083032014-09-22 16:11:34 -07001814
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001815 /**
1816 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001817 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001818 * @param sw - Switch to add the rule
1819 * @param hostIpAddress Destination host IP address
1820 * @param hostMacAddress Destination host MAC address
1821 */
Sangho Shineb083032014-09-22 16:11:34 -07001822 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1823 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1824
1825 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001826
Sangho Shin463bee52014-09-29 15:14:43 -07001827 /**
1828 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001829 *
Sangho Shin463bee52014-09-29 15:14:43 -07001830 * @param ipv4
1831 */
1832 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001833 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001834 }
1835
1836 /**
1837 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001838 *
Sangho Shin463bee52014-09-29 15:14:43 -07001839 * @param destIp Destination address of packets to retrieve
1840 */
1841 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1842
1843 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1844
Sangho Shin61535402014-10-01 11:37:14 -07001845 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001846 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001847 int dest = ip.getDestinationAddress();
1848 IPv4Address ip1 = IPv4Address.of(dest);
1849 IPv4Address ip2 = IPv4Address.of(destIp);
1850 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001851 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001852 }
1853 }
1854 }
1855
1856 return bufferedPackets;
1857 }
1858
Sangho Shin15273b62014-10-16 22:22:05 -07001859
1860
Sangho Shin2f263692014-09-15 14:09:41 -07001861}