blob: 8f7bc48e6e8b7f44f67c165280a7fec36f0dadc9 [file] [log] [blame]
Sangho Shin2f263692014-09-15 14:09:41 -07001package net.onrc.onos.apps.segmentrouting;
2
Sangho Shin9c0f4c32014-09-26 16:02:38 -07003import java.io.IOException;
Sangho Shin1aa93542014-09-22 09:49:44 -07004import java.net.Inet4Address;
5import java.net.InetAddress;
6import java.net.UnknownHostException;
Sangho Shin2f263692014-09-15 14:09:41 -07007import java.util.ArrayList;
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07008import java.util.Arrays;
Sangho Shin2f263692014-09-15 14:09:41 -07009import java.util.Collection;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070010import java.util.HashMap;
Sangho Shin5be3e532014-10-03 17:20:58 -070011import java.util.HashSet;
Sangho Shin2f263692014-09-15 14:09:41 -070012import java.util.Iterator;
13import java.util.List;
14import java.util.Map;
Sangho Shin5be3e532014-10-03 17:20:58 -070015import java.util.Set;
Sangho Shin61535402014-10-01 11:37:14 -070016import java.util.concurrent.ConcurrentLinkedQueue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070017import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070018import java.util.concurrent.ScheduledExecutorService;
19import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070020import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070021
22import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070023import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070024import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070025import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070026import net.floodlightcontroller.core.module.FloodlightModuleContext;
27import net.floodlightcontroller.core.module.FloodlightModuleException;
28import net.floodlightcontroller.core.module.IFloodlightModule;
29import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070030import net.floodlightcontroller.core.util.SingletonTask;
Sangho Shin7330c032014-10-20 10:34:51 -070031import net.floodlightcontroller.restserver.IRestApiService;
Sangho Shin43cee112014-09-25 16:43:34 -070032import net.floodlightcontroller.threadpool.IThreadPoolService;
Sangho Shin15273b62014-10-16 22:22:05 -070033import net.floodlightcontroller.util.MACAddress;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070034import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070035import net.onrc.onos.api.packet.IPacketService;
Sangho Shinf65b4da2014-10-28 16:58:13 -070036import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicy.PolicyType;
37import net.onrc.onos.apps.segmentrouting.SegmentRoutingTunnel.TunnelRouteInfo;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -070038import net.onrc.onos.apps.segmentrouting.web.SegmentRoutingWebRoutable;
Srikanth Vavilapalli8a661e72014-10-27 15:40:22 -070039import net.onrc.onos.core.drivermanager.OFSwitchImplDellOSR;
Sangho Shin2f263692014-09-15 14:09:41 -070040import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070041import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070042import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070043import net.onrc.onos.core.matchaction.MatchAction;
44import net.onrc.onos.core.matchaction.MatchActionId;
45import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
Sangho Shin5be3e532014-10-03 17:20:58 -070046import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
Sangho Shin43cee112014-09-25 16:43:34 -070047import net.onrc.onos.core.matchaction.action.Action;
48import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
49import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
50import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
51import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
52import net.onrc.onos.core.matchaction.action.GroupAction;
Sangho Shin6d3c2f02014-10-22 10:10:55 -070053import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
54import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
55import net.onrc.onos.core.matchaction.action.OutputAction;
Sangho Shin43cee112014-09-25 16:43:34 -070056import net.onrc.onos.core.matchaction.action.PopMplsAction;
57import net.onrc.onos.core.matchaction.action.PushMplsAction;
Sangho Shine842cad2014-10-24 16:07:35 -070058import net.onrc.onos.core.matchaction.action.SetDAAction;
Sangho Shin43cee112014-09-25 16:43:34 -070059import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Sangho Shine842cad2014-10-24 16:07:35 -070060import net.onrc.onos.core.matchaction.action.SetSAAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070061import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070062import net.onrc.onos.core.matchaction.match.Match;
63import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin15273b62014-10-16 22:22:05 -070064import net.onrc.onos.core.matchaction.match.PacketMatch;
65import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
Sangho Shin2f263692014-09-15 14:09:41 -070066import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070067import net.onrc.onos.core.packet.Ethernet;
68import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070069import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070070import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinbce900e2014-10-07 17:13:23 -070071import net.onrc.onos.core.topology.Link;
Sangho Shinc8d2f592014-09-30 16:53:57 -070072import net.onrc.onos.core.topology.LinkData;
Sangho Shinbce900e2014-10-07 17:13:23 -070073import net.onrc.onos.core.topology.MastershipData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070074import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070075import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070076import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070077import net.onrc.onos.core.topology.Switch;
Sangho Shin5be3e532014-10-03 17:20:58 -070078import net.onrc.onos.core.topology.SwitchData;
Sangho Shin1aa93542014-09-22 09:49:44 -070079import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070080import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070081import net.onrc.onos.core.util.IPv4Net;
Sangho Shin6d3c2f02014-10-22 10:10:55 -070082import net.onrc.onos.core.util.PortNumber;
Sangho Shin43cee112014-09-25 16:43:34 -070083import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070084
Sangho Shin43cee112014-09-25 16:43:34 -070085import org.json.JSONArray;
86import org.json.JSONException;
Saurav Dasa962a692014-10-17 14:52:38 -070087import org.projectfloodlight.openflow.protocol.OFBarrierReply;
Saurav Dasbc594a42014-09-25 20:13:50 -070088import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070089import org.projectfloodlight.openflow.types.IPv4Address;
Sangho Shine842cad2014-10-24 16:07:35 -070090import org.projectfloodlight.openflow.types.MacAddress;
Sangho Shin2f263692014-09-15 14:09:41 -070091import org.slf4j.Logger;
92import org.slf4j.LoggerFactory;
93
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070094public class SegmentRoutingManager implements IFloodlightModule,
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -070095 ITopologyListener, IPacketListener, ISegmentRoutingService {
Sangho Shin2f263692014-09-15 14:09:41 -070096
97 private static final Logger log = LoggerFactory
98 .getLogger(SegmentRoutingManager.class);
Sangho Shin23f898d2014-10-13 16:54:00 -070099
Fahad Naeem Khan5b558f22014-10-16 10:35:20 -0700100 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700101 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700102 private MutableTopology mutableTopology;
Sangho Shin61535402014-10-01 11:37:14 -0700103 private ConcurrentLinkedQueue<IPv4> ipPacketQueue;
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700104 private IRestApiService restApi;
Sangho Shin2f263692014-09-15 14:09:41 -0700105 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -0700106 private ArpHandler arpHandler;
107 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700108 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -0700109 private IThreadPoolService threadPool;
110 private SingletonTask discoveryTask;
Sangho Shin23f898d2014-10-13 16:54:00 -0700111 private SingletonTask linkAddTask;
Sangho Shin15273b62014-10-16 22:22:05 -0700112 private SingletonTask testTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700113 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -0700114
Sangho Shinfbc572c2014-10-02 16:37:05 -0700115 private HashMap<Switch, ECMPShortestPathGraph> graphs;
Sangho Shin23f898d2014-10-13 16:54:00 -0700116 private HashMap<String, LinkData> linksDown;
117 private HashMap<String, LinkData> linksToAdd;
Sangho Shin5be3e532014-10-03 17:20:58 -0700118 private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
Sangho Shinf65b4da2014-10-28 16:58:13 -0700119 private HashMap<String, SegmentRoutingPolicy> policyTable;
120 private HashMap<String, SegmentRoutingTunnel> tunnelTable;
Sangho Shin6471d202014-10-23 10:59:36 -0700121 private HashMap<Integer, HashMap<Integer, List<Integer>>> adjacencySidTable;
Sangho Shinc0d0f752014-10-29 11:22:40 -0700122 private HashMap<String, HashMap<Integer, Integer>> adjcencyGroupIdTable;
Sangho Shin2404fec2014-10-29 10:43:05 -0700123
Sangho Shin5b8f5452014-10-20 11:46:01 -0700124
Sangho Shine842cad2014-10-24 16:07:35 -0700125 // Flag whether transit router supports ECMP or not
Srikanth Vavilapalli8a661e72014-10-27 15:40:22 -0700126 // private boolean supportTransitECMP = true;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700127
Sangho Shine842cad2014-10-24 16:07:35 -0700128 private int testMode = 0;
Sangho Shinbce900e2014-10-07 17:13:23 -0700129
130 private int numOfEvents = 0;
131 private int numOfEventProcess = 0;
132 private int numOfPopulation = 0;
Sangho Shin99918bd2014-10-08 15:52:35 -0700133 private long matchActionId = 0L;
Sangho Shin58182672014-10-21 13:23:38 -0700134
Sangho Shin23f898d2014-10-13 16:54:00 -0700135 private final int DELAY_TO_ADD_LINK = 10;
Sangho Shin15273b62014-10-16 22:22:05 -0700136 private final int MAX_NUM_LABELS = 3;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700137
Sangho Shin5b8f5452014-10-20 11:46:01 -0700138 private final int POLICY_ADD1 = 1;
139 private final int POLICY_ADD2 = 2;
140 private final int POLICY_REMOVE1 = 3;
141 private final int POLICY_REMOVE2 = 4;
Sangho Shin4b46bcd2014-10-20 15:48:47 -0700142 private final int TUNNEL_REMOVE1 = 5;
143 private final int TUNNEL_REMOVE2 = 6;
Sangho Shin5b8f5452014-10-20 11:46:01 -0700144
145
Sangho Shin7330c032014-10-20 10:34:51 -0700146 // ************************************
147 // IFloodlightModule implementation
148 // ************************************
149
Sangho Shin2f263692014-09-15 14:09:41 -0700150 @Override
151 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700152 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
153 l.add(ISegmentRoutingService.class);
154 return l;
Sangho Shin2f263692014-09-15 14:09:41 -0700155 }
156
157 @Override
158 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Srikanth Vavilapalli8c49db72014-10-20 13:35:08 -0700159 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
160 m.put(ISegmentRoutingService.class, this);
161 return m;
Sangho Shin2f263692014-09-15 14:09:41 -0700162 }
163
164 @Override
165 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
166 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
167
168 l.add(IFloodlightProviderService.class);
169 l.add(IConfigInfoService.class);
170 l.add(ITopologyService.class);
171 l.add(IPacketService.class);
172 l.add(IFlowPusherService.class);
173 l.add(ITopologyService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700174 l.add(IRestApiService.class);
Sangho Shin2f263692014-09-15 14:09:41 -0700175
176 return l;
177
178 }
179
180 @Override
181 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700182 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700183 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700184 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700185 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700186 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700187 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700188 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700189 mutableTopology = topologyService.getTopology();
Sangho Shin61535402014-10-01 11:37:14 -0700190 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700191 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin23f898d2014-10-13 16:54:00 -0700192 linksDown = new HashMap<String, LinkData>();
193 linksToAdd = new HashMap<String, LinkData>();
Sangho Shin5be3e532014-10-03 17:20:58 -0700194 topologyEventQueue = new ConcurrentLinkedQueue<TopologyEvents>();
Sangho Shin15273b62014-10-16 22:22:05 -0700195 packetService = context.getServiceImpl(IPacketService.class);
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700196 restApi = context.getServiceImpl(IRestApiService.class);
Sangho Shinf65b4da2014-10-28 16:58:13 -0700197 policyTable = new HashMap<String, SegmentRoutingPolicy>();
198 tunnelTable = new HashMap<String, SegmentRoutingTunnel>();
Sangho Shin6471d202014-10-23 10:59:36 -0700199 adjacencySidTable = new HashMap<Integer,HashMap<Integer, List<Integer>>>();
Sangho Shinc0d0f752014-10-29 11:22:40 -0700200 adjcencyGroupIdTable = new HashMap<String, HashMap<Integer, Integer>>();
Sangho Shin2f263692014-09-15 14:09:41 -0700201
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700202 packetService.registerPacketListener(this);
Sangho Shin15273b62014-10-16 22:22:05 -0700203 topologyService.addListener(this, false);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700204
Sangho Shin99918bd2014-10-08 15:52:35 -0700205
Sangho Shin2f263692014-09-15 14:09:41 -0700206 }
207
208 @Override
209 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700210 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Fahad Naeem Khan4444b952014-10-18 22:30:50 -0700211 restApi.addRestletRoutable(new SegmentRoutingWebRoutable());
Sangho Shin2f263692014-09-15 14:09:41 -0700212
Sangho Shinc8d2f592014-09-30 16:53:57 -0700213 discoveryTask = new SingletonTask(ses, new Runnable() {
214 @Override
215 public void run() {
Sangho Shin5be3e532014-10-03 17:20:58 -0700216 handleTopologyChangeEvents();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700217 }
218 });
Sangho Shin23f898d2014-10-13 16:54:00 -0700219
220 linkAddTask = new SingletonTask(ses, new Runnable() {
221 @Override
222 public void run() {
223 delayedAddLink();
224 }
225 });
226
Sangho Shin15273b62014-10-16 22:22:05 -0700227 testTask = new SingletonTask(ses, new Runnable() {
228 @Override
229 public void run() {
230 runTest();
231 }
232 });
233
Sangho Shin5b8f5452014-10-20 11:46:01 -0700234 testMode = POLICY_ADD1;
Sangho Shin69229fb2014-10-27 16:17:04 -0700235 //testTask.reschedule(20, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700236 }
237
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700238 @Override
239 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700240 if (payload.getEtherType() == Ethernet.TYPE_ARP)
241 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700242 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Sangho Shin7330c032014-10-20 10:34:51 -0700243 addPacketToPacketBuffer((IPv4) payload.getPayload());
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700244 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
245 icmpHandler.processPacketIn(sw, inPort, payload);
246 else
247 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700248 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700249 else {
250 log.debug("{}", payload.toString());
251 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700252 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700253
Sangho Shin2f263692014-09-15 14:09:41 -0700254
Sangho Shin7330c032014-10-20 10:34:51 -0700255 // ************************************
256 // Topology event handlers
257 // ************************************
Sangho Shineb083032014-09-22 16:11:34 -0700258
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700259 /**
260 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700261 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700262 * @param topologyEvents the generated Topology Events
263 * @see TopologyEvents
264 */
265 public void topologyEvents(TopologyEvents topologyEvents)
266 {
Sangho Shin5be3e532014-10-03 17:20:58 -0700267 topologyEventQueue.add(topologyEvents);
Sangho Shinbce900e2014-10-07 17:13:23 -0700268 discoveryTask.reschedule(100, TimeUnit.MILLISECONDS);
Sangho Shin5be3e532014-10-03 17:20:58 -0700269 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700270
Sangho Shin23f898d2014-10-13 16:54:00 -0700271 /**
272 * Process the multiple topology events with some delay (100MS at most for now)
273 *
274 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700275 private void handleTopologyChangeEvents() {
Sangho Shinbce900e2014-10-07 17:13:23 -0700276 numOfEventProcess ++;
277
Sangho Shin51625342014-10-17 09:30:48 -0700278 Collection<LinkData> linkEntriesAddedAll = new ArrayList<LinkData>();
279 Collection<PortData> portEntriesAddedAll = new ArrayList<PortData>();
280 Collection<PortData> portEntriesRemovedAll = new ArrayList<PortData>();
281 Collection<LinkData> linkEntriesRemovedAll = new ArrayList<LinkData>();
282 Collection<SwitchData> switchAddedAll = new ArrayList<SwitchData>();
283 Collection<SwitchData> switchRemovedAll = new ArrayList<SwitchData>();
284 Collection<MastershipData> mastershipRemovedAll = new ArrayList<MastershipData>();
Sangho Shinbce900e2014-10-07 17:13:23 -0700285
Sangho Shin5be3e532014-10-03 17:20:58 -0700286 while (!topologyEventQueue.isEmpty()) {
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700287 // We should handle the events in the order of when they happen
288 // TODO: We need to simulate the final results of multiple events
289 // and shoot only the final state.
290 // Ex: link s1-s2 down, link s1-s2 up --> Do nothing
291 // Ex: ink s1-s2 up, s1-p1,p2 down --> link s1-s2 down
Sangho Shin51625342014-10-17 09:30:48 -0700292
Sangho Shin5be3e532014-10-03 17:20:58 -0700293 TopologyEvents topologyEvents = topologyEventQueue.poll();
Sangho Shin51625342014-10-17 09:30:48 -0700294
295 Collection<LinkData> linkEntriesAdded = topologyEvents.getAddedLinkDataEntries();
296 Collection<PortData> portEntriesAdded = topologyEvents.getAddedPortDataEntries();
297 Collection<PortData> portEntriesRemoved = topologyEvents.getRemovedPortDataEntries();
298 Collection<LinkData> linkEntriesRemoved = topologyEvents.getRemovedLinkDataEntries();
299 Collection<SwitchData> switchAdded = topologyEvents.getAddedSwitchDataEntries();
300 Collection<SwitchData> switchRemoved = topologyEvents.getRemovedSwitchDataEntries();
301 Collection<MastershipData> mastershipRemoved = topologyEvents.getRemovedMastershipDataEntries();
302
303 linkEntriesAddedAll.addAll(linkEntriesAdded);
304 portEntriesAddedAll.addAll(portEntriesAdded);
305 portEntriesRemovedAll.addAll(portEntriesRemoved);
306 linkEntriesRemovedAll.addAll(linkEntriesRemoved);
307 switchAddedAll.addAll(switchAdded);
308 switchRemovedAll.addAll(switchRemoved);
309 mastershipRemovedAll.addAll(mastershipRemoved);
Sangho Shinbce900e2014-10-07 17:13:23 -0700310 numOfEvents++;
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700311
312 if (!portEntriesRemoved.isEmpty()) {
313 processPortRemoval(portEntriesRemoved);
314 }
315
316 if (!linkEntriesRemoved.isEmpty()) {
317 processLinkRemoval(linkEntriesRemoved);
318 }
319
320 if (!switchRemoved.isEmpty()) {
321 processSwitchRemoved(switchRemoved);
322 }
323
324 if (!mastershipRemoved.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700325 log.debug("Mastership is removed. Check if ports are down also.");
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700326 }
327
328 if (!linkEntriesAdded.isEmpty()) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700329 processLinkAdd(linkEntriesAdded, false);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700330 }
331
332 if (!portEntriesAdded.isEmpty()) {
333 processPortAdd(portEntriesAdded);
334 }
335
336 if (!switchAdded.isEmpty()) {
337 processSwitchAdd(switchAdded);
338 }
Sangho Shin51625342014-10-17 09:30:48 -0700339
Sangho Shinbce900e2014-10-07 17:13:23 -0700340 }
341
Sangho Shin23f898d2014-10-13 16:54:00 -0700342 // TODO: 100ms is enough to check both mastership removed events
343 // and the port removed events? What if the PORT_STATUS packets comes late?
Sangho Shin51625342014-10-17 09:30:48 -0700344 if (!mastershipRemovedAll.isEmpty()) {
345 if (portEntriesRemovedAll.isEmpty()) {
Saurav Das82e62972014-10-16 14:53:57 -0700346 log.debug("Just mastership is removed. Do not do anthing.");
Sangho Shin23f898d2014-10-13 16:54:00 -0700347 }
348 else {
349 HashMap<String, MastershipData> mastershipToRemove =
350 new HashMap<String, MastershipData>();
Sangho Shin51625342014-10-17 09:30:48 -0700351 for (MastershipData ms: mastershipRemovedAll) {
352 for (PortData port: portEntriesRemovedAll) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700353 // TODO: check ALL ports of the switch are dead ..
Sangho Shinc0d0f752014-10-29 11:22:40 -0700354 mastershipToRemove.put(ms.getDpid().toString(), ms);
355 log.debug("Swtich {} is really down.", ms.getDpid());
356 break;
Sangho Shin23f898d2014-10-13 16:54:00 -0700357 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700358 }
359 processMastershipRemoved(mastershipToRemove.values());
360 }
361 }
362
Sangho Shinbce900e2014-10-07 17:13:23 -0700363 log.debug("num events {}, num of process {}, "
364 + "num of Population {}", numOfEvents, numOfEventProcess,
365 numOfPopulation);
366 }
367
368 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700369 * Process the SwitchAdded events from topologyMananger.
370 * It does nothing. When a switch is added, then link will be added too.
371 * LinkAdded event will handle process all re-computation.
372 *
373 * @param switchAdded
374 */
375 private void processSwitchAdd(Collection<SwitchData> switchAdded) {
376
377 }
378
379 /**
Sangho Shinbce900e2014-10-07 17:13:23 -0700380 * Remove all ports connected to the switch removed
381 *
382 * @param mastershipRemoved master switch info removed
383 */
384 private void processMastershipRemoved(Collection<MastershipData>
385 mastershipRemoved) {
386 for (MastershipData mastership: mastershipRemoved) {
387 Switch sw = mutableTopology.getSwitch(mastership.getDpid());
388 for (Link link: sw.getOutgoingLinks()) {
389 Port dstPort = link.getDstPort();
390 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800391 dstPort.getDpid().value());
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700392 if (dstSw != null) {
393 dstSw.removePortFromGroups(dstPort.getNumber());
Sangho Shin2051d562014-11-05 09:54:42 -0800394 log.debug("MasterSwitch {} is gone: remove port {}",
395 sw.getDpid(), dstPort);
Sangho Shinc1b8dea2014-10-13 12:03:28 -0700396 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700397 }
Sangho Shinc0d0f752014-10-29 11:22:40 -0700398 // Flush the groupId table for adjacencySid;
399 log.debug("Flush the AdjacencyGroupId table for sw {}", sw);
400 adjcencyGroupIdTable.remove(sw.getDpid().toString());
Sangho Shin61535402014-10-01 11:37:14 -0700401 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700402
403 linksToAdd.clear();
404 linksDown.clear();
Sangho Shin61535402014-10-01 11:37:14 -0700405 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700406
Sangho Shinbce900e2014-10-07 17:13:23 -0700407 /**
408 * Remove all ports connected to the switch removed
409 *
410 * @param switchRemoved Switch removed
411 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700412 private void processSwitchRemoved(Collection<SwitchData> switchRemoved) {
Sangho Shin23f898d2014-10-13 16:54:00 -0700413 log.debug("SwitchRemoved event occurred !!!");
Sangho Shin5be3e532014-10-03 17:20:58 -0700414 }
415
Sangho Shin61535402014-10-01 11:37:14 -0700416 /**
Sangho Shin99918bd2014-10-08 15:52:35 -0700417 * Report ports added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700418 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700419 * @param portEntries
420 */
421 private void processPortAdd(Collection<PortData> portEntries) {
Sangho Shin99918bd2014-10-08 15:52:35 -0700422 // TODO: do we need to add ports with delay?
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700423 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700424 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700425
Sangho Shinfbc572c2014-10-02 16:37:05 -0700426 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800427 port.getDpid().value());
Sangho Shin815af0c2014-10-10 13:05:45 -0700428 if (sw != null) {
Sangho Shin721ca042014-10-09 13:03:40 -0700429 sw.addPortToGroups(port.getPortNumber());
Sangho Shin15273b62014-10-16 22:22:05 -0700430 //log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin815af0c2014-10-10 13:05:45 -0700431 }
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700432 }
433 }
434
435 /**
436 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shin23f898d2014-10-13 16:54:00 -0700437 * If the link to add was removed before, then we just schedule the add link
438 * event and do not recompute the path now.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700439 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700440 * @param linkEntries
441 */
Sangho Shin23f898d2014-10-13 16:54:00 -0700442 private void processLinkAdd(Collection<LinkData> linkEntries, boolean delayed) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700443
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700444 for (LinkData link : linkEntries) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700445
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700446 SwitchPort srcPort = link.getSrc();
447 SwitchPort dstPort = link.getDst();
448
Sangho Shin23f898d2014-10-13 16:54:00 -0700449 String key = srcPort.getDpid().toString() +
450 dstPort.getDpid().toString();
451 if (!delayed) {
452 if (linksDown.containsKey(key)) {
453 linksToAdd.put(key, link);
454 linksDown.remove(key);
455 linkAddTask.reschedule(DELAY_TO_ADD_LINK, TimeUnit.SECONDS);
456 log.debug("Add link {} with 5 sec delay", link);
457 // TODO: What if we have multiple events of add link:
458 // one is new link add, the other one is link up for
459 // broken link? ECMPSPG function cannot deal with it for now
460 return;
461 }
462 }
463 else {
464 if (linksDown.containsKey(key)) {
465 linksToAdd.remove(key);
466 log.debug("Do not add the link {}: it is down again!", link);
467 return;
468 }
469 }
470
Sangho Shinfbc572c2014-10-02 16:37:05 -0700471 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800472 srcPort.getDpid().value());
Sangho Shinfbc572c2014-10-02 16:37:05 -0700473 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800474 dstPort.getDpid().value());
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700475
Sangho Shin815af0c2014-10-10 13:05:45 -0700476 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700477 continue;
478
479 srcSw.addPortToGroups(srcPort.getPortNumber());
480 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin5be3e532014-10-03 17:20:58 -0700481
Sangho Shin15273b62014-10-16 22:22:05 -0700482 //log.debug("Add a link port {} to switch {} to add link {}", srcPort, srcSw,
483 // link);
484 //log.debug("Add a link port {} to switch {} to add link {}", dstPort, dstSw,
485 // link);
Sangho Shin815af0c2014-10-10 13:05:45 -0700486
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700487 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700488 populateEcmpRoutingRules(false);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700489 }
490
491 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700492 * Check if all links are gone b/w the two switches. If all links are gone,
493 * then we need to recalculate the path. Otherwise, just report link failure
Sangho Shin370e17b2014-10-27 11:39:08 -0700494 * to the driver. IF the switches do not support ECMP in transit routers and
495 * the link removed is between transit routers, then just recompute the path
496 * regardless of ECMP.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700497 *
Sangho Shin61535402014-10-01 11:37:14 -0700498 * @param linkEntries
499 */
500 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700501 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700502 SwitchPort srcPort = link.getSrc();
503 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700504
Sangho Shinfbc572c2014-10-02 16:37:05 -0700505 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800506 srcPort.getDpid().value());
Sangho Shinfbc572c2014-10-02 16:37:05 -0700507 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800508 dstPort.getDpid().value());
Sangho Shin815af0c2014-10-10 13:05:45 -0700509 if ((srcSw == null) || (dstSw == null))
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700510 /* If this link is not between two switches, ignore it */
511 continue;
Sangho Shin23f898d2014-10-13 16:54:00 -0700512
Srikanth Vavilapallibb47e782014-10-09 18:16:35 -0700513 srcSw.removePortFromGroups(srcPort.getPortNumber());
514 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700515 log.debug("Remove port {} from switch {}", srcPort, srcSw);
516 log.debug("Remove port {} from switch {}", dstPort, dstSw);
517
Sangho Shinf66aa262014-10-27 16:03:42 -0700518 if ((srcSw instanceof OFSwitchImplDellOSR &&
519 dstSw instanceof OFSwitchImplDellOSR) &&
Sangho Shin370e17b2014-10-27 11:39:08 -0700520 isTransitRouter(mutableTopology.getSwitch(srcPort.getDpid())) &&
521 isTransitRouter(mutableTopology.getSwitch(dstPort.getDpid()))) {
522 populateEcmpRoutingRules(false);
523 }
524 else {
525 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
526 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
527 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
528 dstPort.getDpid());
529 log.debug("All paths will recomputed regardless of the rest "
530 + "of the event");
531 populateEcmpRoutingRules(false);
532 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700533 }
Sangho Shin23f898d2014-10-13 16:54:00 -0700534
535 String key = link.getSrc().getDpid().toString()+
536 link.getDst().getDpid().toString();
537 if (!linksDown.containsKey(key)) {
538 linksDown.put(key, link);
539 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700540 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700541
Sangho Shin61535402014-10-01 11:37:14 -0700542 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700543
Sangho Shin61535402014-10-01 11:37:14 -0700544 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700545 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700546 *
Sangho Shin61535402014-10-01 11:37:14 -0700547 * @param portEntries
548 */
549 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700550 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700551 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700552
Sangho Shinfbc572c2014-10-02 16:37:05 -0700553 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800554 port.getDpid().value());
Sangho Shin815af0c2014-10-10 13:05:45 -0700555 if (sw != null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700556 sw.removePortFromGroups(port.getPortNumber());
Sangho Shin815af0c2014-10-10 13:05:45 -0700557 log.debug("Remove port {} from switch {}", port, dpid);
558 }
Sangho Shin61535402014-10-01 11:37:14 -0700559 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700560 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700561
562 /**
Sangho Shin7330c032014-10-20 10:34:51 -0700563 * Add the link immediately
564 * The function is scheduled when link add event happens and called
565 * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
566 */
567 private void delayedAddLink() {
568
569 processLinkAdd(linksToAdd.values(), true);
570
571 }
572
573
574 // ************************************
575 // ECMP shorted path routing functions
576 // ************************************
577
578 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700579 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700580 *
Sangho Shin99918bd2014-10-08 15:52:35 -0700581 * @param modified if true, it "modifies" the rules
Sangho Shin1aa93542014-09-22 09:49:44 -0700582 */
Sangho Shin5be3e532014-10-03 17:20:58 -0700583 private void populateEcmpRoutingRules(boolean modified) {
584 graphs.clear();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700585 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700586 for (Switch sw : switches) {
587 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700588 graphs.put(sw, ecmpSPG);
589 //log.debug("ECMPShortestPathGraph is computed for switch {}",
590 // HexString.toHexString(sw.getDpid().value()));
Sangho Shin5be3e532014-10-03 17:20:58 -0700591 populateEcmpRoutingRulesForPath(sw, ecmpSPG, modified);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700592
593 // Set adjacency routing rule for all switches
594 try {
595 populateAdjacencyncyRule(sw);
596 } catch (JSONException e) {
597 // TODO Auto-generated catch block
598 e.printStackTrace();
599 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700600 }
Sangho Shinbce900e2014-10-07 17:13:23 -0700601 numOfPopulation++;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700602 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700603
Sangho Shin204b9972014-10-22 11:08:10 -0700604 /**
605 * populate the MPLS rules to handle Adjacency IDs
606 *
607 * @param sw Switch
608 * @throws JSONException
609 */
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700610 private void populateAdjacencyncyRule(Switch sw) throws JSONException {
611 String adjInfo = sw.getStringAttribute("adjacencySids");
Sangho Shin204b9972014-10-22 11:08:10 -0700612 String nodeSidStr = sw.getStringAttribute("nodeSid");
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700613 String srcMac = sw.getStringAttribute("routerMac");
Sangho Shin204b9972014-10-22 11:08:10 -0700614 String autoAdjInfo = sw.getStringAttribute("autogenAdjSids");
615
Sangho Shinced05b62014-10-22 11:23:14 -0700616 if (autoAdjInfo == null || srcMac == null || nodeSidStr == null)
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700617 return;
618
Sangho Shinced05b62014-10-22 11:23:14 -0700619 // parse adjacency Id
Sangho Shincfef3922014-10-22 12:04:16 -0700620 HashMap<Integer, List<Integer>> adjacencyInfo = null;
Sangho Shinced05b62014-10-22 11:23:14 -0700621 if (adjInfo != null) {
Sangho Shincfef3922014-10-22 12:04:16 -0700622 adjacencyInfo = parseAdjacencySidInfo(adjInfo);
Sangho Shinced05b62014-10-22 11:23:14 -0700623 }
Sangho Shincfef3922014-10-22 12:04:16 -0700624 // parse auto generated adjacency Id
625 adjacencyInfo.putAll(parseAdjacencySidInfo(autoAdjInfo));
Sangho Shinced05b62014-10-22 11:23:14 -0700626
Sangho Shin6471d202014-10-23 10:59:36 -0700627 adjacencySidTable.put(Integer.parseInt(nodeSidStr), adjacencyInfo);
Sangho Shin204b9972014-10-22 11:08:10 -0700628
Sangho Shin6471d202014-10-23 10:59:36 -0700629 for (Integer adjId: adjacencyInfo.keySet()) {
630 List<Integer> ports = adjacencyInfo.get(adjId);
631 if (ports.size() == 1) {
632 setAdjacencyRuleOfOutput(sw, adjId, srcMac, ports.get(0));
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700633 }
634 else {
Sangho Shin6471d202014-10-23 10:59:36 -0700635 setAdjacencyRuleOfGroup(sw, adjId, ports);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700636 }
Sangho Shin6471d202014-10-23 10:59:36 -0700637 }
638 }
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700639
Sangho Shin6471d202014-10-23 10:59:36 -0700640 /**
641 * Set Adjacency Rule to MPLS table for adjacency Ids attached to multiple
642 * ports
643 *
644 * @param sw Switch
645 * @param adjId Adjacency ID
646 * @param ports List of ports assigned to the Adjacency ID
647 */
Sangho Shin2051d562014-11-05 09:54:42 -0800648 private void setAdjacencyRuleOfGroup(Switch sw, Integer adjId,
649 List<Integer> ports) {
Sangho Shin6471d202014-10-23 10:59:36 -0700650
651 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800652 sw.getDpid().value());
Sangho Shin6471d202014-10-23 10:59:36 -0700653
Sangho Shin2404fec2014-10-29 10:43:05 -0700654 Integer groupId = -1;
Sangho Shin6471d202014-10-23 10:59:36 -0700655 if (sw13 != null) {
656 List<PortNumber> portList = new ArrayList<PortNumber>();
Sangho Shin2404fec2014-10-29 10:43:05 -0700657 int key = 0;
658 for (Integer port: ports) {
659 PortNumber portNumber = PortNumber.uint32(port);
660 portList.add(portNumber);
661 key += portNumber.hashCode();
662 }
663 key += sw.getDpid().hashCode();
Sangho Shinc0d0f752014-10-29 11:22:40 -0700664
665 HashMap<Integer, Integer> adjGroupIdMap =
666 adjcencyGroupIdTable.get(sw.getDpid().toString());
667 if (adjGroupIdMap != null) {
668 groupId = adjGroupIdMap.get(key);
669 if (groupId == null) {
670 groupId = sw13.createGroup(new ArrayList<Integer>(),
671 portList);
672 if (groupId < 0) {
673 log.debug("Failed to create a group at driver for "
674 + "adj ID {}", adjId);
675 return;
676 }
677 else {
678 adjGroupIdMap.put(key, groupId);
679 }
680 }
681 }
682 else {
Sangho Shin2404fec2014-10-29 10:43:05 -0700683 groupId = sw13.createGroup(new ArrayList<Integer>(), portList);
684 if (groupId < 0) {
Sangho Shinc0d0f752014-10-29 11:22:40 -0700685 log.debug("Failed to create a group at driver for adj ID {}",
686 adjId);
Sangho Shin2404fec2014-10-29 10:43:05 -0700687 return;
688 }
689 else {
Sangho Shinc0d0f752014-10-29 11:22:40 -0700690 adjGroupIdMap = new HashMap<Integer, Integer>();
691 adjGroupIdMap.put(key, groupId);
692 adjcencyGroupIdTable.put(sw.getDpid().toString(),
693 adjGroupIdMap);
Sangho Shin2404fec2014-10-29 10:43:05 -0700694 }
695 }
Sangho Shin6471d202014-10-23 10:59:36 -0700696 }
697
698 pushAdjRule(sw, adjId, null, null, groupId, true);
699 pushAdjRule(sw, adjId, null, null, groupId, false);
700 }
701
702 /**
703 * Set Adjacency Rule to MPLS table for adjacency Ids attached to single port
704 *
705 * @param sw Switch
706 * @param adjId Adjacency ID
707 * @param ports List of ports assigned to the Adjacency ID
708 */
709 private void setAdjacencyRuleOfOutput(Switch sw, Integer adjId, String srcMac, Integer portNo) {
710
711 Dpid dstDpid = null;
712 for (Link link: sw.getOutgoingLinks()) {
713 if (link.getSrcPort().getPortNumber().value() == portNo) {
714 dstDpid = link.getDstPort().getDpid();
715 break;
716 }
717 }
718 if (dstDpid == null) {
719 log.debug("Cannot find the destination switch for the adjacency ID {}", adjId);
720 return;
721 }
722 Switch dstSw = mutableTopology.getSwitch(dstDpid);
723 String dstMac = null;
724 if (dstSw == null) {
725 log.debug("Cannot find SW {}", dstDpid.toString());
726 return;
727 }
728 else {
729 dstMac = dstSw.getStringAttribute("routerMac");
730 }
731
732 pushAdjRule(sw, adjId, srcMac, dstMac, portNo, true); // BoS = 1
733 pushAdjRule(sw, adjId, srcMac, dstMac, portNo, false); // BoS = 0
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700734
735 }
736
Sangho Shin204b9972014-10-22 11:08:10 -0700737 /**
738 * Push the MPLS rule for Adjacency ID
739 *
740 * @param sw Switch to push the rule
741 * @param id Adjacency ID
742 * @param srcMac source MAC address
743 * @param dstMac destination MAC address
744 * @param portNo port number assigned to the ID
745 * @param bos BoS option
746 */
Sangho Shin6471d202014-10-23 10:59:36 -0700747 private void pushAdjRule(Switch sw, int id, String srcMac, String dstMac,
748 int num, boolean bos) {
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700749
750 MplsMatch mplsMatch = new MplsMatch(id, bos);
751 List<Action> actions = new ArrayList<Action>();
752
Sangho Shin63a01402014-10-29 10:00:00 -0700753 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
754 actions.add(copyTtlInAction);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700755 if (bos) {
756 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700757 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700758 actions.add(popAction);
759 actions.add(decNwTtlAction);
760 }
761 else {
762 PopMplsAction popAction = new PopMplsAction(EthType.MPLS_UNICAST);
763 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
764 actions.add(popAction);
765 actions.add(decMplsTtlAction);
766 }
767
Sangho Shin6471d202014-10-23 10:59:36 -0700768 // Output action
769 if (srcMac != null && dstMac != null) {
Sangho Shind6d8a7e2014-10-28 14:51:03 -0700770 ModifyDstMacAction setDstAction = new ModifyDstMacAction(MACAddress.valueOf(dstMac));
771 ModifySrcMacAction setSrcAction = new ModifySrcMacAction(MACAddress.valueOf(srcMac));
Sangho Shin6471d202014-10-23 10:59:36 -0700772 OutputAction outportAction = new OutputAction(PortNumber.uint32(num));
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700773
Sangho Shin6471d202014-10-23 10:59:36 -0700774 actions.add(setDstAction);
775 actions.add(setSrcAction);
776 actions.add(outportAction);
777 }
778 // Group Action
779 else {
780 GroupAction groupAction = new GroupAction();
781 groupAction.setGroupId(num);
782 actions.add(groupAction);
783 }
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700784
785 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
786 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
787 Operator operator = Operator.ADD;
788 MatchActionOperationEntry maEntry =
789 new MatchActionOperationEntry(operator, matchAction);
790
791 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800792 sw.getDpid().value());
Sangho Shin6d3c2f02014-10-22 10:10:55 -0700793
794 if (sw13 != null) {
795 try {
796 //printMatchActionOperationEntry(sw, maEntry);
797 sw13.pushFlow(maEntry);
798 } catch (IOException e) {
799 e.printStackTrace();
800 }
801 }
802 }
803
Sangho Shin99918bd2014-10-08 15:52:35 -0700804 /**
805 * populate routing rules to forward packets from the switch given to
806 * all other switches.
807 *
808 * @param sw source switch
809 * @param ecmpSPG shortest path from the the source switch to all others
810 * @param modified modification flag
811 */
Sangho Shinfbc572c2014-10-02 16:37:05 -0700812 private void populateEcmpRoutingRulesForPath(Switch sw,
Sangho Shin5be3e532014-10-03 17:20:58 -0700813 ECMPShortestPathGraph ecmpSPG, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700814
Sangho Shinfbc572c2014-10-02 16:37:05 -0700815 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
816 ecmpSPG.getAllLearnedSwitchesAndVia();
Sangho Shin81d5e8c2014-10-30 23:48:19 -0700817 List<OFBarrierReplyFuture> replies = new ArrayList<OFBarrierReplyFuture>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700818 for (Integer itrIdx : switchVia.keySet()) {
819 //log.debug("ECMPShortestPathGraph:Switches learned in "
820 // + "Iteration{} from switch {}:",
821 // itrIdx,
822 // HexString.toHexString(sw.getDpid().value()));
823 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
824 switchVia.get(itrIdx);
825 for (Switch targetSw : swViaMap.keySet()) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700826 //log.debug("ECMPShortestPathGraph:****switch {} via:",
827 // HexString.toHexString(targetSw.getDpid().value()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700828 String destSw = sw.getDpid().toString();
829 List<String> fwdToSw = new ArrayList<String>();
830
Sangho Shinfbc572c2014-10-02 16:37:05 -0700831 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
Sangho Shin5be3e532014-10-03 17:20:58 -0700832 //log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700833 if (via.isEmpty()) {
834 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700835 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700836 else {
837 fwdToSw.add(via.get(0).toString());
838 }
Sangho Shin43cee112014-09-25 16:43:34 -0700839 }
Sangho Shin5be3e532014-10-03 17:20:58 -0700840 setRoutingRule(targetSw, destSw, fwdToSw, modified);
Sangho Shin8a59fde2014-10-29 23:49:18 -0700841 // Send Barrier Message and make sure all rules are set
842 // before we set the rules to next routers
Sangho Shin81d5e8c2014-10-30 23:48:19 -0700843 OFBarrierReplyFuture replyFuture = sendBarrier(targetSw);
844 if (replyFuture != null)
845 replies.add(replyFuture);
846 else {
847 log.warn("Failed to send a Barrier message to sw {}",
848 targetSw);
849 }
850 }
851 if (!checkBarrierReplies(replies)) {
852 log.warn("Failed to get Barrier replis");
853 return;
Sangho Shinfbc572c2014-10-02 16:37:05 -0700854 }
855 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700856 }
857
Sangho Shinfbc572c2014-10-02 16:37:05 -0700858 /**
859 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700860 * Set routing rules in targetSw {forward packets to fwdToSw switches in
861 * order to send packets to destSw} - If the target switch is an edge router
862 * and final destnation switch is also an edge router, then set IP
863 * forwarding rules to subnets - If only the target switch is an edge
864 * router, then set IP forwarding rule to the transit router loopback IP
865 * address - If the target is a transit router, then just set the MPLS
866 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700867 *
Sangho Shin43cee112014-09-25 16:43:34 -0700868 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700869 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700870 * @param fwdToSw next hop switches
871 */
Sangho Shin99918bd2014-10-08 15:52:35 -0700872 private void setRoutingRule(Switch targetSw, String destSw,
873 List<String> fwdToSw, boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700874
Sangho Shin43cee112014-09-25 16:43:34 -0700875 if (fwdToSw.isEmpty()) {
876 fwdToSw.add(destSw);
877 }
878
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700879 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700880 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
881 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700882 // We assume that there is at least one transit router b/w edge
883 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700884 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
885 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700886 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Sangho Shin5be3e532014-10-03 17:20:58 -0700887 , fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700888
Sangho Shin43cee112014-09-25 16:43:34 -0700889 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700890 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
891 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700892 // Edge router can be a transit router
893 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700894 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700895 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700896 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700897 // We assume that there is at least one transit router b/w edge
898 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700899 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
900 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700901 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw,
902 null, modified);
Sangho Shin721ca042014-10-09 13:03:40 -0700903 // Edge router can be a transit router
904 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700905 }
906 // if it is a transit router, then set rules in the MPLS table
907 else {
Sangho Shin5be3e532014-10-03 17:20:58 -0700908 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw, modified);
Sangho Shin43cee112014-09-25 16:43:34 -0700909 }
910
911 }
912
Sangho Shinfbc572c2014-10-02 16:37:05 -0700913 /**
914 * Set IP forwarding rule to the gateway of each subnet of switches
915 *
916 * @param targetSw Switch to set rules
917 * @param subnets subnet information
918 * @param mplsLabel destination MPLS label
919 * @param fwdToSw router to forward packets to
920 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700921 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
Sangho Shin5be3e532014-10-03 17:20:58 -0700922 String mplsLabel, List<String> fwdToSw, boolean modified) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700923
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700924 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700925 new ArrayList<MatchActionOperationEntry>();
926
927 try {
928 JSONArray arry = new JSONArray(subnets);
929 for (int i = 0; i < arry.length(); i++) {
930 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
Sangho Shin5be3e532014-10-03 17:20:58 -0700931 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries,
932 modified);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700933 }
934 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700935 e.printStackTrace();
936 }
937
938 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700939 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -0800940 targetSw.getDpid().value());
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700941
Sangho Shin721ca042014-10-09 13:03:40 -0700942 if (sw13 != null) {
943 try {
944 sw13.pushFlows(entries);
945 } catch (IOException e) {
946 e.printStackTrace();
947 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700948 }
949 }
950
951 }
952
Sangho Shin43cee112014-09-25 16:43:34 -0700953 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700954 * Set IP forwarding rule - If the destination is the next hop, then do not
955 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
956 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700957 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700958 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700959 * @param subnetIp Match IP address
960 * @param mplsLabel MPLS label of final destination router
961 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700962 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700963 */
964 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin5be3e532014-10-03 17:20:58 -0700965 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries,
966 boolean modified) {
Sangho Shin43cee112014-09-25 16:43:34 -0700967
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700968 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700969 List<Action> actions = new ArrayList<>();
Sangho Shin721ca042014-10-09 13:03:40 -0700970 GroupAction groupAction = new GroupAction();
Sangho Shin43cee112014-09-25 16:43:34 -0700971
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700972 // If destination SW is the same as the fwd SW, then do not push MPLS
973 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700974 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700975 PushMplsAction pushMplsAction = new PushMplsAction();
976 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
977 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700978 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700979
Sangho Shin62ce5c12014-10-08 16:24:40 -0700980 //actions.add(pushMplsAction);
981 //actions.add(copyTtlOutAction);
982 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -0700983 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -0700984 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin43cee112014-09-25 16:43:34 -0700985 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700986 else {
987 String fwdToSw = fwdToSws.get(0);
988 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
989 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
990 actions.add(decTtlAction);
991 }
992 else {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700993 SetMplsIdAction setIdAction = new SetMplsIdAction(
994 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700995 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700996 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700997
Sangho Shin62ce5c12014-10-08 16:24:40 -0700998 //actions.add(pushMplsAction);
999 //actions.add(copyTtlOutAction);
1000 //actions.add(decMplsTtlAction);
Saurav Das82e62972014-10-16 14:53:57 -07001001 // actions.add(setIdAction);
Sangho Shin721ca042014-10-09 13:03:40 -07001002 groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001003 }
1004 }
Sangho Shin43cee112014-09-25 16:43:34 -07001005
Sangho Shin43cee112014-09-25 16:43:34 -07001006 for (String fwdSw : fwdToSws) {
1007 groupAction.addSwitch(new Dpid(fwdSw));
1008 }
1009 actions.add(groupAction);
1010
Sangho Shin99918bd2014-10-08 15:52:35 -07001011 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001012 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -07001013
Sangho Shin5be3e532014-10-03 17:20:58 -07001014 Operator operator = null;
1015 if (modified)
1016 operator = Operator.MODIFY;
1017 else
1018 operator = Operator.ADD;
1019
Sangho Shin43cee112014-09-25 16:43:34 -07001020 MatchActionOperationEntry maEntry =
Sangho Shin5be3e532014-10-03 17:20:58 -07001021 new MatchActionOperationEntry(operator, matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -07001022
Sangho Shin2051d562014-11-05 09:54:42 -08001023 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(sw.getDpid().value());
1024 // getSwId(sw.getDpid().toString()));
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001025
Sangho Shin5be3e532014-10-03 17:20:58 -07001026 if (sw13 != null) {
1027 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001028 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shin5be3e532014-10-03 17:20:58 -07001029 if (entries != null)
1030 entries.add(maEntry);
1031 else
1032 sw13.pushFlow(maEntry);
1033 } catch (IOException e) {
1034 e.printStackTrace();
1035 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001036 }
1037
Sangho Shin43cee112014-09-25 16:43:34 -07001038 }
1039
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001040 /**
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001041 * Set MPLS forwarding rules to MPLS table
1042 * </p>
1043 * If the destination is the same as the next hop to forward packets then,
1044 * pop the MPLS label according to PHP rule. Here, if BoS is set, then
1045 * copy TTL In and decrement NW TTL. Otherwise, it just decrement the MPLS
1046 * TTL of the another MPLS header.
1047 * If the next hop is not the destination, just forward packets to next
1048 * hops using Group action.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001049 *
Sangho Shin204b9972014-10-22 11:08:10 -07001050 * TODO: refactoring required
1051 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001052 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -07001053 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001054 * @param fwdSws next hop switches
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001055 * */
Sangho Shin5be3e532014-10-03 17:20:58 -07001056 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws,
1057 boolean modified) {
Sangho Shin463bee52014-09-29 15:14:43 -07001058
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001059 if (fwdSws.isEmpty())
1060 return;
Sangho Shin43cee112014-09-25 16:43:34 -07001061
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001062 Collection<MatchActionOperationEntry> maEntries =
1063 new ArrayList<MatchActionOperationEntry>();
1064 String fwdSw1 = fwdSws.get(0);
Sangho Shin43cee112014-09-25 16:43:34 -07001065
Sangho Shine842cad2014-10-24 16:07:35 -07001066 //If the next hop is the destination router, do PHP
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001067 if (fwdSws.size() == 1 && mplsLabel.equals(getMplsLabel(fwdSw1))) {
Sangho Shine842cad2014-10-24 16:07:35 -07001068 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, true, true));
1069 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, true, false));
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001070 }
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001071 else {
Sangho Shine842cad2014-10-24 16:07:35 -07001072 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, false, true));
1073 maEntries.add(buildMAEntry(sw, mplsLabel, fwdSws, false, false));
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001074 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001075 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -08001076 sw.getDpid().value());
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001077
Sangho Shin5be3e532014-10-03 17:20:58 -07001078 if (sw13 != null) {
1079 try {
Sangho Shinbce900e2014-10-07 17:13:23 -07001080 //printMatchActionOperationEntry(sw, maEntry);
Sangho Shinc1b8dea2014-10-13 12:03:28 -07001081 sw13.pushFlows(maEntries);
Sangho Shin5be3e532014-10-03 17:20:58 -07001082 } catch (IOException e) {
1083 e.printStackTrace();
1084 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001085 }
Sangho Shin43cee112014-09-25 16:43:34 -07001086 }
1087
Sangho Shin7330c032014-10-20 10:34:51 -07001088
1089 // ************************************
1090 // Policy routing classes and functions
1091 // ************************************
1092
Fahad Naeem Khan1e712ad2014-10-27 16:48:07 -07001093 /**
Sangho Shin81655442014-10-20 14:22:46 -07001094 * Return the Tunnel table
1095 *
1096 * @return collection of TunnelInfo
1097 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001098 public Collection<SegmentRoutingTunnel> getTunnelTable() {
Fahad Naeem Khana40f9b62014-10-20 18:33:45 -07001099 return this.tunnelTable.values();
Sangho Shin81655442014-10-20 14:22:46 -07001100 }
Sangho Shin204b9972014-10-22 11:08:10 -07001101
Sangho Shinbe3c3612014-10-30 14:20:36 -07001102 /**
1103 * Return the Policy Table
1104 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001105 public Collection<SegmentRoutingPolicy> getPoclicyTable() {
Fahad Naeem Khan12fa63a2014-10-21 17:01:27 -07001106 return this.policyTable.values();
1107 }
Sangho Shin81655442014-10-20 14:22:46 -07001108
1109 /**
Sangho Shin5671cbb2014-10-20 22:35:41 -07001110 * Return router DPIDs for the tunnel
1111 *
1112 * @param tid tunnel ID
1113 * @return List of DPID
1114 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001115 public SegmentRoutingTunnel getTunnelInfo(String tid) {
1116 return tunnelTable.get(tid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001117 }
1118
1119 /**
1120 * Get the first group ID for the tunnel for specific source router
1121 * If Segment Stitching was required to create the tunnel, there are
Sangho Shinf65b4da2014-10-28 16:58:13 -07001122 * multiple source routers.
Sangho Shin5671cbb2014-10-20 22:35:41 -07001123 *
1124 * @param tunnelId ID for the tunnel
1125 * @param dpid source router DPID
1126 * @return the first group ID of the tunnel
1127 */
1128 public int getTunnelGroupId(String tunnelId, String dpid) {
Sangho Shinf65b4da2014-10-28 16:58:13 -07001129 SegmentRoutingTunnel tunnel = tunnelTable.get(tunnelId);
1130 for (TunnelRouteInfo routeInfo: tunnel.getRoutes()) {
Sangho Shin6471d202014-10-23 10:59:36 -07001131 String tunnelSrcDpid = routeInfo.getSrcSwDpid();
1132 if (tunnelSrcDpid.equals(dpid))
1133 return routeInfo.getGroupId();
1134 }
Sangho Shin5671cbb2014-10-20 22:35:41 -07001135
Sangho Shin6471d202014-10-23 10:59:36 -07001136 return -1;
Sangho Shin5671cbb2014-10-20 22:35:41 -07001137 }
1138
1139 /**
Sangho Shin15273b62014-10-16 22:22:05 -07001140 * Create a tunnel for policy routing
1141 * It delivers the node IDs of tunnels to driver.
1142 * Split the node IDs if number of IDs exceeds the limit for stitching.
1143 *
1144 * @param tunnelId Node IDs for the tunnel
1145 * @param Ids tunnel ID
1146 */
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001147 public boolean createTunnel(String tunnelId, List<Integer> labelIds) {
Sangho Shin15273b62014-10-16 22:22:05 -07001148
Sangho Shinf65b4da2014-10-28 16:58:13 -07001149 SegmentRoutingTunnel srTunnel =
1150 new SegmentRoutingTunnel(this, tunnelId, labelIds);
1151 if (srTunnel.createTunnel()) {
1152 tunnelTable.put(tunnelId, srTunnel);
1153 return true;
1154 }
1155 else {
Sangho Shin15273b62014-10-16 22:22:05 -07001156 return false;
1157 }
Sangho Shin15273b62014-10-16 22:22:05 -07001158 }
1159
Sangho Shinbe3c3612014-10-30 14:20:36 -07001160 /**
1161 * Create a policy
1162 * TODO: To be removed
1163 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001164 @Override
1165 public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
1166 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
1167 Short srcPort, Short dstPort, int priority, String tid) {
Sangho Shin6471d202014-10-23 10:59:36 -07001168
Sangho Shinf65b4da2014-10-28 16:58:13 -07001169 return createPolicy(pid, srcMac, dstMac, etherType, srcIp, dstIp, ipProto,
1170 srcPort, dstPort, priority, tid, PolicyType.TUNNEL_FLOW);
Sangho Shin6471d202014-10-23 10:59:36 -07001171 }
1172
Sangho Shin15273b62014-10-16 22:22:05 -07001173 /**
Sangho Shinbe3c3612014-10-30 14:20:36 -07001174 * Create a policy
Sangho Shin15273b62014-10-16 22:22:05 -07001175 *
Sangho Shin15273b62014-10-16 22:22:05 -07001176 */
Sangho Shinbe3c3612014-10-30 14:20:36 -07001177 @Override
Sangho Shin306633a2014-10-20 14:26:55 -07001178 public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
Sangho Shin15273b62014-10-16 22:22:05 -07001179 Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
Sangho Shinf65b4da2014-10-28 16:58:13 -07001180 Short srcTcpPort, Short dstTcpPort, int priority, String tid,
1181 PolicyType type) {
1182
1183 // Sanity check
1184 SegmentRoutingTunnel tunnelInfo = tunnelTable.get(tid);
1185 if (tunnelInfo == null) {
1186 log.warn("Tunnel {} is not defined", tid);
1187 return false;
1188 }
Sangho Shin15273b62014-10-16 22:22:05 -07001189
Sangho Shin5b8f5452014-10-20 11:46:01 -07001190 PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
1191
1192 if (srcMac != null)
1193 packetBuilder.setSrcMac(srcMac);
1194 if (dstMac != null)
1195 packetBuilder.setDstMac(dstMac);
Sangho Shin58182672014-10-21 13:23:38 -07001196 if (etherType == null) // Cqpd requires the type of IPV4
1197 packetBuilder.setEtherType(Ethernet.TYPE_IPV4);
1198 else
Sangho Shin5b8f5452014-10-20 11:46:01 -07001199 packetBuilder.setEtherType(etherType);
1200 if (srcIp != null)
1201 packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
1202 if (dstIp != null)
1203 packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
1204 if (ipProto != null)
1205 packetBuilder.setIpProto(ipProto);
1206 if (srcTcpPort > 0)
1207 packetBuilder.setSrcTcpPort(srcTcpPort);
1208 if (dstTcpPort > 0)
1209 packetBuilder.setDstTcpPort(dstTcpPort);
1210 PacketMatch policyMatch = packetBuilder.build();
Sangho Shinf65b4da2014-10-28 16:58:13 -07001211
1212 if (type == PolicyType.TUNNEL_FLOW) {
1213 SegmentRoutingPolicy srPolicy =
1214 new SegmentRoutingPolicyTunnel(this,pid, type, policyMatch,
1215 priority, tid);
1216 if (srPolicy.createPolicy()) {
1217 policyTable.put(pid, srPolicy);
1218 return true;
1219 }
1220 else { log.warn("Failed to create a policy");
1221 return false;
1222 }
1223 }
1224 else {
1225 log.warn("No other policy is supported yet.");
Sangho Shin6471d202014-10-23 10:59:36 -07001226 return false;
1227 }
Sangho Shin15273b62014-10-16 22:22:05 -07001228 }
1229
Sangho Shin5b8f5452014-10-20 11:46:01 -07001230 /**
1231 * Remove all policies applied to specific tunnel.
1232 *
1233 * @param srcMac
1234 * @param dstMac
1235 * @param etherType
1236 * @param srcIp
1237 * @param dstIp
1238 * @param ipProto
1239 * @param srcTcpPort
1240 * @param dstTcpPort
1241 * @param tid
Sangho Shin306633a2014-10-20 14:26:55 -07001242 * @return
Sangho Shin5b8f5452014-10-20 11:46:01 -07001243 */
Sangho Shin306633a2014-10-20 14:26:55 -07001244 public boolean removePolicy(String pid) {
Sangho Shinf65b4da2014-10-28 16:58:13 -07001245 //Sanity check
1246 SegmentRoutingPolicy policy = policyTable.get(pid);
1247 if (policy == null) {
1248 log.warn("Cannot find the policy {}", pid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001249 return false;
Sangho Shinf65b4da2014-10-28 16:58:13 -07001250 }
1251 if (policy.removePolicy()) {
1252 policyTable.remove(pid);
1253 log.debug("Policy {} is removed.", pid);
1254 return true;
1255 }
1256 else {
1257 log.warn("Faild to remove the policy {}", pid);
Sangho Shin5671cbb2014-10-20 22:35:41 -07001258 return false;
Sangho Shin5b8f5452014-10-20 11:46:01 -07001259 }
1260
Sangho Shine020cc32014-10-20 13:28:02 -07001261 }
Sangho Shin5b8f5452014-10-20 11:46:01 -07001262
Fahad Naeem Khan4ff83d62014-10-28 16:18:07 -07001263 public enum removeTunnelMessages{
1264 SUCCESS(0, "Tunnel is removed successfully."),
1265 ERROR_REFERENCED(1, "Can't remove tunnel as its referenced by other policy(s)"),
1266 ERROR_SWITCH(2, "Switch not found in the tunnel route"),
1267 ERROR_DRIVER(3, "Can't remove tunnel at driver"),
1268 ERROR_TUNNEL(4, "Tunnel not found");
1269
1270 private final int code;
1271 private final String description;
1272
1273 private removeTunnelMessages(int code, String description) {
1274 this.code = code;
1275 this.description = description;
1276 }
1277
1278 public String getDescription() {
1279 return this.description;
1280 }
1281
1282 public int getCode() {
1283 return this.code;
1284 }
1285
1286 @Override
1287 public String toString() {
1288 return "[" + this.code + ": " + this.description + "]";
1289 }
1290
1291 }
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001292 /**
1293 * Remove a tunnel
1294 * It removes all groups for the tunnel if the tunnel is not used for any
1295 * policy.
1296 *
1297 * @param tunnelId tunnel ID to remove
1298 */
Fahad Naeem Khan4ff83d62014-10-28 16:18:07 -07001299 public removeTunnelMessages removeTunnel(String tunnelId) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001300
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001301 // Check if the tunnel is used for any policy
Sangho Shinf65b4da2014-10-28 16:58:13 -07001302 for (SegmentRoutingPolicy policy: policyTable.values()) {
1303 if (policy.getType() == PolicyType.TUNNEL_FLOW) {
1304 String tid = ((SegmentRoutingPolicyTunnel)policy).getTunnelId();
1305 if (tid.equals(tunnelId)) {
1306 log.debug("Tunnel {} is still used for the policy {}.",
1307 policy.getPolicyId(), tunnelId);
1308 return removeTunnelMessages.ERROR_REFERENCED;
1309 }
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001310 }
1311 }
1312
Sangho Shinf65b4da2014-10-28 16:58:13 -07001313 SegmentRoutingTunnel tunnel = tunnelTable.get(tunnelId);
1314 if (tunnel == null) {
1315 log.warn("Tunnul object does not exist {}", tunnelId);
Fahad Naeem Khan4ff83d62014-10-28 16:18:07 -07001316 return removeTunnelMessages.ERROR_TUNNEL;
Sangho Shinf65b4da2014-10-28 16:58:13 -07001317 }
1318 else {
1319 if (tunnel.removeTunnel()) {
1320 tunnelTable.remove(tunnelId);
1321 log.debug("Tunnel {} was removed successfully.", tunnelId);
1322 return removeTunnelMessages.SUCCESS;
Sangho Shin5671cbb2014-10-20 22:35:41 -07001323 }
1324 else {
Sangho Shinf65b4da2014-10-28 16:58:13 -07001325 log.warn("Faild in removing the tunnel {}", tunnelId);
1326 return removeTunnelMessages.ERROR_DRIVER;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001327 }
1328 }
Sangho Shin55d00e12014-10-20 12:13:07 -07001329 }
1330
Sangho Shin7330c032014-10-20 10:34:51 -07001331 // ************************************
1332 // Utility functions
1333 // ************************************
1334
Sangho Shinbe3c3612014-10-30 14:20:36 -07001335 /**
1336 * Get the next MatchAction ID
1337 *
1338 * @return MatchAction ID
1339 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001340 public long getNextMatchActionID() {
1341 return this.matchActionId++;
1342 }
Sangho Shin1a692c02014-10-23 17:05:41 -07001343
Sangho Shinbe3c3612014-10-30 14:20:36 -07001344 /**
1345 * Get ports for the adjacency SID given
1346 *
1347 * @param nodeSid Node SID of the adjacency SID
1348 * @param adjacencySid Adjacency SID
1349 * @return List of ports
1350 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001351 public List<Integer> getAdacencyPorts(int nodeSid, int adjacencySid) {
Sangho Shin1a692c02014-10-23 17:05:41 -07001352 HashMap<Integer, List<Integer>> adjacencySidInfo =
Sangho Shinf65b4da2014-10-28 16:58:13 -07001353 adjacencySidTable.get(Integer.valueOf(nodeSid));
1354 if (adjacencySidInfo == null)
Sangho Shin6471d202014-10-23 10:59:36 -07001355 return null;
Sangho Shinf65b4da2014-10-28 16:58:13 -07001356 else
1357 return adjacencySidInfo.get(Integer.valueOf(adjacencySid));
Sangho Shin6471d202014-10-23 10:59:36 -07001358 }
1359
Sangho Shine842cad2014-10-24 16:07:35 -07001360 /**
1361 * Check if the node ID is the adjacency ID or not
1362 *
1363 * @param nodeId to check
1364 * @return true if the node ID is the adjacency ID, false otherwise
1365 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001366 public boolean isAdjacencySid(String nodeId) {
Sangho Shin6471d202014-10-23 10:59:36 -07001367 // XXX The rule might change
1368 if (Integer.parseInt(nodeId) > 10000)
1369 return true;
1370
1371 return false;
1372 }
1373
Sangho Shin15273b62014-10-16 22:22:05 -07001374 /**
Sangho Shinced05b62014-10-22 11:23:14 -07001375 * Returns the Adjacency IDs for the node
1376 *
1377 * @param nodeSid Node SID
Sangho Shincfef3922014-10-22 12:04:16 -07001378 * @return Collection of Adjacency ID
Sangho Shinced05b62014-10-22 11:23:14 -07001379 */
Sangho Shincfef3922014-10-22 12:04:16 -07001380 public Collection<Integer> getAdjacencyIds(int nodeSid) {
1381 HashMap<Integer, List<Integer>> adjecencyInfo =
Sangho Shin6471d202014-10-23 10:59:36 -07001382 adjacencySidTable.get(Integer.valueOf(nodeSid));
Sangho Shincfef3922014-10-22 12:04:16 -07001383
1384 return adjecencyInfo.keySet();
1385 }
1386
Sangho Shinbe3c3612014-10-30 14:20:36 -07001387 /**
1388 * Send a Barrier request message and wait for the reply.
1389 * It waits for the reply for 2 seconds and it cause exception when timer
1390 * expires.
1391 * TODO: When it does not receive the reply within timeout, recovery action
1392 * is required.
1393 *
1394 * @param sw Switch to send the Barrier message
1395 */
Sangho Shin81d5e8c2014-10-30 23:48:19 -07001396 private OFBarrierReplyFuture sendBarrier(Switch sw) {
Sangho Shin8a59fde2014-10-29 23:49:18 -07001397 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -08001398 sw.getDpid().value());
Sangho Shin81d5e8c2014-10-30 23:48:19 -07001399 OFBarrierReplyFuture replyFuture = null;
Sangho Shin8a59fde2014-10-29 23:49:18 -07001400 if (sw13 != null) {
Sangho Shin8a59fde2014-10-29 23:49:18 -07001401 try {
1402 replyFuture = sw13.sendBarrier();
1403 } catch (IOException e) {
1404 log.error("Error sending barrier request to switch {}",
1405 sw13.getId(), e.getCause());
1406 }
Sangho Shin81d5e8c2014-10-30 23:48:19 -07001407 }
1408
1409 return replyFuture;
1410 }
1411
1412 private boolean checkBarrierReplies(List<OFBarrierReplyFuture> replies) {
1413
1414 for (OFBarrierReplyFuture replyFuture: replies) {
Sangho Shin8a59fde2014-10-29 23:49:18 -07001415 OFBarrierReply br = null;
1416 try {
1417 br = replyFuture.get(2, TimeUnit.SECONDS);
1418 } catch (TimeoutException | InterruptedException | ExecutionException e) {
1419 // XXX for some reason these exceptions are not being thrown
1420 }
1421 if (br == null) {
Sangho Shin81d5e8c2014-10-30 23:48:19 -07001422 log.warn("Did not receive barrier-reply for request ID {}",
1423 replyFuture.getTransactionId());
Sangho Shin8a59fde2014-10-29 23:49:18 -07001424 // XXX take corrective action
Sangho Shin81d5e8c2014-10-30 23:48:19 -07001425 return false;
Sangho Shin8a59fde2014-10-29 23:49:18 -07001426 }
1427 }
Sangho Shin81d5e8c2014-10-30 23:48:19 -07001428 return true;
Sangho Shin8a59fde2014-10-29 23:49:18 -07001429 }
1430
Sangho Shincfef3922014-10-22 12:04:16 -07001431 /**
1432 * Returns the Adjacency Info for the node
1433 *
1434 * @param nodeSid Node SID
1435 * @return HashMap of <AdjacencyID, list of ports>
1436 */
1437 public HashMap<Integer, List<Integer>> getAdjacencyInfo(int nodeSid) {
Sangho Shin6471d202014-10-23 10:59:36 -07001438 return adjacencySidTable.get(Integer.valueOf(nodeSid));
Sangho Shincfef3922014-10-22 12:04:16 -07001439 }
1440
Sangho Shine842cad2014-10-24 16:07:35 -07001441 /**
1442 * Parse the adjacency jason string and build the adjacency Table
1443 *
1444 * @param adjInfo adjacency info jason string
1445 * @return HashMap<Adjacency ID, List of ports> object
1446 * @throws JSONException
1447 */
1448 private HashMap<Integer, List<Integer>> parseAdjacencySidInfo(String adjInfo)
1449 throws JSONException {
Sangho Shincfef3922014-10-22 12:04:16 -07001450 JSONArray arry = new JSONArray(adjInfo);
Sangho Shin2404fec2014-10-29 10:43:05 -07001451 HashMap<Integer, List<Integer>> adjacencyInfo =
Sangho Shincfef3922014-10-22 12:04:16 -07001452 new HashMap<Integer, List<Integer>>();
1453
1454 for (int i = 0; i < arry.length(); i++) {
1455 Integer adjId = (Integer) arry.getJSONObject(i).get("adjSid");
1456 JSONArray portNos = (JSONArray) arry.getJSONObject(i).get("ports");
1457 if (adjId == null || portNos == null)
1458 continue;
1459
1460 List<Integer> portNoList = new ArrayList<Integer>();
1461 for (int j = 0; j < portNos.length(); j++) {
Sangho Shin62325582014-10-24 10:36:09 -07001462 portNoList.add(Integer.valueOf(portNos.getInt(j)));
Sangho Shincfef3922014-10-22 12:04:16 -07001463 }
Sangho Shin2404fec2014-10-29 10:43:05 -07001464 adjacencyInfo.put(adjId, portNoList);
Sangho Shincfef3922014-10-22 12:04:16 -07001465 }
Sangho Shin2404fec2014-10-29 10:43:05 -07001466 return adjacencyInfo;
Sangho Shinced05b62014-10-22 11:23:14 -07001467 }
1468
1469 /**
Sangho Shine842cad2014-10-24 16:07:35 -07001470 * Build the MatchActionOperationEntry according to the flag
1471 *
1472 * @param sw node ID to push for MPLS label
1473 * @param mplsLabel List of Switch DPIDs to forwards packets to
1474 * @param fwdSws PHP flag
1475 * @param Bos BoS flag
1476 * @param isTransitRouter
1477 * @return MatchiACtionOperationEntry object
1478 */
1479 private MatchActionOperationEntry buildMAEntry(Switch sw,
1480 String mplsLabel, List<String> fwdSws, boolean php,
1481 boolean Bos) {
1482 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel), Bos);
1483 List<Action> actions = new ArrayList<Action>();
1484
1485 PopMplsAction popActionBos = new PopMplsAction(EthType.IPv4);
1486 PopMplsAction popAction = new PopMplsAction(EthType.MPLS_UNICAST);
1487 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
1488 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
1489 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
1490
1491 if (php) {
1492 actions.add(copyTtlInAction);
1493 if (Bos) {
1494 actions.add(popActionBos);
1495 actions.add(decNwTtlAction);
1496 }
1497 else {
1498 actions.add(popAction);
1499 actions.add(decMplsTtlAction);
1500 }
1501 }
1502 else {
1503 actions.add(decMplsTtlAction);
1504 }
1505
Sangho Shin402354e2014-10-27 16:53:05 -07001506 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -08001507 sw.getDpid().value());
Sangho Shin402354e2014-10-27 16:53:05 -07001508 if ((sw13 instanceof OFSwitchImplDellOSR) && isTransitRouter(sw) && !php) {
Sangho Shine842cad2014-10-24 16:07:35 -07001509 PortNumber port = pickOnePort(sw, fwdSws);
1510 if (port == null) {
1511 log.warn("Failed to get a port from NeightborSet");
1512 return null;
1513 }
1514 OutputAction outputAction = new OutputAction(port);
1515 Switch destSwitch =
1516 mutableTopology.getSwitch(new Dpid(fwdSws.get(0)));
1517 MacAddress srcMac =
1518 MacAddress.of(sw.getStringAttribute("routerMac"));
1519 MacAddress dstMac =
1520 MacAddress.of(destSwitch.getStringAttribute("routerMac"));
1521 SetSAAction setSAAction = new SetSAAction(srcMac);
1522 SetDAAction setDAAction = new SetDAAction(dstMac);
1523 actions.add(outputAction);
1524 actions.add(setSAAction);
1525 actions.add(setDAAction);
1526 }
1527 else {
1528 GroupAction groupAction = new GroupAction();
1529 for (String dpid: fwdSws)
1530 groupAction.addSwitch(new Dpid(dpid));
1531 actions.add(groupAction);
1532 }
1533
1534 MatchAction matchAction = new MatchAction(new MatchActionId(matchActionId++),
1535 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
1536 Operator operator = Operator.ADD;
1537 MatchActionOperationEntry maEntry =
1538 new MatchActionOperationEntry(operator, matchAction);
1539
1540 return maEntry;
1541 }
1542
1543 /**
1544 * Pick a router from the neighbor set and return the port
1545 * connected to the router.
1546 *
1547 * @param sw source switch
1548 * @param fwdSwDpids neighbor set of the switch
1549 * @return PortNumber connected to one of the neighbors
1550 */
1551 private PortNumber pickOnePort(Switch sw, List<String> fwdSwDpids) {
1552 for (Link link: sw.getOutgoingLinks()) {
1553 if (link.getDstSwitch().getDpid().toString().equals(fwdSwDpids.get(0)))
1554 return link.getSrcPort().getNumber();
1555 }
1556
1557 return null;
1558 }
1559
1560 /**
1561 * check if the router is the transit router or not
1562 *
1563 * @param sw router switch to check
1564 * @return true if the switch is the transit router, false otherwise
1565 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001566 public boolean isTransitRouter(Switch sw) {
Sangho Shine842cad2014-10-24 16:07:35 -07001567 int i = 0;
1568 for(Switch neighbor: sw.getNeighbors()) {
1569 i++;
1570 }
1571 if (i > 1)
1572 return true;
1573 else
1574 return false;
1575 }
1576
1577 /**
Sangho Shin55908712014-10-27 15:16:48 -07001578 * Get the forwarding Switch DPIDs to send packets to a node.
1579 * If ECMP in transit routers is not supported, only one switch needs to be
1580 * selected as the neighbor set to forward packets to.
Sangho Shin15273b62014-10-16 22:22:05 -07001581 *
Sangho Shin7330c032014-10-20 10:34:51 -07001582 * @param srcSw source switch
1583 * @param nodeId destination node Id
1584 * @return list of switch DPID to forward packets to
Sangho Shin15273b62014-10-16 22:22:05 -07001585 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001586 public List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
Sangho Shin15273b62014-10-16 22:22:05 -07001587
Sangho Shin7330c032014-10-20 10:34:51 -07001588 List<Dpid> fwdSws = new ArrayList<Dpid>();
1589 Switch destSw = null;
Sangho Shin15273b62014-10-16 22:22:05 -07001590
Sangho Shin7330c032014-10-20 10:34:51 -07001591 destSw = getSwitchFromNodeId(nodeId);
1592
1593 if (destSw == null) {
1594 log.debug("Cannot find the switch with ID {}", nodeId);
1595 return null;
1596 }
1597
1598 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
1599
1600 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
1601 ecmpSPG.getAllLearnedSwitchesAndVia();
1602 for (Integer itrIdx : switchVia.keySet()) {
1603 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
1604 switchVia.get(itrIdx);
1605 for (Switch targetSw : swViaMap.keySet()) {
1606 String destSwDpid = destSw.getDpid().toString();
1607 if (targetSw.getDpid().toString().equals(destSwDpid)) {
1608 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
1609 if (via.isEmpty()) {
1610 fwdSws.add(destSw.getDpid());
1611 }
1612 else {
Sangho Shina000c612014-10-21 14:17:59 -07001613 Dpid firstVia = via.get(via.size()-1);
1614 fwdSws.add(firstVia);
Sangho Shinf66aa262014-10-27 16:03:42 -07001615 IOF13Switch targetSw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -08001616 targetSw.getDpid().value());
Sangho Shinf66aa262014-10-27 16:03:42 -07001617 if (targetSw13 instanceof OFSwitchImplDellOSR &&
Sangho Shin55908712014-10-27 15:16:48 -07001618 isTransitRouter(targetSw) &&
1619 isTransitRouter(mutableTopology.getSwitch(firstVia))) {
1620 return fwdSws;
1621 }
Sangho Shin7330c032014-10-20 10:34:51 -07001622 }
1623 }
1624 }
1625 }
1626 }
1627
1628 return fwdSws;
Sangho Shin15273b62014-10-16 22:22:05 -07001629 }
1630
Sangho Shin7330c032014-10-20 10:34:51 -07001631 /**
1632 * Get switch for the node Id specified
1633 *
1634 * @param nodeId node ID for switch
1635 * @return Switch
1636 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001637 public Switch getSwitchFromNodeId(String nodeId) {
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001638
Sangho Shin7330c032014-10-20 10:34:51 -07001639 for (Switch sw : mutableTopology.getSwitches()) {
1640 String id = sw.getStringAttribute("nodeSid");
1641 if (id.equals(nodeId)) {
1642 return sw;
1643 }
1644 }
1645
1646 return null;
1647 }
Fahad Naeem Khan4444b952014-10-18 22:30:50 -07001648
Sangho Shin43cee112014-09-25 16:43:34 -07001649 /**
Sangho Shin7330c032014-10-20 10:34:51 -07001650 * Check if the switch is the edge router or not.
1651 *
1652 * @param dpid Dpid of the switch to check
1653 * @return true if it is an edge router, otherwise false
1654 */
1655 private boolean IsEdgeRouter(String dpid) {
Sangho Shin0df01982014-09-25 17:11:18 -07001656
Sangho Shin7330c032014-10-20 10:34:51 -07001657 for (Switch sw : mutableTopology.getSwitches()) {
1658 String dpidStr = sw.getDpid().toString();
1659 if (dpid.equals(dpidStr)) {
1660 /*
1661 String subnetInfo = sw.getStringAttribute("subnets");
1662 if (subnetInfo == null || subnetInfo.equals("[]")) {
1663 return false;
1664 }
1665 else
1666 return true;
1667 */
1668 String isEdge = sw.getStringAttribute("isEdgeRouter");
1669 if (isEdge != null) {
1670 if (isEdge.equals("true"))
1671 return true;
1672 else
1673 return false;
1674 }
Sangho Shin43cee112014-09-25 16:43:34 -07001675 }
1676 }
1677
Sangho Shin7330c032014-10-20 10:34:51 -07001678 return false;
Sangho Shineb083032014-09-22 16:11:34 -07001679 }
1680
1681 /**
1682 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -07001683 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001684 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -07001685 * @return MPLS label for the switch
1686 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001687 public String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -07001688
1689 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001690 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -07001691 String dpidStr = sw.getDpid().toString();
1692 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -07001693 mplsLabel = sw.getStringAttribute("nodeSid");
1694 break;
Sangho Shin1aa93542014-09-22 09:49:44 -07001695 }
1696 }
1697
Sangho Shineb083032014-09-22 16:11:34 -07001698 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -07001699 }
1700
Sangho Shineb083032014-09-22 16:11:34 -07001701 /**
Sangho Shin1aa93542014-09-22 09:49:44 -07001702 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -07001703 *
Sangho Shin1aa93542014-09-22 09:49:44 -07001704 * @param addr - subnet address to match
1705 * @param addr1 - IP address to check
1706 * @return true if the IP address matches to the subnet, otherwise false
1707 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001708 public boolean netMatch(String addr, String addr1) { // addr is subnet
1709 // address and addr1 is
1710 // ip address. Function
1711 // will return true, if
1712 // addr1 is within
1713 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -07001714
1715 String[] parts = addr.split("/");
1716 String ip = parts[0];
1717 int prefix;
1718
1719 if (parts.length < 2) {
1720 prefix = 0;
1721 } else {
1722 prefix = Integer.parseInt(parts[1]);
1723 }
1724
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001725 Inet4Address a = null;
1726 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -07001727 try {
1728 a = (Inet4Address) InetAddress.getByName(ip);
1729 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001730 } catch (UnknownHostException e) {
1731 }
Sangho Shin1aa93542014-09-22 09:49:44 -07001732
1733 byte[] b = a.getAddress();
1734 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001735 ((b[1] & 0xFF) << 16) |
1736 ((b[2] & 0xFF) << 8) |
1737 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001738
1739 byte[] b1 = a1.getAddress();
1740 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001741 ((b1[1] & 0xFF) << 16) |
1742 ((b1[2] & 0xFF) << 8) |
1743 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -07001744
1745 int mask = ~((1 << (32 - prefix)) - 1);
1746
1747 if ((ipInt & mask) == (ipInt1 & mask)) {
1748 return true;
1749 }
1750 else {
1751 return false;
1752 }
1753 }
Sangho Shineb083032014-09-22 16:11:34 -07001754
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001755 /**
1756 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -07001757 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -07001758 * @param sw - Switch to add the rule
1759 * @param hostIpAddress Destination host IP address
1760 * @param hostMacAddress Destination host MAC address
1761 */
Sangho Shineb083032014-09-22 16:11:34 -07001762 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
1763 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
Sangho Shineb083032014-09-22 16:11:34 -07001764 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -07001765
Sangho Shin463bee52014-09-29 15:14:43 -07001766 /**
1767 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -07001768 *
Sangho Shin463bee52014-09-29 15:14:43 -07001769 * @param ipv4
1770 */
Sangho Shin7330c032014-10-20 10:34:51 -07001771 public void addPacketToPacketBuffer(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -07001772 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -07001773 }
1774
1775 /**
1776 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -07001777 *
Sangho Shin463bee52014-09-29 15:14:43 -07001778 * @param destIp Destination address of packets to retrieve
1779 */
1780 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
1781
1782 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
1783
Sangho Shin61535402014-10-01 11:37:14 -07001784 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001785 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -07001786 int dest = ip.getDestinationAddress();
1787 IPv4Address ip1 = IPv4Address.of(dest);
1788 IPv4Address ip2 = IPv4Address.of(destIp);
1789 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -07001790 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -07001791 }
1792 }
1793 }
1794
1795 return bufferedPackets;
1796 }
1797
Sangho Shin7330c032014-10-20 10:34:51 -07001798 /**
1799 * Get MAC address to known hosts
1800 *
1801 * @param destinationAddress IP address to get MAC address
1802 * @return MAC Address to given IP address
1803 */
1804 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
1805
1806 // Can't we get the host IP address from the TopologyService ??
1807
1808 Iterator<ArpEntry> iterator = arpEntries.iterator();
1809
1810 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
1811 byte[] ipAddressInByte = ipAddress.getBytes();
1812
1813 while (iterator.hasNext()) {
1814 ArpEntry arpEntry = iterator.next();
1815 byte[] address = arpEntry.targetIpAddress;
1816
1817 IPv4Address a = IPv4Address.of(address);
1818 IPv4Address b = IPv4Address.of(ipAddressInByte);
1819
1820 if (a.equals(b)) {
1821 log.debug("Found an arp entry");
1822 return arpEntry.targetMacAddress;
1823 }
1824 }
1825
1826 return null;
1827 }
1828
1829 /**
1830 * Send an ARP request via ArpHandler
1831 *
1832 * @param destinationAddress
1833 * @param sw
1834 * @param inPort
1835 *
1836 */
1837 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
1838 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
1839 }
1840
Sangho Shinbe3c3612014-10-30 14:20:36 -07001841 /**
1842 * Get IOF13Switch object for the DPID
1843 *
1844 * @param dpid Switch DPID
1845 * @return IOF13Switch object
1846 */
Sangho Shin2051d562014-11-05 09:54:42 -08001847 public IOF13Switch getIOF13Switch(String dpidStr) {
Sangho Shinf65b4da2014-10-28 16:58:13 -07001848
Sangho Shin2051d562014-11-05 09:54:42 -08001849 Dpid dpid = new Dpid(dpidStr);
Sangho Shinf65b4da2014-10-28 16:58:13 -07001850 IOF13Switch targetSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin2051d562014-11-05 09:54:42 -08001851 dpid.value());
Sangho Shinf65b4da2014-10-28 16:58:13 -07001852
1853 return targetSw;
1854 }
1855
Sangho Shinbe3c3612014-10-30 14:20:36 -07001856 /**
1857 * Get Switch object for the DPID
1858 *
1859 * @param dpid Switch DPID
1860 * @return Switch object
1861 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001862 public Switch getSwitch(String dpid) {
1863 return mutableTopology.getSwitch(new Dpid(dpid));
1864 }
1865
1866
Sangho Shin7330c032014-10-20 10:34:51 -07001867 // ************************************
1868 // Test functions
1869 // ************************************
1870
Sangho Shin55d00e12014-10-20 12:13:07 -07001871 private void runTest() {
1872
1873 if (testMode == POLICY_ADD1) {
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001874 Integer[] routeArray = {101, 105, 110};
1875 /*List<Dpid> routeList = new ArrayList<Dpid>();
Sangho Shin55d00e12014-10-20 12:13:07 -07001876 for (int i = 0; i < routeArray.length; i++) {
1877 Dpid dpid = getSwitchFromNodeId(routeArray[i]).getDpid();
1878 routeList.add(dpid);
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001879 }*/
Sangho Shin55d00e12014-10-20 12:13:07 -07001880
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001881 if (createTunnel("1", Arrays.asList(routeArray))) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001882 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1883 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1884
1885 log.debug("Set the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001886 this.createPolicy("1", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001887 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
Sangho Shine020cc32014-10-20 13:28:02 -07001888 "1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001889 testMode = POLICY_ADD2;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001890 testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001891 }
1892 else {
1893 // retry it
1894 testTask.reschedule(5, TimeUnit.SECONDS);
1895 }
1896 }
1897 else if (testMode == POLICY_ADD2) {
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001898 Integer[] routeArray = {101, 102, 103, 104, 105, 108, 110};
Sangho Shin55d00e12014-10-20 12:13:07 -07001899
Srikanth Vavilapalli1f6a5742014-10-21 13:45:11 -07001900 if (createTunnel("2", Arrays.asList(routeArray))) {
Sangho Shin55d00e12014-10-20 12:13:07 -07001901 IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
1902 IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
1903
1904 log.debug("Set the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001905 this.createPolicy("2", null, null, Ethernet.TYPE_IPV4, srcIp,
Sangho Shin55d00e12014-10-20 12:13:07 -07001906 dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 20000,
Sangho Shine020cc32014-10-20 13:28:02 -07001907 "2");
Fahad Naeem Khan95aa4012014-10-21 14:07:00 -07001908 //testMode = POLICY_REMOVE2;
1909 //testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001910 }
1911 else {
1912 log.debug("Retry it");
1913 testTask.reschedule(5, TimeUnit.SECONDS);
1914 }
1915 }
1916 else if (testMode == POLICY_REMOVE2){
1917 log.debug("Remove the policy 2");
Sangho Shine020cc32014-10-20 13:28:02 -07001918 this.removePolicy("2");
Sangho Shin55d00e12014-10-20 12:13:07 -07001919 testMode = POLICY_REMOVE1;
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001920 testTask.reschedule(5, TimeUnit.SECONDS);
Sangho Shin55d00e12014-10-20 12:13:07 -07001921 }
1922 else if (testMode == POLICY_REMOVE1){
1923 log.debug("Remove the policy 1");
Sangho Shine020cc32014-10-20 13:28:02 -07001924 this.removePolicy("1");
Sangho Shin55d00e12014-10-20 12:13:07 -07001925
Sangho Shin4b46bcd2014-10-20 15:48:47 -07001926 testMode = TUNNEL_REMOVE1;
1927 testTask.reschedule(5, TimeUnit.SECONDS);
1928 }
1929 else if (testMode == TUNNEL_REMOVE1) {
1930 log.debug("Remove the tunnel 1");
1931 this.removeTunnel("1");
1932
1933 testMode = TUNNEL_REMOVE2;
1934 testTask.reschedule(5, TimeUnit.SECONDS);
1935 }
1936 else if (testMode == TUNNEL_REMOVE2) {
1937 log.debug("Remove the tunnel 2");
1938 this.removeTunnel("2");
1939 log.debug("The end of test");
1940 }
Sangho Shin55d00e12014-10-20 12:13:07 -07001941 }
Sangho Shin7330c032014-10-20 10:34:51 -07001942
1943 private void runTest1() {
1944
1945 String dpid1 = "00:00:00:00:00:00:00:01";
1946 String dpid2 = "00:00:00:00:00:00:00:0a";
1947 Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
1948 Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
1949
1950 if (srcSw == null || dstSw == null) {
1951 testTask.reschedule(1, TimeUnit.SECONDS);
1952 log.debug("Switch is gone. Reschedule the test");
1953 return;
1954 }
1955
1956 String[] routeArray = {"101", "102", "105", "108", "110"};
1957 List<String> routeList = new ArrayList<String>();
1958 for (int i = 0; i < routeArray.length; i++)
1959 routeList.add(routeArray[i]);
1960
1961 List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
1962
1963 log.debug("Test set is {}", routeList.toString());
1964 log.debug("Result set is {}", optimizedRoute.toString());
1965
1966
1967 }
1968
Sangho Shin7330c032014-10-20 10:34:51 -07001969 /**
1970 * Debugging function to print out the Match Action Entry
1971 * @param sw13
1972 *
1973 * @param maEntry
1974 */
Sangho Shinf65b4da2014-10-28 16:58:13 -07001975 public void printMatchActionOperationEntry(
Sangho Shin7330c032014-10-20 10:34:51 -07001976 IOF13Switch sw13, MatchActionOperationEntry maEntry) {
1977
1978 StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
1979
1980 MatchAction ma = maEntry.getTarget();
1981 Match m = ma.getMatch();
1982 List<Action> actions = ma.getActions();
1983
1984 if (m instanceof Ipv4Match) {
1985 logStr.append("If the IP matches with ");
1986 IPv4Net ip = ((Ipv4Match) m).getDestination();
1987 logStr.append(ip.toString());
1988 logStr.append(" then ");
1989 }
1990 else if (m instanceof MplsMatch) {
1991 logStr.append("If the MPLS label matches with ");
1992 int mplsLabel = ((MplsMatch) m).getMplsLabel();
1993 logStr.append(mplsLabel);
1994 logStr.append(" then ");
1995 }
1996 else if (m instanceof PacketMatch) {
Sangho Shinc5a38a02014-10-28 16:09:38 -07001997 logStr.append("if the policy match is XXX then ");
Sangho Shin7330c032014-10-20 10:34:51 -07001998 }
1999
2000 logStr.append(" do { ");
2001 for (Action action : actions) {
2002 if (action instanceof CopyTtlInAction) {
2003 logStr.append("copy ttl In, ");
2004 }
2005 else if (action instanceof CopyTtlOutAction) {
2006 logStr.append("copy ttl Out, ");
2007 }
2008 else if (action instanceof DecMplsTtlAction) {
2009 logStr.append("Dec MPLS TTL , ");
2010 }
2011 else if (action instanceof GroupAction) {
2012 logStr.append("Forward packet to < ");
2013 NeighborSet dpids = ((GroupAction) action).getDpids();
2014 logStr.append(dpids.toString() + ",");
Sangho Shin7330c032014-10-20 10:34:51 -07002015 }
2016 else if (action instanceof PopMplsAction) {
2017 logStr.append("Pop MPLS label, ");
2018 }
2019 else if (action instanceof PushMplsAction) {
2020 logStr.append("Push MPLS label, ");
2021 }
2022 else if (action instanceof SetMplsIdAction) {
2023 int id = ((SetMplsIdAction) action).getMplsId();
2024 logStr.append("Set MPLS ID as " + id + ", ");
2025 }
2026 }
2027
2028 log.debug(logStr.toString());
2029
2030 }
2031
Sangho Shin7330c032014-10-20 10:34:51 -07002032 // ************************************
2033 // Unused classes and functions
2034 // ************************************
2035
2036 /**
2037 * Temporary class to to keep ARP entry
2038 *
2039 */
2040 private class ArpEntry {
2041
2042 byte[] targetMacAddress;
2043 byte[] targetIpAddress;
2044
2045 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
2046 this.targetMacAddress = macAddress;
2047 this.targetIpAddress = ipAddress;
2048 }
2049 }
2050
2051 /**
2052 * This class is used only for link recovery optimization in
2053 * modifyEcmpRoutingRules() function.
2054 * TODO: please remove if the optimization is not used at all
2055 */
2056 private class SwitchPair {
2057 private Switch src;
2058 private Switch dst;
2059
2060 public SwitchPair(Switch src, Switch dst) {
2061 this.src = src;
2062 this.dst = dst;
2063 }
2064
2065 public Switch getSource() {
2066 return src;
2067 }
2068
2069 public Switch getDestination() {
2070 return dst;
2071 }
2072 }
2073
2074 /**
2075 * Update ARP Cache using ARP packets It is used to set destination MAC
2076 * address to forward packets to known hosts. But, it will be replace with
2077 * Host information of Topology service later.
2078 *
2079 * @param arp APR packets to use for updating ARP entries
2080 */
2081 public void updateArpCache(ARP arp) {
2082
2083 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
2084 arp.getSenderProtocolAddress());
2085 // TODO: Need to check the duplication
2086 arpEntries.add(arpEntry);
2087 }
2088
2089 /**
2090 * Modify the routing rules for the lost links
2091 * - Recompute the path if the link failed is included in the path
2092 * (including src and dest).
2093 *
2094 * @param newLink
2095 */
2096 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
2097
2098 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
2099 Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
2100
2101 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
2102 Switch rootSw = ecmpSPG.getRootSwitch();
2103 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
2104 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
2105 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
2106 for (Switch destSw: p.keySet()) {
2107 ArrayList<Path> path = p.get(destSw);
2108 if (checkPath(path, linkRemoved)) {
2109 boolean found = false;
2110 for (SwitchPair pair: linksToRecompute) {
2111 if (pair.getSource().getDpid() == rootSw.getDpid() &&
2112 pair.getSource().getDpid() == destSw.getDpid()) {
2113 found = true;
2114 }
2115 }
2116 if (!found) {
2117 linksToRecompute.add(new SwitchPair(rootSw, destSw));
2118 }
2119 }
2120 }
2121 }
2122 }
2123
2124 // Recompute the path for the specific route
2125 for (SwitchPair pair: linksToRecompute) {
2126
2127 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
2128 // We need the following function for optimization
2129 //ECMPShortestPathGraph ecmpSPG =
2130 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
2131 ECMPShortestPathGraph ecmpSPG =
2132 new ECMPShortestPathGraph(pair.getSource());
2133 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
2134 }
2135 }
2136
2137 /**
2138 * Optimize the mpls label
2139 * The feature will be used only for policy of "avoid a specific switch".
2140 * Check route to each router in route backward.
2141 * If there is only one route to the router and the routers are included in
2142 * the route, remove the id from the path.
2143 * A-B-C-D-E => A-B-C-D-E -> A-E
2144 * | | => A-B-H-I -> A-I
Sangho Shin5b8f5452014-10-20 11:46:01 -07002145 * F-G-H-I => A-D-I > A-D-I
Sangho Shin7330c032014-10-20 10:34:51 -07002146 */
2147 private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
2148
2149 List<String> optimizedPath = new ArrayList<String>();
2150 optimizedPath.addAll(route);
2151 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
2152
2153 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
2154 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
2155 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
2156 for (Switch s: p.keySet()) {
2157 if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
2158 ArrayList<Path> ecmpPaths = p.get(s);
2159 if (ecmpPaths!= null && ecmpPaths.size() == 1) {
2160 for (Path path: ecmpPaths) {
2161 for (LinkData link: path) {
2162 String srcId = getMplsLabel(link.getSrc().getDpid().toString());
2163 String dstId = getMplsLabel(link.getSrc().getDpid().toString());
2164 if (optimizedPath.contains(srcId)) {
2165 optimizedPath.remove(srcId);
2166 }
2167 if (optimizedPath.contains(dstId)) {
2168 optimizedPath.remove(dstId);
2169 }
2170 }
2171 }
2172 }
2173 }
2174 }
2175 }
2176
2177 return optimizedPath;
2178
2179 }
2180
2181 /**
2182 * Check if the path is affected from the link removed
2183 *
2184 * @param path Path to check
2185 * @param linkRemoved link removed
2186 * @return true if the path contains the link removed
2187 */
2188 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
2189
2190 for (Path ppp: path) {
2191 // TODO: need to check if this is a bidirectional or
2192 // unidirectional
2193 for (LinkData link: ppp) {
2194 if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
2195 link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
2196 return true;
2197 }
2198 }
2199
2200 return false;
2201 }
Sangho Shin15273b62014-10-16 22:22:05 -07002202
2203
Sangho Shinf65b4da2014-10-28 16:58:13 -07002204
Sangho Shin2f263692014-09-15 14:09:41 -07002205}