blob: 036b23cfd03c0dcffba5703da88aeb7387954df3 [file] [log] [blame]
Sangho Shin2f263692014-09-15 14:09:41 -07001package net.onrc.onos.apps.segmentrouting;
2
Sangho Shin9c0f4c32014-09-26 16:02:38 -07003import java.io.IOException;
Sangho Shin1aa93542014-09-22 09:49:44 -07004import java.net.Inet4Address;
5import java.net.InetAddress;
6import java.net.UnknownHostException;
Sangho Shin2f263692014-09-15 14:09:41 -07007import java.util.ArrayList;
8import java.util.Collection;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -07009import java.util.HashMap;
Sangho Shin2f263692014-09-15 14:09:41 -070010import java.util.Iterator;
Sangho Shin463bee52014-09-29 15:14:43 -070011import java.util.LinkedList;
Sangho Shin2f263692014-09-15 14:09:41 -070012import java.util.List;
13import java.util.Map;
Sangho Shin463bee52014-09-29 15:14:43 -070014import java.util.Queue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070015import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070016import java.util.concurrent.ScheduledExecutorService;
17import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070018import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070019
20import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070021import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070022import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070023import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070024import net.floodlightcontroller.core.module.FloodlightModuleContext;
25import net.floodlightcontroller.core.module.FloodlightModuleException;
26import net.floodlightcontroller.core.module.IFloodlightModule;
27import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070028import net.floodlightcontroller.core.util.SingletonTask;
29import net.floodlightcontroller.threadpool.IThreadPoolService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070030import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070031import net.onrc.onos.api.packet.IPacketService;
32import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
33import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070034import net.onrc.onos.core.matchaction.MatchAction;
35import net.onrc.onos.core.matchaction.MatchActionId;
36import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
37import net.onrc.onos.core.matchaction.action.Action;
38import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
39import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
40import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
41import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
42import net.onrc.onos.core.matchaction.action.GroupAction;
43import net.onrc.onos.core.matchaction.action.PopMplsAction;
44import net.onrc.onos.core.matchaction.action.PushMplsAction;
45import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070046import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070047import net.onrc.onos.core.matchaction.match.Match;
48import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin2f263692014-09-15 14:09:41 -070049import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070050import net.onrc.onos.core.packet.Ethernet;
51import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070052import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070053import net.onrc.onos.core.topology.ITopologyService;
Sangho Shinc8d2f592014-09-30 16:53:57 -070054import net.onrc.onos.core.topology.LinkData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070055import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070056import net.onrc.onos.core.topology.Port;
Sangho Shinc8d2f592014-09-30 16:53:57 -070057import net.onrc.onos.core.topology.PortData;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070058import net.onrc.onos.core.topology.Switch;
Sangho Shin1aa93542014-09-22 09:49:44 -070059import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070060import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070061import net.onrc.onos.core.util.IPv4Net;
62import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070063
Sangho Shin43cee112014-09-25 16:43:34 -070064import org.json.JSONArray;
65import org.json.JSONException;
Saurav Dasbc594a42014-09-25 20:13:50 -070066import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070067import org.projectfloodlight.openflow.types.IPv4Address;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070068import org.projectfloodlight.openflow.util.HexString;
Sangho Shin2f263692014-09-15 14:09:41 -070069import org.slf4j.Logger;
70import org.slf4j.LoggerFactory;
71
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070072public class SegmentRoutingManager implements IFloodlightModule,
Sangho Shinac5ee2b2014-09-28 21:27:20 -070073 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070074
75 private static final Logger log = LoggerFactory
76 .getLogger(SegmentRoutingManager.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070077 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070078 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070079 private MutableTopology mutableTopology;
Sangho Shin463bee52014-09-29 15:14:43 -070080 private Queue<IPv4> ipPacketQueue;
Sangho Shin2f263692014-09-15 14:09:41 -070081
82 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070083 private ArpHandler arpHandler;
84 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070085 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070086 private IThreadPoolService threadPool;
87 private SingletonTask discoveryTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070088 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -070089
90 @Override
91 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
92 // TODO Auto-generated method stub
93 return null;
94 }
95
96 @Override
97 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
98 // TODO Auto-generated method stub
99 return null;
100 }
101
102 @Override
103 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
104 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
105
106 l.add(IFloodlightProviderService.class);
107 l.add(IConfigInfoService.class);
108 l.add(ITopologyService.class);
109 l.add(IPacketService.class);
110 l.add(IFlowPusherService.class);
111 l.add(ITopologyService.class);
112
113 return l;
114
115 }
116
117 @Override
118 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700119 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700120 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700121 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700122 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700123 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700124 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700125 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700126 mutableTopology = topologyService.getTopology();
127 topologyService.addListener(this, false);
Sangho Shin463bee52014-09-29 15:14:43 -0700128 ipPacketQueue = new LinkedList<IPv4>();
Sangho Shin2f263692014-09-15 14:09:41 -0700129
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700130 this.packetService = context.getServiceImpl(IPacketService.class);
131 packetService.registerPacketListener(this);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700132
Sangho Shin2f263692014-09-15 14:09:41 -0700133 }
134
135 @Override
136 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700137 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700138
Sangho Shinc8d2f592014-09-30 16:53:57 -0700139 discoveryTask = new SingletonTask(ses, new Runnable() {
140 @Override
141 public void run() {
142 populateEcmpRoutingRules();
143 }
144 });
Sangho Shin2f263692014-09-15 14:09:41 -0700145 }
146
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700147 @Override
148 public void receive(Switch sw, Port inPort, Ethernet payload) {
149 if (payload.getEtherType() == Ethernet.TYPE_ARP)
150 arpHandler.processPacketIn(sw, inPort, payload);
151 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Sangho Shin463bee52014-09-29 15:14:43 -0700152 addPacket((IPv4)payload.getPayload());
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700153 if (((IPv4)payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700154 icmpHandler.processPacketIn(sw, inPort, payload);
155 else
156 ipHandler.processPacketIn(sw, inPort, payload);
157 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700158 else {
159 log.debug("{}", payload.toString());
160 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700161 }
Sangho Shin2f263692014-09-15 14:09:41 -0700162 /**
163 * Update ARP Cache using ARP packets
164 * It is used to set destination MAC address to forward packets to known hosts.
165 * But, it will be replace with Host information of Topology service later.
166 *
167 * @param arp APR packets to use for updating ARP entries
168 */
169 public void updateArpCache(ARP arp) {
170
171 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(), arp.getSenderProtocolAddress());
172 // TODO: Need to check the duplication
173 arpEntries.add(arpEntry);
174 }
175
176 /**
177 * Get MAC address to known hosts
178 *
179 * @param destinationAddress IP address to get MAC address
180 * @return MAC Address to given IP address
181 */
182 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
183
184 // Can't we get the host IP address from the TopologyService ??
185
186 Iterator<ArpEntry> iterator = arpEntries.iterator();
187
188 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
189 byte[] ipAddressInByte = ipAddress.getBytes();
190
191 while (iterator.hasNext() ) {
192 ArpEntry arpEntry = iterator.next();
193 byte[] address = arpEntry.targetIpAddress;
194
195 IPv4Address a = IPv4Address.of(address);
196 IPv4Address b = IPv4Address.of(ipAddressInByte);
197
198 if ( a.equals(b)) {
199 log.debug("Found an arp entry");
200 return arpEntry.targetMacAddress;
201 }
202 }
203
204 return null;
205 }
206
Sangho Shineb083032014-09-22 16:11:34 -0700207 /**
208 * Send an ARP request via ArpHandler
209 * @param destinationAddress
210 * @param sw
211 * @param inPort
212 *
213 */
214 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
215 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
216 }
Sangho Shin2f263692014-09-15 14:09:41 -0700217
218 /**
219 * Temporary class to to keep ARP entry
220 *
221 */
222 private class ArpEntry {
223
224 byte[] targetMacAddress;
225 byte[] targetIpAddress;
226
227 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
228 this.targetMacAddress = macAddress;
229 this.targetIpAddress = ipAddress;
230 }
Sangho Shin2f263692014-09-15 14:09:41 -0700231 }
Sangho Shineb083032014-09-22 16:11:34 -0700232
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700233 /**
234 * Topology events that have been generated.
235 *
236 * @param topologyEvents the generated Topology Events
237 * @see TopologyEvents
238 */
239 public void topologyEvents(TopologyEvents topologyEvents)
240 {
Sangho Shin43cee112014-09-25 16:43:34 -0700241 if ((topologyEvents.getAddedLinkDataEntries() != null) ||
242 (topologyEvents.getRemovedLinkDataEntries() != null))
243 {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700244 discoveryTask.reschedule(1, TimeUnit.SECONDS);
245 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700246
247 Collection<PortData> portEntries =
248 topologyEvents.getRemovedPortDataEntries();
249 if (!portEntries.isEmpty()) {
250 // report port removal to the driver
251 for (PortData port: portEntries) {
252 Dpid dpid = port.getDpid();
253 int portNo = (int) port.getPortNumber().value();
254 log.debug("Remove port {} from switch {}", portNo, dpid.toString());
255 }
256 }
257
258 Collection<LinkData> linkEntries =
259 topologyEvents.getRemovedLinkDataEntries();
260 if (!linkEntries.isEmpty()) {
261 for (LinkData link: linkEntries) {
262 Dpid srcSwDpid = link.getSrc().getDpid();
263 Dpid dstSwDpid = link.getDst().getDpid();
264
265 Switch srcSwitch = mutableTopology.getSwitch(srcSwDpid);
266 Switch dstSwitch = mutableTopology.getSwitch(dstSwDpid);
267
268
269 }
270 }
271
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700272 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700273
274 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700275 * Populate routing rules walking through the ECMP shortest paths
Sangho Shin1aa93542014-09-22 09:49:44 -0700276 *
Sangho Shin1aa93542014-09-22 09:49:44 -0700277 */
Sangho Shin43cee112014-09-25 16:43:34 -0700278 private void populateEcmpRoutingRules() {
Sangho Shin1aa93542014-09-22 09:49:44 -0700279
Sangho Shin43cee112014-09-25 16:43:34 -0700280 Iterable<Switch> switches= mutableTopology.getSwitches();
281 for (Switch sw : switches) {
282 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
283 log.debug("ECMPShortestPathGraph is computed for switch {}",
284 HexString.toHexString(sw.getDpid().value()));
Sangho Shin1aa93542014-09-22 09:49:44 -0700285
Sangho Shin43cee112014-09-25 16:43:34 -0700286 HashMap<Integer, HashMap<Switch,ArrayList<ArrayList<Dpid>>>> switchVia =
287 ecmpSPG.getAllLearnedSwitchesAndVia();
288 for (Integer itrIdx: switchVia.keySet()){
289 log.debug("ECMPShortestPathGraph:Switches learned in "
290 + "Iteration{} from switch {}:",
291 itrIdx,
292 HexString.toHexString(sw.getDpid().value()));
293 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
294 switchVia.get(itrIdx);
295 for (Switch targetSw: swViaMap.keySet()){
296 log.debug("ECMPShortestPathGraph:****switch {} via:",
297 HexString.toHexString(targetSw.getDpid().value()));
298 String destSw = sw.getDpid().toString();
299 List<String> fwdToSw = new ArrayList<String>();
300
301 int i=0;
302 for (ArrayList<Dpid> via:swViaMap.get(targetSw)){
303 log.debug("ECMPShortestPathGraph:******{}) {}",++i,via);
304 if (via.isEmpty()) {
305 fwdToSw.add(destSw);
306 }
307 else {
308 fwdToSw.add(via.get(0).toString());
309 }
310 }
311 setRoutingRule(targetSw, destSw, fwdToSw);
312 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700313
314 // Send Barrier Message and make sure all rules are set
315 // before we set the rules to next routers
316 IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
317 getSwId(sw.getDpid().toString()));
318 try {
319 OFBarrierReplyFuture replyFuture = sw13.sendBarrier();
320 replyFuture.get(10, TimeUnit.SECONDS);
321 } catch (IOException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700322 e.printStackTrace();
323 }
324 catch (InterruptedException | ExecutionException | TimeoutException e) {
325 log.error("Barrier message not received for sw: {}", sw.getDpid());
326 e.printStackTrace();
327 }
Sangho Shineb083032014-09-22 16:11:34 -0700328 }
329 }
Sangho Shin43cee112014-09-25 16:43:34 -0700330 }
331
332 /**
333 *
334 * Set routing rules in targetSw
335 * {forward packets to fwdToSw switches in order to send packets to destSw}
336 * - If the target switch is an edge router and final destnation switch is also
337 * an edge router, then set IP forwarding rules to subnets
338 * - If only the target switch is an edge router, then set IP forwarding rule to
339 * the transit router loopback IP address
340 * - If the target is a transit router, then just set the MPLS forwarding rule
341 *
342 * @param targetSw Switch to set the rules
343 * @param destSw Final destination switches
344 * @param fwdToSw next hop switches
345 */
346 private void setRoutingRule(Switch targetSw, String destSw, List<String> fwdToSw) {
347
348
349 if (fwdToSw.isEmpty()) {
350 fwdToSw.add(destSw);
351 }
352
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700353 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700354 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
355 IsEdgeRouter(destSw)) {
356 // We assume that there is at least one transit router b/w edge routers
357 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
358 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700359 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
360 ,fwdToSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700361
Sangho Shin43cee112014-09-25 16:43:34 -0700362 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700363 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw, null);
Sangho Shin43cee112014-09-25 16:43:34 -0700364 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700365 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700366 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
367 // We assume that there is at least one transit router b/w edge routers
368 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
369 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700370 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw, null);
Sangho Shin43cee112014-09-25 16:43:34 -0700371 }
372 // if it is a transit router, then set rules in the MPLS table
373 else {
374 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw);
375 }
376
377 }
378
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700379 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
380 String mplsLabel, List<String> fwdToSw) {
381
382 Collection <MatchActionOperationEntry> entries =
383 new ArrayList<MatchActionOperationEntry>();
384
385 try {
386 JSONArray arry = new JSONArray(subnets);
387 for (int i = 0; i < arry.length(); i++) {
388 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
389 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries);
390 }
391 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700392 e.printStackTrace();
393 }
394
395 if (!entries.isEmpty()) {
396 IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
397 getSwId(targetSw.getDpid().toString()));
398
399 try {
400 sw13.pushFlows(entries);
401 } catch (IOException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700402 e.printStackTrace();
403 }
404 }
405
406 }
407
Sangho Shin43cee112014-09-25 16:43:34 -0700408 /**
409 * Check if the switch is the edge router or not
410 * If any subnet information is defined in the config file, the we assume
411 * it is an edge router
412 *
413 * @param dpid Dpid of the switch to check
414 * @return true if it is an edge router, otherwise false
415 */
416 private boolean IsEdgeRouter(String dpid) {
417
418 for (Switch sw: mutableTopology.getSwitches()) {
419 String dpidStr = sw.getDpid().toString();
420 if (dpid.equals(dpidStr)) {
421 String subnetInfo = sw.getStringAttribute("subnets");
422 if (subnetInfo == null || subnetInfo.equals("[]")) {
423 return false;
424 }
425 else
426 return true;
427 }
428 }
429
430 return false;
431 }
432
433 /**
434 * Set IP forwarding rule
435 * - If the destination is the next hop, then do not push MPLS,
436 * just decrease the NW TTL
437 * - Otherwise, push MPLS label and set the MPLS ID
438 *
439 * @param sw target switch to set rules
440 * @param subnetIp Match IP address
441 * @param mplsLabel MPLS label of final destination router
442 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700443 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700444 */
445 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700446 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries) {
Sangho Shin43cee112014-09-25 16:43:34 -0700447
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700448 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700449 List<Action> actions = new ArrayList<>();
450
451 // If destination SW is the same as the fwd SW, then do not push MPLS label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700452
453 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700454 PushMplsAction pushMplsAction = new PushMplsAction();
455 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
456 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700457 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700458
459 actions.add(pushMplsAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700460 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700461 actions.add(decMplsTtlAction);
462 actions.add(setIdAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700463 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700464 else {
465 String fwdToSw = fwdToSws.get(0);
466 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
467 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
468 actions.add(decTtlAction);
469 }
470 else {
471 PushMplsAction pushMplsAction = new PushMplsAction();
472 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
473 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700474 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700475
476 actions.add(pushMplsAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700477 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700478 actions.add(decMplsTtlAction);
479 actions.add(setIdAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700480 }
481 }
Sangho Shin43cee112014-09-25 16:43:34 -0700482
483 GroupAction groupAction = new GroupAction();
484
485 for (String fwdSw : fwdToSws) {
486 groupAction.addSwitch(new Dpid(fwdSw));
487 }
488 actions.add(groupAction);
489
Sangho Shinc8d2f592014-09-30 16:53:57 -0700490 // TODO: Mactch Action Id should be set correctly
Sangho Shin43cee112014-09-25 16:43:34 -0700491 MatchAction matchAction = new MatchAction(new MatchActionId(0),
492 new SwitchPort((long)0,(short)0), ipMatch, actions);
493
494 MatchActionOperationEntry maEntry =
495 new MatchActionOperationEntry(
496 net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
497 matchAction);
498
Sangho Shin463bee52014-09-29 15:14:43 -0700499 IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700500 getSwId(sw.getDpid().toString()));
501
502 try {
503 printMatchActionOperationEntry(sw, maEntry);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700504 if (entries != null)
505 entries.add(maEntry);
506 else
507 sw13.pushFlow(maEntry);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700508 } catch (IOException e) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700509 e.printStackTrace();
510 }
511
Sangho Shin43cee112014-09-25 16:43:34 -0700512 }
513
514
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700515 /**
516 * Convert a string DPID to its Switch Id (integer)
517 *
518 * @param dpid
519 * @return
520 */
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700521 private long getSwId(String dpid) {
522
523 long swId = 0;
524
525 String swIdStr = dpid.substring(dpid.lastIndexOf(":")+1);
526 if (swIdStr != null)
527 swId = Integer.parseInt(swIdStr);
528
529 return swId;
530 }
531
Sangho Shin43cee112014-09-25 16:43:34 -0700532 /**
533 * Set MPLS forwarding rules to MPLS table
534 * - If the destination is the same as the next hop to forward packets
535 * then, pop the MPLS label according to PHP rule
536 * - Otherwise, just forward packets to next hops using Group action
537 *
538 * @param sw Switch to set the rules
539 * @param mplsLabel destination MPLS label
540 * @param fwdSws next hop switches
541 */
542 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws) {
Sangho Shin463bee52014-09-29 15:14:43 -0700543
Sangho Shin43cee112014-09-25 16:43:34 -0700544 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel));
545
546 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700547
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700548 // If the destination is the same as the next hop, then pop MPLS
Sangho Shinc8d2f592014-09-30 16:53:57 -0700549 // Otherwise, just decrease the MPLS TTL.
Sangho Shin463bee52014-09-29 15:14:43 -0700550 if (fwdSws.size() == 1) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700551 String fwdMplsId = getMplsLabel(fwdSws.get(0));
552 if (fwdMplsId.equals(mplsLabel)) {
553 String fwdSw = fwdSws.get(0);
554 if (mplsLabel.equals(getMplsLabel(fwdSw))) {
555 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
556 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700557 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700558
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700559 actions.add(copyTtlInAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700560 actions.add(popAction);
561 actions.add(decNwTtlAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700562 }
563 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700564 else {
565 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
566 actions.add(decMplsTtlAction);
567 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700568 }
Sangho Shin43cee112014-09-25 16:43:34 -0700569 GroupAction groupAction = new GroupAction();
570 for (String fwdSw: fwdSws)
571 groupAction.addSwitch(new Dpid(fwdSw));
572 actions.add(groupAction);
573
574 MatchAction matchAction = new MatchAction(new MatchActionId(0),
575 new SwitchPort((long)0,(short)0), mplsMatch, actions);
576
577 MatchActionOperationEntry maEntry =
578 new MatchActionOperationEntry(
579 net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
580 matchAction);
581
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700582 IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
583 getSwId(sw.getDpid().toString()));
584
585 try {
586 printMatchActionOperationEntry(sw, maEntry);
587 sw13.pushFlow(maEntry);
588 } catch (IOException e) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700589 e.printStackTrace();
590 }
591
Sangho Shin43cee112014-09-25 16:43:34 -0700592 }
593
594
595 /**
596 * Debugging function to print out the Match Action Entry
597 *
598 * @param maEntry
599 */
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700600 private void printMatchActionOperationEntry(Switch sw,
601 MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -0700602
Sangho Shin0df01982014-09-25 17:11:18 -0700603 StringBuilder logStr = new StringBuilder("In switch " + sw.getDpid() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -0700604
605 MatchAction ma = maEntry.getTarget();
606 Match m = ma.getMatch();
607 List<Action> actions = ma.getActions();
608
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700609 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -0700610 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700611 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -0700612 logStr.append(ip.toString());
613 logStr.append(" then ");
614 }
615 else if (m instanceof MplsMatch) {
616 logStr.append("If the MPLS label matches with ");
617 int mplsLabel = ((MplsMatch) m).getMplsLabel();
618 logStr.append(mplsLabel);
619 logStr.append(" then ");
620 }
621
622 logStr.append(" do { ");
623 for (Action action: actions) {
624 if (action instanceof CopyTtlInAction) {
625 logStr.append("copy ttl In, ");
626 }
627 else if (action instanceof CopyTtlOutAction) {
628 logStr.append("copy ttl Out, ");
629 }
630 else if (action instanceof DecMplsTtlAction) {
631 logStr.append("Dec MPLS TTL , ");
632 }
633 else if (action instanceof GroupAction) {
634 logStr.append("Forward packet to < ");
Sangho Shin0df01982014-09-25 17:11:18 -0700635 NeighborSet dpids = ((GroupAction)action).getDpids();
636 logStr.append(dpids.toString() + ",");
637
Sangho Shin43cee112014-09-25 16:43:34 -0700638 }
639 else if (action instanceof PopMplsAction) {
640 logStr.append("Pop MPLS label, ");
641 }
642 else if (action instanceof PushMplsAction) {
643 logStr.append("Push MPLS label, ");
644 }
645 else if (action instanceof SetMplsIdAction) {
646 int id = ((SetMplsIdAction)action).getMplsId();
647 logStr.append("Set MPLS ID as " + id + ", ");
648
649 }
650 }
651
652 log.debug(logStr.toString());
653
Sangho Shineb083032014-09-22 16:11:34 -0700654 }
655
656 /**
657 * Get MPLS label reading the config file
658 *
659 * @param dipid DPID of the switch
660 * @return MPLS label for the switch
661 */
662
Sangho Shin43cee112014-09-25 16:43:34 -0700663 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -0700664
665 String mplsLabel = null;
666 for (Switch sw: mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700667 String dpidStr = sw.getDpid().toString();
668 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -0700669 mplsLabel = sw.getStringAttribute("nodeSid");
670 break;
Sangho Shin1aa93542014-09-22 09:49:44 -0700671 }
672 }
673
Sangho Shineb083032014-09-22 16:11:34 -0700674 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -0700675 }
676
Sangho Shineb083032014-09-22 16:11:34 -0700677
678
679 /**
Sangho Shin1aa93542014-09-22 09:49:44 -0700680 * The function checks if given IP matches to the given subnet mask
681 *
682 * @param addr - subnet address to match
683 * @param addr1 - IP address to check
684 * @return true if the IP address matches to the subnet, otherwise false
685 */
Sangho Shin1aa93542014-09-22 09:49:44 -0700686 public boolean netMatch(String addr, String addr1){ //addr is subnet address and addr1 is ip address. Function will return true, if addr1 is within addr(subnet)
687
688 String[] parts = addr.split("/");
689 String ip = parts[0];
690 int prefix;
691
692 if (parts.length < 2) {
693 prefix = 0;
694 } else {
695 prefix = Integer.parseInt(parts[1]);
696 }
697
698 Inet4Address a =null;
699 Inet4Address a1 =null;
700 try {
701 a = (Inet4Address) InetAddress.getByName(ip);
702 a1 = (Inet4Address) InetAddress.getByName(addr1);
703 } catch (UnknownHostException e){}
704
705 byte[] b = a.getAddress();
706 int ipInt = ((b[0] & 0xFF) << 24) |
707 ((b[1] & 0xFF) << 16) |
708 ((b[2] & 0xFF) << 8) |
709 ((b[3] & 0xFF) << 0);
710
711 byte[] b1 = a1.getAddress();
712 int ipInt1 = ((b1[0] & 0xFF) << 24) |
713 ((b1[1] & 0xFF) << 16) |
714 ((b1[2] & 0xFF) << 8) |
715 ((b1[3] & 0xFF) << 0);
716
717 int mask = ~((1 << (32 - prefix)) - 1);
718
719 if ((ipInt & mask) == (ipInt1 & mask)) {
720 return true;
721 }
722 else {
723 return false;
724 }
725 }
Sangho Shineb083032014-09-22 16:11:34 -0700726
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700727 /**
728 * Add a routing rule for the host
729 *
730 * @param sw - Switch to add the rule
731 * @param hostIpAddress Destination host IP address
732 * @param hostMacAddress Destination host MAC address
733 */
Sangho Shineb083032014-09-22 16:11:34 -0700734 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
735 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
736
737 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700738
Sangho Shin463bee52014-09-29 15:14:43 -0700739 /**
740 * Add IP packet to a buffer queue
741 *
742 * @param ipv4
743 */
744 public void addPacket(IPv4 ipv4) {
745 synchronized (ipPacketQueue) {
746 ipPacketQueue.add(ipv4);
747 }
748 }
749
750 /**
751 * Retrieve all packets whose destination is the given address.
752 *
753 * @param destIp Destination address of packets to retrieve
754 */
755 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
756
757 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
758
759 synchronized (ipPacketQueue) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700760 if (!ipPacketQueue.isEmpty()) {
761 for (IPv4 ip: ipPacketQueue) {
762 int dest = ip.getDestinationAddress();
763 IPv4Address ip1 = IPv4Address.of(dest);
764 IPv4Address ip2 = IPv4Address.of(destIp);
765 if (ip1.equals(ip2)) {
766 bufferedPackets.add((IPv4)(ipPacketQueue.poll()).clone());
767 }
Sangho Shin463bee52014-09-29 15:14:43 -0700768 }
769 }
770 }
771
772 return bufferedPackets;
773 }
774
Sangho Shin2f263692014-09-15 14:09:41 -0700775}