blob: 668ceaa1d576392e6862f40cbeb358ca2d595521 [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;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070034import net.onrc.onos.apps.segmentrouting.web.SegmentRoutingWebRoutable;
Sangho Shin2f263692014-09-15 14:09:41 -070035import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070036import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070037import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070038import net.onrc.onos.core.matchaction.MatchAction;
39import net.onrc.onos.core.matchaction.MatchActionId;
40import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070041import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070042import net.onrc.onos.core.matchaction.action.Action;
43import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
44import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
45import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
46import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
47import net.onrc.onos.core.matchaction.action.GroupAction;
48import net.onrc.onos.core.matchaction.action.PopMplsAction;
49import net.onrc.onos.core.matchaction.action.PushMplsAction;
50import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070051import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070052import net.onrc.onos.core.matchaction.match.Match;
53import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070054import net.onrc.onos.core.matchaction.match.PacketMatch;
55import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070056import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070057import net.onrc.onos.core.packet.Ethernet;
58import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070059import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070060import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070061import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070062import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070063import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070064import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070065import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070066import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070067import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070068import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070069import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070070import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070071import net.onrc.onos.core.util.IPv4Net;
72import net.onrc.onos.core.util.SwitchPort;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070073import net.floodlightcontroller.restserver.IRestApiService;
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 Vavilapallif25c7b02014-10-01 14:30:43 -070084 ITopologyListener, IPacketListener {
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 Shin15273b62014-10-16 22:22:05 -0700108 private HashMap<Integer, HashMap<String, PolicyRouteInfo>> stitchInfo;
109 private HashMap<Integer, HashMap<String, Integer>> tunnelGroupMap;
Sangho Shinbce900e2014-10-07 17:13:23 -0700110
111 private int numOfEvents = 0;
112 private int numOfEventProcess = 0;
113 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700114 private long matchActionId = 0L;
Sangho Shin23f898d2014-10-13 16:54:00 -0700115 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700116 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700117
Sangho Shin2f263692014-09-15 14:09:41 -0700118 @Override
119 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
120 // TODO Auto-generated method stub
121 return null;
122 }
123
124 @Override
125 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
126 // TODO Auto-generated method stub
127 return null;
128 }
129
130 @Override
131 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
132 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
133
134 l.add(IFloodlightProviderService.class);
135 l.add(IConfigInfoService.class);
136 l.add(ITopologyService.class);
137 l.add(IPacketService.class);
138 l.add(IFlowPusherService.class);
139 l.add(ITopologyService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700140 l.add(IRestApiService.class);
Sangho Shin2f263692014-09-15 14:09:41 -0700141
142 return l;
143
144 }
145
146 @Override
147 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700148 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700149 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700150 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700151 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700152 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700153 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700154 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700155 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700156 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700157 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700158 linksDown = new HashMap<String, LinkData>();
159 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700160 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700161 stitchInfo = new HashMap<Integer, HashMap<String, PolicyRouteInfo>>();
162 packetService = context.getServiceImpl(IPacketService.class);
163 tunnelGroupMap = new HashMap<Integer, HashMap<String, Integer>>();
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700164 restApi = context.getServiceImpl(IRestApiService.class);
Sangho Shin2f263692014-09-15 14:09:41 -0700165
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700166 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700167 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700168
Sangho Shin99918bd2014-10-08 15:52:35 -0700169
Sangho Shin2f263692014-09-15 14:09:41 -0700170 }
171
172 @Override
173 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700174 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700175 restApi.addRestletRoutable(new SegmentRoutingWebRoutable());
Sangho Shin2f263692014-09-15 14:09:41 -0700176
Sangho Shinc8d2f592014-09-30 16:53:57 -0700177 discoveryTask = new SingletonTask(ses, new Runnable() {
178 @Override
179 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700180 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700181 }
182 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700183
184 linkAddTask = new SingletonTask(ses, new Runnable() {
185 @Override
186 public void run() {
187 delayedAddLink();
188 }
189 });
190
Sangho Shin15273b62014-10-16 22:22:05 -0700191 testTask = new SingletonTask(ses, new Runnable() {
192 @Override
193 public void run() {
194 runTest();
195 }
196 });
197
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700198 // policy routing test task
199 //testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700200 }
201
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700202
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700203 @Override
204 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700205 if (payload.getEtherType() == Ethernet.TYPE_ARP)
206 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700207 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700208 addPacket((IPv4) payload.getPayload());
209 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
210 icmpHandler.processPacketIn(sw, inPort, payload);
211 else
212 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700213 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700214 else {
215 log.debug("{}", payload.toString());
216 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700217 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700218
Sangho Shin2f263692014-09-15 14:09:41 -0700219 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700220 * Update ARP Cache using ARP packets It is used to set destination MAC
221 * address to forward packets to known hosts. But, it will be replace with
222 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700223 *
Sangho Shin2f263692014-09-15 14:09:41 -0700224 * @param arp APR packets to use for updating ARP entries
225 */
226 public void updateArpCache(ARP arp) {
227
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700228 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
229 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700230 // TODO: Need to check the duplication
231 arpEntries.add(arpEntry);
232 }
233
234 /**
235 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700236 *
Sangho Shin2f263692014-09-15 14:09:41 -0700237 * @param destinationAddress IP address to get MAC address
238 * @return MAC Address to given IP address
239 */
240 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
241
242 // Can't we get the host IP address from the TopologyService ??
243
244 Iterator<ArpEntry> iterator = arpEntries.iterator();
245
246 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
247 byte[] ipAddressInByte = ipAddress.getBytes();
248
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700249 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700250 ArpEntry arpEntry = iterator.next();
251 byte[] address = arpEntry.targetIpAddress;
252
253 IPv4Address a = IPv4Address.of(address);
254 IPv4Address b = IPv4Address.of(ipAddressInByte);
255
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700256 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700257 log.debug("Found an arp entry");
258 return arpEntry.targetMacAddress;
259 }
260 }
261
262 return null;
263 }
264
Sangho Shineb083032014-09-22 16:11:34 -0700265 /**
266 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700267 *
Sangho Shineb083032014-09-22 16:11:34 -0700268 * @param destinationAddress
269 * @param sw
270 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700271 *
Sangho Shineb083032014-09-22 16:11:34 -0700272 */
273 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
274 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
275 }
Sangho Shin2f263692014-09-15 14:09:41 -0700276
277 /**
278 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700279 *
Sangho Shin2f263692014-09-15 14:09:41 -0700280 */
281 private class ArpEntry {
282
283 byte[] targetMacAddress;
284 byte[] targetIpAddress;
285
286 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
287 this.targetMacAddress = macAddress;
288 this.targetIpAddress = ipAddress;
289 }
Sangho Shin2f263692014-09-15 14:09:41 -0700290 }
Sangho Shineb083032014-09-22 16:11:34 -0700291
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700292 /**
293 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700294 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700295 * @param topologyEvents the generated Topology Events
296 * @see TopologyEvents
297 */
298 public void topologyEvents(TopologyEvents topologyEvents)
299 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700300 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700301 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700302 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700303
Sangho Shin23f898d2014-10-13 16:54:00 -0700304 /**
305 * Process the multiple topology events with some delay (100MS at most for now)
306 *
307 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700308 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700309 numOfEventProcess ++;
310
Sangho Shin51625342014-10-17 09:30:48 -0700311 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
312 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
313 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
314 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
315 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
316 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
317 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700318
Sangho Shin5be3e532014-10-03 17:20:58 -0700319 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700320 // We should handle the events in the order of when they happen
321 // TODO: We need to simulate the final results of multiple events
322 // and shoot only the final state.
323 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
324 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700325
Sangho Shin5be3e532014-10-03 17:20:58 -0700326 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700327
328 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
329 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
330 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
331 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
332 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
333 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
334 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
335
336 linkEntriesAddedAll.addAll(linkEntriesAdded);
337 portEntriesAddedAll.addAll(portEntriesAdded);
338 portEntriesRemovedAll.addAll(portEntriesRemoved);
339 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
340 switchAddedAll.addAll(switchAdded);
341 switchRemovedAll.addAll(switchRemoved);
342 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700343 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700344
345 if (!portEntriesRemoved.isEmpty()) {
346 processPortRemoval(portEntriesRemoved);
347 }
348
349 if (!linkEntriesRemoved.isEmpty()) {
350 processLinkRemoval(linkEntriesRemoved);
351 }
352
353 if (!switchRemoved.isEmpty()) {
354 processSwitchRemoved(switchRemoved);
355 }
356
357 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700358 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700359 }
360
361 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700362 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700363 }
364
365 if (!portEntriesAdded.isEmpty()) {
366 processPortAdd(portEntriesAdded);
367 }
368
369 if (!switchAdded.isEmpty()) {
370 processSwitchAdd(switchAdded);
371 }
Sangho Shin51625342014-10-17 09:30:48 -0700372
Sangho Shinbce900e2014-10-07 17:13:23 -0700373 }
374
Sangho Shin23f898d2014-10-13 16:54:00 -0700375 // TODO: 100ms is enough to check both mastership removed events
376 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700377 if (!mastershipRemovedAll.isEmpty()) {
378 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700379 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700380 }
381 else {
382 HashMap<String, MastershipData> mastershipToRemove =
383 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700384 for (MastershipData ms: mastershipRemovedAll) {
385 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700386 // TODO: check ALL ports of the switch are dead ..
387 if (port.getDpid().equals(ms.getDpid())) {
388 mastershipToRemove.put(ms.getDpid().toString(), ms);
389 }
390 }
391 log.debug("Swtich {} is really down.", ms.getDpid());
392 }
393 processMastershipRemoved(mastershipToRemove.values());
394 }
395 }
396
Sangho Shinbce900e2014-10-07 17:13:23 -0700397 log.debug("num events {}, num of process {}, "
398 + "num of Population {}", numOfEvents, numOfEventProcess,
399 numOfPopulation);
400 }
401
402 /**
Sangho Shin23f898d2014-10-13 16:54:00 -0700403 * Add the link immediately
404 * The function is scheduled when link add event happens and called
405 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
406 */
407 private void delayedAddLink() {
408
409 processLinkAdd(linksToAdd.values(), true);
410
411 }
412
413 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700414 * Process the SwitchAdded events from topologyMananger.
415 * It does nothing. When a switch is added, then link will be added too.
416 * LinkAdded event will handle process all re-computation.
417 *
418 * @param switchAdded
419 */
420 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
421
422 }
423
424 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700425 * Remove all ports connected to the switch removed
426 *
427 * @param mastershipRemoved master switch info removed
428 */
429 private void processMastershipRemoved(Collection<MastershipData>
430 mastershipRemoved) {
431 for (MastershipData mastership: mastershipRemoved) {
432 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
433 for (Link link: sw.getOutgoingLinks()) {
434 Port dstPort = link.getDstPort();
435 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
436 getSwId(dstPort.getDpid().toString()));
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700437 if (dstSw != null) {
438 dstSw.removePortFromGroups(dstPort.getNumber());
439 log.debug("MasterSwitch {} is gone: remove port {}", sw.getDpid(), dstPort);
440 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700441 }
Sangho Shin61535402014-10-01 11:37:14 -0700442 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700443
444 linksToAdd.clear();
445 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700446 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700447
Sangho Shinbce900e2014-10-07 17:13:23 -0700448 /**
449 * Remove all ports connected to the switch removed
450 *
451 * @param switchRemoved Switch removed
452 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700453 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700454 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700455 }
456
Sangho Shin61535402014-10-01 11:37:14 -0700457 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700458 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700459 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700460 * @param portEntries
461 */
462 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700463 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700464 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700465 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700466
Sangho Shinfbc572c2014-10-02 16:37:05 -0700467 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700468 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700469 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700470 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700471 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700472 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700473 }
474 }
475
476 /**
477 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700478 * If the link to add was removed before, then we just schedule the add link
479 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700480 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700481 * @param linkEntries
482 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700483 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700484
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700485 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700486
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700487 SwitchPort srcPort = link.getSrc();
488 SwitchPort dstPort = link.getDst();
489
Sangho Shin23f898d2014-10-13 16:54:00 -0700490 String key = srcPort.getDpid().toString() +
491 dstPort.getDpid().toString();
492 if (!delayed) {
493 if (linksDown.containsKey(key)) {
494 linksToAdd.put(key, link);
495 linksDown.remove(key);
496 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
497 log.debug("Add link {} with 5 sec delay", link);
498 // TODO: What if we have multiple events of add link:
499 // one is new link add, the other one is link up for
500 // broken link? ECMPSPG function cannot deal with it for now
501 return;
502 }
503 }
504 else {
505 if (linksDown.containsKey(key)) {
506 linksToAdd.remove(key);
507 log.debug("Do not add the link {}: it is down again!", link);
508 return;
509 }
510 }
511
Sangho Shinfbc572c2014-10-02 16:37:05 -0700512 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700513 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700514 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700515 getSwId(dstPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700516
Sangho Shin815af0c2014-10-10 13:05:45 -0700517 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700518 continue;
519
520 srcSw.addPortToGroups(srcPort.getPortNumber());
521 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700522
Sangho Shin15273b62014-10-16 22:22:05 -0700523 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
524 // link);
525 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
526 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700527
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700528 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700529 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700530 }
531
532 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700533 * Check if all links are gone b/w the two switches. If all links are gone,
534 * then we need to recalculate the path. Otherwise, just report link failure
535 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700536 *
Sangho Shin61535402014-10-01 11:37:14 -0700537 * @param linkEntries
538 */
539 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700540 boolean recomputationRequired = false;
541
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700542 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700543 SwitchPort srcPort = link.getSrc();
544 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700545
Sangho Shinfbc572c2014-10-02 16:37:05 -0700546 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700547 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700548 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700549 getSwId(dstPort.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700550 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700551 /* If this link is not between two switches, ignore it */
552 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700553
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700554 srcSw.removePortFromGroups(srcPort.getPortNumber());
555 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700556 log.debug("Remove port {} from switch {}", srcPort, srcSw);
557 log.debug("Remove port {} from switch {}", dstPort, dstSw);
558
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700559 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
560 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700561 // TODO: it is only for debugging purpose.
Sangho Shin99918bd2014-10-08 15:52:35 -0700562 // We just need to call populateEcmpRoutingRules() and return;
Sangho Shinbce900e2014-10-07 17:13:23 -0700563 recomputationRequired = true;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700564 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin5be3e532014-10-03 17:20:58 -0700565 dstPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700566 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700567
568 String key = link.getSrc().getDpid().toString()+
569 link.getDst().getDpid().toString();
570 if (!linksDown.containsKey(key)) {
571 linksDown.put(key, link);
572 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700573 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700574
575 if (recomputationRequired)
576 populateEcmpRoutingRules(false);
Sangho Shin61535402014-10-01 11:37:14 -0700577 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700578
Sangho Shin61535402014-10-01 11:37:14 -0700579 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700580 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700581 *
Sangho Shin61535402014-10-01 11:37:14 -0700582 * @param portEntries
583 */
584 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700585 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700586 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700587
Sangho Shinfbc572c2014-10-02 16:37:05 -0700588 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700589 getSwId(port.getDpid().toString()));
Sangho Shin815af0c2014-10-10 13:05:45 -0700590 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700591 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700592 log.debug("Remove port {} from switch {}", port, dpid);
593 }
Sangho Shin61535402014-10-01 11:37:14 -0700594 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700595 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700596
597 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700598 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700599 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700600 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700601 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700602 private void populateEcmpRoutingRules(boolean modified) {
603 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700604 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700605 for (Switch sw : switches) {
606 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700607 graphs.put(sw, ecmpSPG);
608 //log.debug("ECMPShortestPathGraph is computed for switch {}",
609 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700610 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700611 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700612 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700613 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700614
Sangho Shin99918bd2014-10-08 15:52:35 -0700615 /**
616 * populate routing rules to forward packets from the switch given to
617 * all other switches.
618 *
619 * @param sw source switch
620 * @param ecmpSPG shortest path from the the source switch to all others
621 * @param modified modification flag
622 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700623 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700624 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700625
Sangho Shinfbc572c2014-10-02 16:37:05 -0700626 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
627 ecmpSPG.getAllLearnedSwitchesAndVia();
628 for (Integer itrIdx : switchVia.keySet()) {
629 //log.debug("ECMPShortestPathGraph:Switches learned in "
630 // + "Iteration{} from switch {}:",
631 // itrIdx,
632 // HexString.toHexString(sw.getDpid().value()));
633 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
634 switchVia.get(itrIdx);
635 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700636 //log.debug("ECMPShortestPathGraph:****switch {} via:",
637 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700638 String destSw = sw.getDpid().toString();
639 List<String> fwdToSw = new ArrayList<String>();
640
Sangho Shinfbc572c2014-10-02 16:37:05 -0700641 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700642 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700643 if (via.isEmpty()) {
644 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700645 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700646 else {
647 fwdToSw.add(via.get(0).toString());
648 }
Sangho Shin43cee112014-09-25 16:43:34 -0700649 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700650 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shineb083032014-09-22 16:11:34 -0700651 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700652
653 // Send Barrier Message and make sure all rules are set
654 // before we set the rules to next routers
Saurav Dasa962a692014-10-17 14:52:38 -0700655 // TODO: barriers to all switches in this update stage
Sangho Shinfbc572c2014-10-02 16:37:05 -0700656 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
657 getSwId(sw.getDpid().toString()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700658 if (sw13 != null) {
Saurav Dasa962a692014-10-17 14:52:38 -0700659 OFBarrierReplyFuture replyFuture = null;
Sangho Shin5be3e532014-10-03 17:20:58 -0700660 try {
Saurav Dasa962a692014-10-17 14:52:38 -0700661 replyFuture = sw13.sendBarrier();
Sangho Shin5be3e532014-10-03 17:20:58 -0700662 } catch (IOException e) {
Saurav Dasa962a692014-10-17 14:52:38 -0700663 log.error("Error sending barrier request to switch {}",
664 sw13.getId(), e.getCause());
Sangho Shin5be3e532014-10-03 17:20:58 -0700665 }
Saurav Dasa962a692014-10-17 14:52:38 -0700666 OFBarrierReply br = null;
667 try {
668 br = replyFuture.get(2, TimeUnit.SECONDS);
669 } catch (TimeoutException | InterruptedException | ExecutionException e) {
670 // XXX for some reason these exceptions are not being thrown
671 }
672 if (br == null) {
673 log.warn("Did not receive barrier-reply from {}", sw13.getId());
674 // XXX take corrective action
675 }
676
Sangho Shinfbc572c2014-10-02 16:37:05 -0700677 }
678 }
679
680 }
681
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700682
Sangho Shin99918bd2014-10-08 15:52:35 -0700683 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700684 * This class is used only for link recovery optimization in
685 * modifyEcmpRoutingRules() function.
Sangho Shin99918bd2014-10-08 15:52:35 -0700686 * TODO: please remove if the optimization is not used at all
Sangho Shinbce900e2014-10-07 17:13:23 -0700687 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700688 private class SwitchPair {
689 private Switch src;
690 private Switch dst;
691
692 public SwitchPair(Switch src, Switch dst) {
693 this.src = src;
694 this.dst = dst;
695 }
696
697 public Switch getSource() {
698 return src;
699 }
700
701 public Switch getDestination() {
702 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700703 }
Sangho Shin43cee112014-09-25 16:43:34 -0700704 }
705
706 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700707 * Modify the routing rules for the lost links
708 * - Recompute the path if the link failed is included in the path
709 * (including src and dest).
710 *
711 * @param newLink
712 */
713 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
714
715 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700716 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700717
718 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
719 Switch rootSw = ecmpSPG.getRootSwitch();
720 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
721 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
722 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
723 for (Switch destSw: p.keySet()) {
724 ArrayList<Path> path = p.get(destSw);
725 if (checkPath(path, linkRemoved)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700726 boolean found = false;
727 for (SwitchPair pair: linksToRecompute) {
728 if (pair.getSource().getDpid() == rootSw.getDpid() &&
729 pair.getSource().getDpid() == destSw.getDpid()) {
730 found = true;
731 }
732 }
733 if (!found) {
734 linksToRecompute.add(new SwitchPair(rootSw, destSw));
735 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700736 }
737 }
738 }
739 }
740
741 // Recompute the path for the specific route
742 for (SwitchPair pair: linksToRecompute) {
743
744 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
Sangho Shin99918bd2014-10-08 15:52:35 -0700745 // We need the following function for optimization
Sangho Shinfbc572c2014-10-02 16:37:05 -0700746 //ECMPShortestPathGraph ecmpSPG =
747 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
748 ECMPShortestPathGraph ecmpSPG =
749 new ECMPShortestPathGraph(pair.getSource());
Sangho Shin5be3e532014-10-03 17:20:58 -0700750 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700751 }
752 }
753
754 /**
755 * Check if the path is affected from the link removed
756 *
757 * @param path Path to check
758 * @param linkRemoved link removed
759 * @return true if the path contains the link removed
760 */
761 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
762
763 for (Path ppp: path) {
764 // TODO: need to check if this is a bidirectional or
765 // unidirectional
Sangho Shin5be3e532014-10-03 17:20:58 -0700766 for (LinkData link: ppp) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700767 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
768 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
769 return true;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700770 }
771 }
772
773 return false;
774 }
775
776 /**
777 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700778 * Set routing rules in targetSw {forward packets to fwdToSw switches in
779 * order to send packets to destSw} - If the target switch is an edge router
780 * and final destnation switch is also an edge router, then set IP
781 * forwarding rules to subnets - If only the target switch is an edge
782 * router, then set IP forwarding rule to the transit router loopback IP
783 * address - If the target is a transit router, then just set the MPLS
784 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700785 *
Sangho Shin43cee112014-09-25 16:43:34 -0700786 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700787 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700788 * @param fwdToSw next hop switches
789 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700790 private void setRoutingRule(Switch targetSw, String destSw,
791 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700792
Sangho Shin43cee112014-09-25 16:43:34 -0700793 if (fwdToSw.isEmpty()) {
794 fwdToSw.add(destSw);
795 }
796
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700797 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700798 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
799 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700800 // We assume that there is at least one transit router b/w edge
801 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700802 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
803 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700804 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700805 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700806
Sangho Shin43cee112014-09-25 16:43:34 -0700807 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700808 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
809 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700810 // Edge router can be a transit router
811 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700812 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700813 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700814 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700815 // We assume that there is at least one transit router b/w edge
816 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700817 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
818 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700819 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
820 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700821 // Edge router can be a transit router
822 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700823 }
824 // if it is a transit router, then set rules in the MPLS table
825 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700826 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700827 }
828
829 }
830
Sangho Shinfbc572c2014-10-02 16:37:05 -0700831 /**
832 * Set IP forwarding rule to the gateway of each subnet of switches
833 *
834 * @param targetSw Switch to set rules
835 * @param subnets subnet information
836 * @param mplsLabel destination MPLS label
837 * @param fwdToSw router to forward packets to
838 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700839 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700840 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700841
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700842 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700843 new ArrayList<MatchActionOperationEntry>();
844
845 try {
846 JSONArray arry = new JSONArray(subnets);
847 for (int i = 0; i < arry.length(); i++) {
848 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700849 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
850 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700851 }
852 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700853 e.printStackTrace();
854 }
855
856 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700857 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700858 getSwId(targetSw.getDpid().toString()));
859
Sangho Shin721ca042014-10-09 13:03:40 -0700860 if (sw13 != null) {
861 try {
862 sw13.pushFlows(entries);
863 } catch (IOException e) {
864 e.printStackTrace();
865 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700866 }
867 }
868
869 }
870
Sangho Shin43cee112014-09-25 16:43:34 -0700871 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700872 * Check if the switch is the edge router or not.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700873 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700874 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700875 * @return true if it is an edge router, otherwise false
876 */
877 private boolean IsEdgeRouter(String dpid) {
878
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700879 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700880 String dpidStr = sw.getDpid().toString();
881 if (dpid.equals(dpidStr)) {
Sangho Shinbce900e2014-10-07 17:13:23 -0700882 /*
Sangho Shin43cee112014-09-25 16:43:34 -0700883 String subnetInfo = sw.getStringAttribute("subnets");
884 if (subnetInfo == null || subnetInfo.equals("[]")) {
885 return false;
886 }
887 else
888 return true;
Sangho Shinbce900e2014-10-07 17:13:23 -0700889 */
890 String isEdge = sw.getStringAttribute("isEdgeRouter");
891 if (isEdge != null) {
892 if (isEdge.equals("true"))
893 return true;
894 else
895 return false;
896 }
Sangho Shin43cee112014-09-25 16:43:34 -0700897 }
898 }
899
900 return false;
901 }
902
903 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700904 * Set IP forwarding rule - If the destination is the next hop, then do not
905 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
906 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700907 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700908 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700909 * @param subnetIp Match IP address
910 * @param mplsLabel MPLS label of final destination router
911 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700912 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700913 */
914 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700915 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
916 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700917
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700918 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700919 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700920 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700921
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700922 // If destination SW is the same as the fwd SW, then do not push MPLS
923 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700924 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700925 PushMplsAction pushMplsAction = new PushMplsAction();
926 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
927 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700928 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700929
Sangho Shin62ce5c12014-10-08 16:24:40 -0700930 //actions.add(pushMplsAction);
931 //actions.add(copyTtlOutAction);
932 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700933 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700934 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700935 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700936 else {
937 String fwdToSw = fwdToSws.get(0);
938 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
939 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
940 actions.add(decTtlAction);
941 }
942 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700943 SetMplsIdAction setIdAction = new SetMplsIdAction(
944 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700945 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700946 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700947
Sangho Shin62ce5c12014-10-08 16:24:40 -0700948 //actions.add(pushMplsAction);
949 //actions.add(copyTtlOutAction);
950 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700951 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700952 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700953 }
954 }
Sangho Shin43cee112014-09-25 16:43:34 -0700955
Sangho Shin43cee112014-09-25 16:43:34 -0700956 for (String fwdSw : fwdToSws) {
957 groupAction.addSwitch(new Dpid(fwdSw));
958 }
959 actions.add(groupAction);
960
Sangho Shin99918bd2014-10-08 15:52:35 -0700961 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700962 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700963
Sangho Shin5be3e532014-10-03 17:20:58 -0700964 Operator operator = null;
965 if (modified)
966 operator = Operator.MODIFY;
967 else
968 operator = Operator.ADD;
969
Sangho Shin43cee112014-09-25 16:43:34 -0700970 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -0700971 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700972
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700973 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700974 getSwId(sw.getDpid().toString()));
975
Sangho Shin5be3e532014-10-03 17:20:58 -0700976 if (sw13 != null) {
977 try {
Sangho Shinbce900e2014-10-07 17:13:23 -0700978 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -0700979 if (entries != null)
980 entries.add(maEntry);
981 else
982 sw13.pushFlow(maEntry);
983 } catch (IOException e) {
984 e.printStackTrace();
985 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700986 }
987
Sangho Shin43cee112014-09-25 16:43:34 -0700988 }
989
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700990 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700991 * Set MPLS forwarding rules to MPLS table
992 * </p>
993 * If the destination is the same as the next hop to forward packets then,
994 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
995 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
996 * TTL of the another MPLS header.
997 * If the next hop is not the destination, just forward packets to next
998 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700999 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001000 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -07001001 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001002 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001003 * */
Sangho Shin5be3e532014-10-03 17:20:58 -07001004 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
1005 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -07001006
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001007 if (fwdSws.isEmpty())
1008 return;
Sangho Shin43cee112014-09-25 16:43:34 -07001009
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001010 Collection<MatchActionOperationEntry> maEntries =
1011 new ArrayList<MatchActionOperationEntry>();
1012 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -07001013
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001014 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
1015 // One rule for Bos = 1
1016 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), true);
1017 List<Action> actions = new ArrayList<Action>();
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001018
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001019 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
1020 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
1021 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
1022
1023 actions.add(copyTtlInAction);
1024 actions.add(popAction);
1025 actions.add(decNwTtlAction);
1026
1027 GroupAction groupAction = new GroupAction();
1028 groupAction.addSwitch(new Dpid(fwdSw1));
1029 actions.add(groupAction);
1030
1031 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
1032 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1033 Operator operator = Operator.ADD;
1034 MatchActionOperationEntry maEntry =
1035 new MatchActionOperationEntry(operator, matchAction);
1036 maEntries.add(maEntry);
1037
1038 // One rule for Bos = 0
Sangho Shin23f898d2014-10-13 16:54:00 -07001039 MplsMatch mplsMatchBos = new MplsMatch(Integer.parseInt(mplsLabel), false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001040 List<Action> actionsBos = new ArrayList<Action>();
Sangho Shin15273b62014-10-16 22:22:05 -07001041 PopMplsAction popActionBos = new PopMplsAction(EthType.MPLS_UNICAST);
1042 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1043
1044 actionsBos.add(copyTtlInAction);
1045 actionsBos.add(popActionBos);
1046 actionsBos.add(decMplsTtlAction);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001047 actionsBos.add(groupAction);
1048
1049 MatchAction matchActionBos = new MatchAction(new MatchActionId(matchActionId++),
1050 new SwitchPort((long) 0, (short) 0), mplsMatchBos, actionsBos);
1051 MatchActionOperationEntry maEntryBos =
1052 new MatchActionOperationEntry(operator, matchActionBos);
1053 maEntries.add(maEntryBos);
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001054 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001055 else {
1056 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), false);
1057 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -07001058
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001059 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1060 actions.add(decMplsTtlAction);
Sangho Shin43cee112014-09-25 16:43:34 -07001061
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001062 GroupAction groupAction = new GroupAction();
1063 for (String fwdSw : fwdSws)
1064 groupAction.addSwitch(new Dpid(fwdSw));
1065 actions.add(groupAction);
Sangho Shin5be3e532014-10-03 17:20:58 -07001066
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001067 MatchAction matchAction = new MatchAction(new MatchActionId(
1068 matchActionId++),
1069 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1070 Operator operator = Operator.ADD;
1071 MatchActionOperationEntry maEntry =
1072 new MatchActionOperationEntry(operator, matchAction);
1073 maEntries.add(maEntry);
Sangho Shine2e9bcd2014-10-13 15:14:18 -07001074
1075 // BoS = 1
1076 MplsMatch mplsMatchBoS = new MplsMatch(Integer.parseInt(mplsLabel), true);
1077 List<Action> actionsBoS = new ArrayList<Action>();
1078
1079 DecMplsTtlAction decMplsTtlActionBoS = new DecMplsTtlAction(1);
1080 actionsBoS.add(decMplsTtlActionBoS);
1081
1082 GroupAction groupActionBoS = new GroupAction();
1083 for (String fwdSw : fwdSws)
1084 groupActionBoS.addSwitch(new Dpid(fwdSw));
1085 actionsBoS.add(groupActionBoS);
1086
1087 MatchAction matchActionBos = new MatchAction(new MatchActionId(
1088 matchActionId++),
1089 new SwitchPort((long) 0, (short) 0), mplsMatchBoS, actionsBoS);
1090 MatchActionOperationEntry maEntryBoS =
1091 new MatchActionOperationEntry(operator, matchActionBos);
1092 maEntries.add(maEntryBoS);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001093 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001094 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001095 getSwId(sw.getDpid().toString()));
1096
Sangho Shin5be3e532014-10-03 17:20:58 -07001097 if (sw13 != null) {
1098 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001099 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001100 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001101 } catch (IOException e) {
1102 e.printStackTrace();
1103 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001104 }
Sangho Shin43cee112014-09-25 16:43:34 -07001105 }
1106
Sangho Shin15273b62014-10-16 22:22:05 -07001107 /**
1108 * Create a tunnel for policy routing
1109 * It delivers the node IDs of tunnels to driver.
1110 * Split the node IDs if number of IDs exceeds the limit for stitching.
1111 *
1112 * @param tunnelId Node IDs for the tunnel
1113 * @param Ids tunnel ID
1114 */
1115 public boolean createTunnel(int tunnelId, List<String> Ids) {
1116
1117 if (tunnelId < 0) {
1118 log.debug("Tunnel ID should be posivtive integer.");
1119 return false;
1120 }
1121
1122 if (Ids.isEmpty() || Ids.size() < 2) {
1123 log.debug("Wrong tunnel information");
1124 return false;
1125 }
1126
1127 HashMap<String, PolicyRouteInfo> stitchingRule = getStitchingRule(Ids);
1128 stitchInfo.put(Integer.valueOf(tunnelId), stitchingRule);
1129 if (stitchingRule == null) {
1130 log.debug("Failed to get the policy rule.");
1131 return false;
1132 }
1133 HashMap<String, Integer> switchGroupPair = new HashMap<String, Integer>();
1134 for (String targetDpid: stitchingRule.keySet()) {
1135 PolicyRouteInfo route = stitchingRule.get(targetDpid);
1136
1137 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
1138 getSwId(targetDpid.toString()));
1139
1140 if (targetSw == null) {
1141 log.debug("Switch {} is gone.", targetDpid);
1142 return false;
1143 }
1144
1145 NeighborSet ns = new NeighborSet();
1146 for (Dpid dpid: route.getFwdSwDpid())
1147 ns.addDpid(dpid);
1148
1149 printTunnelInfo(targetSw, tunnelId, route.getRoute(), ns);
1150 int groupId = targetSw.createTunnel(tunnelId, route.getRoute(), ns);
1151 switchGroupPair.put(targetDpid.toString(), groupId);
1152
1153 }
1154
1155 tunnelGroupMap.put(Integer.valueOf(tunnelId), switchGroupPair);
1156
1157 return true;
1158 }
1159
1160 /**
1161 * Set policy table for policy routing
1162 *
1163 * @param sw
1164 * @param mplsLabel
1165 */
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001166 public void setPolicyTable(MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001167 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001168 Short srcTcpPort, Short dstTcpPort, int tid) {
Sangho Shin15273b62014-10-16 22:22:05 -07001169
1170 HashMap<String, PolicyRouteInfo> routeInfo = stitchInfo.get(Integer.valueOf(tid));
1171 HashMap<String, Integer> switchGroupPair = tunnelGroupMap.get(Integer.valueOf(tid));
1172 for (String srcDpid: routeInfo.keySet()) {
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001173
1174 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1175
1176 if (srcMac != null)
1177 packetBuilder.setSrcMac(srcMac);
1178 if (dstMac != null)
1179 packetBuilder.setDstMac(dstMac);
1180 if (etherType != null) {
1181 packetBuilder.setEtherType(etherType);
1182 }
1183 if (srcIp != null) {
1184 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1185 }
1186 if (dstIp != null) {
1187 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1188 }
1189 if (ipProto != null) {
1190 packetBuilder.setIpProto(ipProto);
1191 }
1192 if (srcTcpPort > 0) {
1193 packetBuilder.setSrcTcpPort(srcTcpPort);
1194 }
1195 if (dstTcpPort > 0) {
1196 packetBuilder.setDstTcpPort(dstTcpPort);
1197 }
1198 PacketMatch policyMatch = packetBuilder.build();
1199
Sangho Shin15273b62014-10-16 22:22:05 -07001200 List<Action> actions = new ArrayList<>();
1201 GroupAction groupAction = new GroupAction();
1202 int gropuId = switchGroupPair.get(srcDpid);
1203 groupAction.setGroupId(gropuId);
1204 actions.add(groupAction);
1205
1206 MatchAction matchAction = new MatchAction(new MatchActionId(
1207 matchActionId++),
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001208 new SwitchPort((long) 0, (short) 0), policyMatch, actions);
Sangho Shin15273b62014-10-16 22:22:05 -07001209 MatchActionOperationEntry maEntry =
1210 new MatchActionOperationEntry(Operator.ADD, matchAction);
1211
1212 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
1213 getSwId(srcDpid));
1214
1215 if (sw13 != null) {
1216 printMatchActionOperationEntry(sw13, maEntry);
1217 try {
1218 sw13.pushFlow(maEntry);
1219 } catch (IOException e) {
1220 e.printStackTrace();
1221 }
1222 }
1223 }
1224 }
1225
1226 /**
1227 * Get the forwarding Switch DPIDs to send packets to a node
1228 *
1229 * @param srcSw source switch
1230 * @param nodeId destination node Id
1231 * @return list of switch DPID to forward packets to
1232 */
1233
1234 private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
1235
1236 List<Dpid> fwdSws = new ArrayList<Dpid>();
1237 Switch destSw = null;
1238
1239 destSw = getSwitchFromNodeId(nodeId);
1240
1241 if (destSw == null) {
1242 log.debug("Cannot find the switch with ID {}", nodeId);
1243 return null;
1244 }
1245
1246 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1247
1248 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1249 ecmpSPG.getAllLearnedSwitchesAndVia();
1250 for (Integer itrIdx : switchVia.keySet()) {
1251 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1252 switchVia.get(itrIdx);
1253 for (Switch targetSw : swViaMap.keySet()) {
1254 String destSwDpid = destSw.getDpid().toString();
1255 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1256 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1257 if (via.isEmpty()) {
1258 fwdSws.add(destSw.getDpid());
1259 }
1260 else {
1261 fwdSws.add(via.get(0));
1262 }
1263 }
1264 }
1265 }
1266 }
1267
1268 return fwdSws;
1269 }
1270
1271 /**
1272 * Get switch for the node Id specified
1273 *
1274 * @param nodeId node ID for switch
1275 * @return Switch
1276 */
1277 private Switch getSwitchFromNodeId(String nodeId) {
1278
1279 for (Switch sw : mutableTopology.getSwitches()) {
1280 String id = sw.getStringAttribute("nodeSid");
1281 if (id.equals(nodeId)) {
1282 return sw;
1283 }
1284 }
1285
1286 return null;
1287 }
1288
1289 /**
1290 * Convert a string DPID to its Switch Id (integer)
1291 *
1292 * @param dpid
1293 * @return
1294 */
1295 private long getSwId(String dpid) {
1296
1297 long swId = 0;
1298
1299 String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
1300 if (swIdHexStr != null)
1301 swId = Integer.decode(swIdHexStr);
1302
1303 return swId;
1304 }
1305
1306 private void runTest() {
1307
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001308 String[] routeArray = {"101", "102", "103", "104", "105", "108", "110"};
1309 List<String> routeList = new ArrayList<String>();
1310 for (int i = 0; i < routeArray.length; i++)
1311 routeList.add(routeArray[i]);
Sangho Shin15273b62014-10-16 22:22:05 -07001312
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001313 if (createTunnel(1, routeList)) {
1314 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1315 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
Sangho Shin15273b62014-10-16 22:22:05 -07001316
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001317 this.setPolicyTable(null, null, Ethernet.TYPE_IPV4, srcIp, dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 1);
Sangho Shin15273b62014-10-16 22:22:05 -07001318 }
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001319 else {
1320 testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin15273b62014-10-16 22:22:05 -07001321 }
1322 }
1323
1324 private void runTest1() {
1325
1326 String dpid1 = "00:00:00:00:00:00:00:01";
1327 String dpid2 = "00:00:00:00:00:00:00:0a";
1328 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1329 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1330
1331 if (srcSw == null || dstSw == null) {
1332 testTask.reschedule(1, TimeUnit.SECONDS);
1333 log.debug("Switch is gone. Reschedule the test");
1334 return;
1335 }
1336
1337 String[] routeArray = {"101", "102", "105", "108", "110"};
1338 List<String> routeList = new ArrayList<String>();
1339 for (int i = 0; i < routeArray.length; i++)
1340 routeList.add(routeArray[i]);
1341
1342 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1343
1344 log.debug("Test set is {}", routeList.toString());
1345 log.debug("Result set is {}", optimizedRoute.toString());
1346
1347
1348 }
1349
1350 /**
1351 * Optimize the mpls label
1352 * The feature will be used only for policy of "avoid a specific switch".
1353 * Check route to each router in route backward.
1354 * If there is only one route to the router and the routers are included in
1355 * the route, remove the id from the path.
1356 * A-B-C-D-E => A-B-C-D-E -> A-E
1357 * | | => A-B-H-I -> A-I
1358 * F-G-H-I => A-D-I -> A-D-I
1359 */
1360 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
1361
1362 List<String> optimizedPath = new ArrayList<String>();
1363 optimizedPath.addAll(route);
1364 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1365
1366 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
1367 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
1368 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
1369 for (Switch s: p.keySet()) {
1370 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
1371 ArrayList<Path> ecmpPaths = p.get(s);
1372 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
1373 for (Path path: ecmpPaths) {
1374 for (LinkData link: path) {
1375 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
1376 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
1377 if (optimizedPath.contains(srcId)) {
1378 optimizedPath.remove(srcId);
1379 }
1380 if (optimizedPath.contains(dstId)) {
1381 optimizedPath.remove(dstId);
1382 }
1383 }
1384 }
1385 }
1386 }
1387 }
1388 }
1389
1390 return optimizedPath;
1391
1392 }
1393
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001394
Sangho Shin15273b62014-10-16 22:22:05 -07001395 class PolicyRouteInfo {
1396
1397 String srcSwDpid;
1398 List<Dpid> fwdSwDpids;
1399 List<String> route;
1400
1401 PolicyRouteInfo() {
1402 fwdSwDpids = new ArrayList<Dpid>();
1403 route = new ArrayList<String>();
1404 }
1405
1406 void setSrcDpid(String dpid) {
1407 this.srcSwDpid = dpid;
1408 }
1409
1410 void setFwdSwDpid(List<Dpid> dpid) {
1411 this.fwdSwDpids = dpid;
1412 }
1413
1414 void addRoute(String id) {
1415 route.add(id);
1416 }
1417
1418 void setRoute(List<String> r) {
1419 this.route = r;
1420 }
1421
1422 String getSrcSwDpid() {
1423 return this.srcSwDpid;
1424 }
1425
1426 List<Dpid> getFwdSwDpid() {
1427 return this.fwdSwDpids;
1428 }
1429
1430 List<String> getRoute() {
1431 return this.route;
1432 }
1433 }
1434
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001435
Sangho Shin15273b62014-10-16 22:22:05 -07001436 /**
1437 *
1438 *
1439 * @param srcSw
1440 * @param dstSw
1441 * @param route
1442 * @return
1443 */
1444 private HashMap<String, PolicyRouteInfo> getStitchingRule(List<String> route) {
1445
1446 if (route.isEmpty() || route.size() < 2)
1447 return null;
1448
1449 HashMap<String, PolicyRouteInfo> rules = new HashMap<String, PolicyRouteInfo>();
1450
1451 Switch srcSw = this.getSwitchFromNodeId(route.get(0));
1452 String srcDpid = srcSw.getDpid().toString();
1453
1454 if (route.size() <= MAX_NUM_LABELS+1) {
1455 PolicyRouteInfo info = new PolicyRouteInfo();
1456 info.setSrcDpid(srcSw.getDpid().toString());
1457 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, route.get(1));
1458 info.setFwdSwDpid(fwdSwDpids);
1459 route.remove(0);
1460 info.setRoute(route);
1461 rules.put(srcDpid, info);
1462 return rules;
1463 }
1464
1465 int i = 0;
1466 PolicyRouteInfo routeInfo = new PolicyRouteInfo();
1467 String prevNodeId = null;
1468 boolean checkNeighbor = true;
1469
1470 for (String nodeId: route) {
1471 if (i == 0) {
1472 routeInfo.setSrcDpid(srcDpid);
1473 srcSw = getSwitchFromNodeId(nodeId);
1474 i++;
1475 }
1476 else if (i == 1) {
1477 if (checkNeighbor) {
1478 // Check if next node is the neighbor SW of the source SW
1479 List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
1480 if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
1481 log.debug("There is no route from node {} to node {}", srcSw.getDpid(), nodeId);
1482 return null;
1483 }
1484 // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
1485 boolean match = false;
1486 for (Dpid dpid: fwdSwDpids) {
1487 if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
1488 List<Dpid> fwdSws = new ArrayList<Dpid>();
1489 fwdSws.add(dpid);
1490 routeInfo.setFwdSwDpid(fwdSws);
1491 match = true;
1492 break;
1493 }
1494 }
1495 if (!match) {
1496 routeInfo.addRoute(nodeId);
1497 routeInfo.setFwdSwDpid(fwdSwDpids);
1498 i++;
1499 }
1500
1501 checkNeighbor = false;
1502 }
1503 else {
1504 routeInfo.addRoute(nodeId);
1505 i++;
1506 }
1507 }
1508 else {
1509 routeInfo.addRoute(nodeId);
1510 i++;
1511 }
1512
1513 if (i == MAX_NUM_LABELS+1) {
1514 rules.put(srcDpid, routeInfo);
1515 routeInfo = new PolicyRouteInfo();
1516 srcSw = getSwitchFromNodeId(nodeId);
1517 srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
1518 routeInfo.setSrcDpid(srcDpid);
1519 i = 1;
1520 checkNeighbor = true;
1521 }
1522 }
1523
1524 if (i < MAX_NUM_LABELS+1) {
1525 rules.put(srcDpid, routeInfo);
1526 }
1527
1528 return rules;
1529 }
1530
1531 /**
1532 * print tunnel info - used only for debugging.
1533 * @param targetSw
1534 *
1535 * @param fwdSwDpids
1536 * @param ids
1537 * @param tunnelId
1538 */
1539 private void printTunnelInfo(IOF13Switch targetSw, int tunnelId,
1540 List<String> ids, NeighborSet ns) {
1541 StringBuilder logStr = new StringBuilder("In switch " +
1542 targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
1543 for (String id: ids)
1544 logStr.append(id + "-");
1545 logStr.append(" output to ");
1546 for (Dpid dpid: ns.getDpids())
1547 logStr.append(dpid + " - ");
1548
1549 log.debug(logStr.toString());
1550
1551 }
1552
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001553
1554
Sangho Shin43cee112014-09-25 16:43:34 -07001555 /**
1556 * Debugging function to print out the Match Action Entry
Sangho Shin15273b62014-10-16 22:22:05 -07001557 * @param sw13
Sangho Shinfbc572c2014-10-02 16:37:05 -07001558 *
Sangho Shin43cee112014-09-25 16:43:34 -07001559 * @param maEntry
1560 */
Sangho Shin15273b62014-10-16 22:22:05 -07001561 private void printMatchActionOperationEntry(
1562 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -07001563
Sangho Shin15273b62014-10-16 22:22:05 -07001564 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001565
1566 MatchAction ma = maEntry.getTarget();
1567 Match m = ma.getMatch();
1568 List<Action> actions = ma.getActions();
1569
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001570 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -07001571 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -07001572 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -07001573 logStr.append(ip.toString());
1574 logStr.append(" then ");
1575 }
1576 else if (m instanceof MplsMatch) {
1577 logStr.append("If the MPLS label matches with ");
1578 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1579 logStr.append(mplsLabel);
1580 logStr.append(" then ");
1581 }
Sangho Shin15273b62014-10-16 22:22:05 -07001582 else if (m instanceof PacketMatch) {
1583 GroupAction ga = (GroupAction)actions.get(0);
1584 logStr.append("if the policy match is XXX then go to group " +
1585 ga.getGroupId());
1586 log.debug(logStr.toString());
1587 return;
1588 }
Sangho Shin43cee112014-09-25 16:43:34 -07001589
1590 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001591 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -07001592 if (action instanceof CopyTtlInAction) {
1593 logStr.append("copy ttl In, ");
1594 }
1595 else if (action instanceof CopyTtlOutAction) {
1596 logStr.append("copy ttl Out, ");
1597 }
1598 else if (action instanceof DecMplsTtlAction) {
1599 logStr.append("Dec MPLS TTL , ");
1600 }
1601 else if (action instanceof GroupAction) {
1602 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001603 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -07001604 logStr.append(dpids.toString() + ",");
1605
Sangho Shin43cee112014-09-25 16:43:34 -07001606 }
1607 else if (action instanceof PopMplsAction) {
1608 logStr.append("Pop MPLS label, ");
1609 }
1610 else if (action instanceof PushMplsAction) {
1611 logStr.append("Push MPLS label, ");
1612 }
1613 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001614 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -07001615 logStr.append("Set MPLS ID as " + id + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -07001616 }
1617 }
1618
1619 log.debug(logStr.toString());
1620
Sangho Shineb083032014-09-22 16:11:34 -07001621 }
1622
1623 /**
1624 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001625 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001626 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001627 * @return MPLS label for the switch
1628 */
1629
Sangho Shin43cee112014-09-25 16:43:34 -07001630 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001631
1632 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001633 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001634 String dpidStr = sw.getDpid().toString();
1635 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001636 mplsLabel = sw.getStringAttribute("nodeSid");
1637 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001638 }
1639 }
1640
Sangho Shineb083032014-09-22 16:11:34 -07001641 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001642 }
1643
Sangho Shineb083032014-09-22 16:11:34 -07001644 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001645 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001646 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001647 * @param addr - subnet address to match
1648 * @param addr1 - IP address to check
1649 * @return true if the IP address matches to the subnet, otherwise false
1650 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001651 public boolean netMatch(String addr, String addr1) { // addr is subnet
1652 // address and addr1 is
1653 // ip address. Function
1654 // will return true, if
1655 // addr1 is within
1656 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001657
1658 String[] parts = addr.split("/");
1659 String ip = parts[0];
1660 int prefix;
1661
1662 if (parts.length < 2) {
1663 prefix = 0;
1664 } else {
1665 prefix = Integer.parseInt(parts[1]);
1666 }
1667
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001668 Inet4Address a = null;
1669 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001670 try {
1671 a = (Inet4Address) InetAddress.getByName(ip);
1672 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001673 } catch (UnknownHostException e) {
1674 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001675
1676 byte[] b = a.getAddress();
1677 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001678 ((b[1] & 0xFF) << 16) |
1679 ((b[2] & 0xFF) << 8) |
1680 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001681
1682 byte[] b1 = a1.getAddress();
1683 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001684 ((b1[1] & 0xFF) << 16) |
1685 ((b1[2] & 0xFF) << 8) |
1686 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001687
1688 int mask = ~((1 << (32 - prefix)) - 1);
1689
1690 if ((ipInt & mask) == (ipInt1 & mask)) {
1691 return true;
1692 }
1693 else {
1694 return false;
1695 }
1696 }
Sangho Shineb083032014-09-22 16:11:34 -07001697
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001698 /**
1699 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001700 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001701 * @param sw - Switch to add the rule
1702 * @param hostIpAddress Destination host IP address
1703 * @param hostMacAddress Destination host MAC address
1704 */
Sangho Shineb083032014-09-22 16:11:34 -07001705 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1706 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
1707
1708 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001709
Sangho Shin463bee52014-09-29 15:14:43 -07001710 /**
1711 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001712 *
Sangho Shin463bee52014-09-29 15:14:43 -07001713 * @param ipv4
1714 */
1715 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001716 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001717 }
1718
1719 /**
1720 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001721 *
Sangho Shin463bee52014-09-29 15:14:43 -07001722 * @param destIp Destination address of packets to retrieve
1723 */
1724 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1725
1726 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1727
Sangho Shin61535402014-10-01 11:37:14 -07001728 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001729 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001730 int dest = ip.getDestinationAddress();
1731 IPv4Address ip1 = IPv4Address.of(dest);
1732 IPv4Address ip2 = IPv4Address.of(destIp);
1733 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001734 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001735 }
1736 }
1737 }
1738
1739 return bufferedPackets;
1740 }
1741
Sangho Shin15273b62014-10-16 22:22:05 -07001742
1743
Sangho Shin2f263692014-09-15 14:09:41 -07001744}