blob: 513b3d656f5acddd2c9120a09d3b47d453f58a5d [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;
11import java.util.List;
12import java.util.Map;
Sangho Shin61535402014-10-01 11:37:14 -070013import java.util.concurrent.ConcurrentLinkedQueue;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070014import java.util.concurrent.ExecutionException;
Sangho Shin43cee112014-09-25 16:43:34 -070015import java.util.concurrent.ScheduledExecutorService;
16import java.util.concurrent.TimeUnit;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070017import java.util.concurrent.TimeoutException;
Sangho Shin2f263692014-09-15 14:09:41 -070018
19import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070020import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070021import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin11d4e0f2014-09-30 12:00:33 -070022import net.floodlightcontroller.core.internal.OFBarrierReplyFuture;
Sangho Shin2f263692014-09-15 14:09:41 -070023import net.floodlightcontroller.core.module.FloodlightModuleContext;
24import net.floodlightcontroller.core.module.FloodlightModuleException;
25import net.floodlightcontroller.core.module.IFloodlightModule;
26import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070027import net.floodlightcontroller.core.util.SingletonTask;
28import net.floodlightcontroller.threadpool.IThreadPoolService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070029import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070030import net.onrc.onos.api.packet.IPacketService;
31import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
Sangho Shinfbc572c2014-10-02 16:37:05 -070032import net.onrc.onos.core.intent.Path;
Sangho Shin2f263692014-09-15 14:09:41 -070033import 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,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -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 Shin61535402014-10-01 11:37:14 -070080 private ConcurrentLinkedQueue<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
Sangho Shinfbc572c2014-10-02 16:37:05 -070090 private HashMap<Switch, ECMPShortestPathGraph> graphs;
91
Sangho Shin2f263692014-09-15 14:09:41 -070092 @Override
93 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
94 // TODO Auto-generated method stub
95 return null;
96 }
97
98 @Override
99 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
100 // TODO Auto-generated method stub
101 return null;
102 }
103
104 @Override
105 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
106 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
107
108 l.add(IFloodlightProviderService.class);
109 l.add(IConfigInfoService.class);
110 l.add(ITopologyService.class);
111 l.add(IPacketService.class);
112 l.add(IFlowPusherService.class);
113 l.add(ITopologyService.class);
114
115 return l;
116
117 }
118
119 @Override
120 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700121 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700122 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700123 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700124 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700125 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700126 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700127 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700128 mutableTopology = topologyService.getTopology();
129 topologyService.addListener(this, false);
Sangho Shin61535402014-10-01 11:37:14 -0700130 ipPacketQueue = new ConcurrentLinkedQueue<IPv4>();
Sangho Shinfbc572c2014-10-02 16:37:05 -0700131 graphs = new HashMap<Switch, ECMPShortestPathGraph>();
Sangho Shin2f263692014-09-15 14:09:41 -0700132
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700133 this.packetService = context.getServiceImpl(IPacketService.class);
134 packetService.registerPacketListener(this);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700135
Sangho Shin2f263692014-09-15 14:09:41 -0700136 }
137
138 @Override
139 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shinc8d2f592014-09-30 16:53:57 -0700140 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
Sangho Shin2f263692014-09-15 14:09:41 -0700141
Sangho Shinc8d2f592014-09-30 16:53:57 -0700142 discoveryTask = new SingletonTask(ses, new Runnable() {
143 @Override
144 public void run() {
145 populateEcmpRoutingRules();
146 }
147 });
Sangho Shin2f263692014-09-15 14:09:41 -0700148 }
149
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700150 @Override
151 public void receive(Switch sw, Port inPort, Ethernet payload) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700152 if (payload.getEtherType() == Ethernet.TYPE_ARP)
153 arpHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700154 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700155 addPacket((IPv4) payload.getPayload());
156 if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
157 icmpHandler.processPacketIn(sw, inPort, payload);
158 else
159 ipHandler.processPacketIn(sw, inPort, payload);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700160 }
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700161 else {
162 log.debug("{}", payload.toString());
163 }
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700164 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700165
Sangho Shin2f263692014-09-15 14:09:41 -0700166 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700167 * Update ARP Cache using ARP packets It is used to set destination MAC
168 * address to forward packets to known hosts. But, it will be replace with
169 * Host information of Topology service later.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700170 *
Sangho Shin2f263692014-09-15 14:09:41 -0700171 * @param arp APR packets to use for updating ARP entries
172 */
173 public void updateArpCache(ARP arp) {
174
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700175 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
176 arp.getSenderProtocolAddress());
Sangho Shin2f263692014-09-15 14:09:41 -0700177 // TODO: Need to check the duplication
178 arpEntries.add(arpEntry);
179 }
180
181 /**
182 * Get MAC address to known hosts
Sangho Shinfbc572c2014-10-02 16:37:05 -0700183 *
Sangho Shin2f263692014-09-15 14:09:41 -0700184 * @param destinationAddress IP address to get MAC address
185 * @return MAC Address to given IP address
186 */
187 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
188
189 // Can't we get the host IP address from the TopologyService ??
190
191 Iterator<ArpEntry> iterator = arpEntries.iterator();
192
193 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
194 byte[] ipAddressInByte = ipAddress.getBytes();
195
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700196 while (iterator.hasNext()) {
Sangho Shin2f263692014-09-15 14:09:41 -0700197 ArpEntry arpEntry = iterator.next();
198 byte[] address = arpEntry.targetIpAddress;
199
200 IPv4Address a = IPv4Address.of(address);
201 IPv4Address b = IPv4Address.of(ipAddressInByte);
202
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700203 if (a.equals(b)) {
Sangho Shin2f263692014-09-15 14:09:41 -0700204 log.debug("Found an arp entry");
205 return arpEntry.targetMacAddress;
206 }
207 }
208
209 return null;
210 }
211
Sangho Shineb083032014-09-22 16:11:34 -0700212 /**
213 * Send an ARP request via ArpHandler
Sangho Shinfbc572c2014-10-02 16:37:05 -0700214 *
Sangho Shineb083032014-09-22 16:11:34 -0700215 * @param destinationAddress
216 * @param sw
217 * @param inPort
Sangho Shinfbc572c2014-10-02 16:37:05 -0700218 *
Sangho Shineb083032014-09-22 16:11:34 -0700219 */
220 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
221 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
222 }
Sangho Shin2f263692014-09-15 14:09:41 -0700223
224 /**
225 * Temporary class to to keep ARP entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700226 *
Sangho Shin2f263692014-09-15 14:09:41 -0700227 */
228 private class ArpEntry {
229
230 byte[] targetMacAddress;
231 byte[] targetIpAddress;
232
233 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
234 this.targetMacAddress = macAddress;
235 this.targetIpAddress = ipAddress;
236 }
Sangho Shin2f263692014-09-15 14:09:41 -0700237 }
Sangho Shineb083032014-09-22 16:11:34 -0700238
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700239 /**
240 * Topology events that have been generated.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700241 *
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700242 * @param topologyEvents the generated Topology Events
243 * @see TopologyEvents
244 */
245 public void topologyEvents(TopologyEvents topologyEvents)
246 {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700247
248 Collection<LinkData> linkEntriesAdded =
249 topologyEvents.getAddedLinkDataEntries();
250 if (!linkEntriesAdded.isEmpty()) {
251 processLinkAdd(linkEntriesAdded);
252 }
253
254 Collection<PortData> PortEntriesAdded =
255 topologyEvents.getAddedPortDataEntries();
256 if (linkEntriesAdded != null) {
257 processPortAdd(PortEntriesAdded);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700258 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700259
260 Collection<PortData> portEntries =
261 topologyEvents.getRemovedPortDataEntries();
262 if (!portEntries.isEmpty()) {
Sangho Shin61535402014-10-01 11:37:14 -0700263 processPortRemoval(portEntries);
Sangho Shinc8d2f592014-09-30 16:53:57 -0700264 }
265
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700266 Collection<LinkData> linkEntriesRemoved =
Sangho Shinc8d2f592014-09-30 16:53:57 -0700267 topologyEvents.getRemovedLinkDataEntries();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700268 if (!linkEntriesRemoved.isEmpty()) {
269 processLinkRemoval(linkEntriesRemoved);
Sangho Shin61535402014-10-01 11:37:14 -0700270 }
271 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700272
Sangho Shin61535402014-10-01 11:37:14 -0700273 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700274 * Report ports newly added to driver
Sangho Shinfbc572c2014-10-02 16:37:05 -0700275 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700276 * @param portEntries
277 */
278 private void processPortAdd(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700279 // TODO: do we need to add ports slowly?
280 for (PortData port : portEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700281 Dpid dpid = port.getDpid();
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700282
Sangho Shinfbc572c2014-10-02 16:37:05 -0700283 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700284 getSwId(port.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700285 sw.addPortToGroups(port.getPortNumber());
286
287 log.debug("Add port {} to switch {}", port, dpid);
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700288 }
289 }
290
291 /**
292 * Reports ports of new links to driver and recalculate ECMP SPG
Sangho Shinfbc572c2014-10-02 16:37:05 -0700293 *
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700294 * @param linkEntries
295 */
296 private void processLinkAdd(Collection<LinkData> linkEntries) {
297
298 // TODO: How to determine this link was broken before and back now
299 // If so, we need to ad the link slowly...
300 // Or, just add any new or restored link slowly ???
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700301 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700302 SwitchPort srcPort = link.getSrc();
303 SwitchPort dstPort = link.getDst();
304
Sangho Shinfbc572c2014-10-02 16:37:05 -0700305 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700306 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700307 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700308 getSwId(srcPort.getDpid().toString()));
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700309
Sangho Shinfbc572c2014-10-02 16:37:05 -0700310 srcSw.addPortToGroups(srcPort.getPortNumber());
311 dstSw.addPortToGroups(dstPort.getPortNumber());
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700312 }
313 discoveryTask.reschedule(1, TimeUnit.SECONDS);
314 }
315
316 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700317 * Check if all links are gone b/w the two switches. If all links are gone,
318 * then we need to recalculate the path. Otherwise, just report link failure
319 * to the driver.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700320 *
Sangho Shin61535402014-10-01 11:37:14 -0700321 * @param linkEntries
322 */
323 private void processLinkRemoval(Collection<LinkData> linkEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700324 for (LinkData link : linkEntries) {
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700325 SwitchPort srcPort = link.getSrc();
326 SwitchPort dstPort = link.getDst();
Sangho Shinc8d2f592014-09-30 16:53:57 -0700327
Sangho Shinfbc572c2014-10-02 16:37:05 -0700328 IOF13Switch srcSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700329 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700330 IOF13Switch dstSw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700331 getSwId(srcPort.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700332
333 // TODO: Why do we get null for the master switch??
334 if (srcSw != null)
335 srcSw.removePortFromGroups(srcPort.getPortNumber());
336 if (dstSw != null)
337 dstSw.removePortFromGroups(dstPort.getPortNumber());
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700338
339 Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
340 if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
Sangho Shinfbc572c2014-10-02 16:37:05 -0700341 //discoveryTask.reschedule(1, TimeUnit.SECONDS);
342 modifyEcmpRoutingRules(link);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700343 log.debug("All links are gone b/w {} and {}", srcPort.getDpid(),
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700344 srcPort.getDpid());
Sangho Shinc8d2f592014-09-30 16:53:57 -0700345 }
346 }
Sangho Shin61535402014-10-01 11:37:14 -0700347 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700348
Sangho Shin61535402014-10-01 11:37:14 -0700349 /**
Sangho Shin3a5fcad2014-10-01 14:14:49 -0700350 * report ports removed to the driver immediately
Sangho Shinfbc572c2014-10-02 16:37:05 -0700351 *
Sangho Shin61535402014-10-01 11:37:14 -0700352 * @param portEntries
353 */
354 private void processPortRemoval(Collection<PortData> portEntries) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700355 for (PortData port : portEntries) {
Sangho Shin61535402014-10-01 11:37:14 -0700356 Dpid dpid = port.getDpid();
Sangho Shin61535402014-10-01 11:37:14 -0700357
Sangho Shinfbc572c2014-10-02 16:37:05 -0700358 IOF13Switch sw = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin61535402014-10-01 11:37:14 -0700359 getSwId(port.getDpid().toString()));
Sangho Shinfbc572c2014-10-02 16:37:05 -0700360 if (sw != null)
361 sw.removePortFromGroups(port.getPortNumber());
362 log.debug("Remove port {} from switch {}", port, dpid);
Sangho Shin61535402014-10-01 11:37:14 -0700363 }
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700364 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700365
366 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700367 * Populate routing rules walking through the ECMP shortest paths
Sangho Shinfbc572c2014-10-02 16:37:05 -0700368 *
Sangho Shin1aa93542014-09-22 09:49:44 -0700369 */
Sangho Shin43cee112014-09-25 16:43:34 -0700370 private void populateEcmpRoutingRules() {
Sangho Shin1aa93542014-09-22 09:49:44 -0700371
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700372 Iterable<Switch> switches = mutableTopology.getSwitches();
Sangho Shin43cee112014-09-25 16:43:34 -0700373 for (Switch sw : switches) {
374 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Sangho Shinfbc572c2014-10-02 16:37:05 -0700375 graphs.put(sw, ecmpSPG);
376 //log.debug("ECMPShortestPathGraph is computed for switch {}",
377 // HexString.toHexString(sw.getDpid().value()));
378 populateEcmpRoutingRulesForPath(sw, ecmpSPG);
379 }
380 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700381
Sangho Shinfbc572c2014-10-02 16:37:05 -0700382 private void populateEcmpRoutingRulesForPath(Switch sw,
383 ECMPShortestPathGraph ecmpSPG) {
Sangho Shin43cee112014-09-25 16:43:34 -0700384
Sangho Shinfbc572c2014-10-02 16:37:05 -0700385 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
386 ecmpSPG.getAllLearnedSwitchesAndVia();
387 for (Integer itrIdx : switchVia.keySet()) {
388 //log.debug("ECMPShortestPathGraph:Switches learned in "
389 // + "Iteration{} from switch {}:",
390 // itrIdx,
391 // HexString.toHexString(sw.getDpid().value()));
392 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
393 switchVia.get(itrIdx);
394 for (Switch targetSw : swViaMap.keySet()) {
395 log.debug("ECMPShortestPathGraph:****switch {} via:",
396 HexString.toHexString(targetSw.getDpid().value()));
397 String destSw = sw.getDpid().toString();
398 List<String> fwdToSw = new ArrayList<String>();
399
400 int i = 0;
401 for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
402 log.debug("ECMPShortestPathGraph:******{}) {}", ++i, via);
403 if (via.isEmpty()) {
404 fwdToSw.add(destSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700405 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700406 else {
407 fwdToSw.add(via.get(0).toString());
408 }
Sangho Shin43cee112014-09-25 16:43:34 -0700409 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700410 setRoutingRule(targetSw, destSw, fwdToSw);
Sangho Shineb083032014-09-22 16:11:34 -0700411 }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700412
413 // Send Barrier Message and make sure all rules are set
414 // before we set the rules to next routers
415 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
416 getSwId(sw.getDpid().toString()));
417 try {
418 OFBarrierReplyFuture replyFuture = sw13.sendBarrier();
419 replyFuture.get(10, TimeUnit.SECONDS);
420 } catch (IOException e) {
421 e.printStackTrace();
422 } catch (InterruptedException | ExecutionException | TimeoutException e) {
423 log.error("Barrier message not received for sw: {}", sw.getDpid());
424 e.printStackTrace();
425 }
426 }
427
428 }
429
430
431 private class SwitchPair {
432 private Switch src;
433 private Switch dst;
434
435 public SwitchPair(Switch src, Switch dst) {
436 this.src = src;
437 this.dst = dst;
438 }
439
440 public Switch getSource() {
441 return src;
442 }
443
444 public Switch getDestination() {
445 return dst;
Sangho Shineb083032014-09-22 16:11:34 -0700446 }
Sangho Shin43cee112014-09-25 16:43:34 -0700447 }
448
449 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700450 * Modify the routing rules for the lost links
451 * - Recompute the path if the link failed is included in the path
452 * (including src and dest).
453 *
454 * @param newLink
455 */
456 private void modifyEcmpRoutingRules(LinkData linkRemoved) {
457
458 //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
459 List<SwitchPair> linksToRecompute = new ArrayList<SwitchPair>();
460
461 for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
462 Switch rootSw = ecmpSPG.getRootSwitch();
463 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
464 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
465 for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
466 for (Switch destSw: p.keySet()) {
467 ArrayList<Path> path = p.get(destSw);
468 if (checkPath(path, linkRemoved)) {
469 linksToRecompute.add(new SwitchPair(rootSw, destSw));
470 }
471 }
472 }
473 }
474
475 // Recompute the path for the specific route
476 for (SwitchPair pair: linksToRecompute) {
477
478 log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
479 // TODO : we need the following function
480 //ECMPShortestPathGraph ecmpSPG =
481 // new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
482 ECMPShortestPathGraph ecmpSPG =
483 new ECMPShortestPathGraph(pair.getSource());
484 // TODO: we need to use different function to MODIFY the rules
485 populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG);
486 }
487 }
488
489 /**
490 * Check if the path is affected from the link removed
491 *
492 * @param path Path to check
493 * @param linkRemoved link removed
494 * @return true if the path contains the link removed
495 */
496 private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
497
498 for (Path ppp: path) {
499 // TODO: need to check if this is a bidirectional or
500 // unidirectional
501 if (ppp.contains(linkRemoved)) {
502 return true;
503 }
504 }
505
506 return false;
507 }
508
509 /**
510 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700511 * Set routing rules in targetSw {forward packets to fwdToSw switches in
512 * order to send packets to destSw} - If the target switch is an edge router
513 * and final destnation switch is also an edge router, then set IP
514 * forwarding rules to subnets - If only the target switch is an edge
515 * router, then set IP forwarding rule to the transit router loopback IP
516 * address - If the target is a transit router, then just set the MPLS
517 * forwarding rule
Sangho Shinfbc572c2014-10-02 16:37:05 -0700518 *
Sangho Shin43cee112014-09-25 16:43:34 -0700519 * @param targetSw Switch to set the rules
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700520 * @param destSw Final destination switches
Sangho Shin43cee112014-09-25 16:43:34 -0700521 * @param fwdToSw next hop switches
522 */
523 private void setRoutingRule(Switch targetSw, String destSw, List<String> fwdToSw) {
524
Sangho Shin43cee112014-09-25 16:43:34 -0700525 if (fwdToSw.isEmpty()) {
526 fwdToSw.add(destSw);
527 }
528
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700529 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700530 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
531 IsEdgeRouter(destSw)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700532 // We assume that there is at least one transit router b/w edge
533 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700534 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
535 String subnets = destSwitch.getStringAttribute("subnets");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700536 setIpTableRouterSubnet(targetSw, subnets, getMplsLabel(destSw)
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700537 , fwdToSw);
Sangho Shin43cee112014-09-25 16:43:34 -0700538
Sangho Shin43cee112014-09-25 16:43:34 -0700539 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700540 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw, null);
Sangho Shin43cee112014-09-25 16:43:34 -0700541 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700542 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700543 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700544 // We assume that there is at least one transit router b/w edge
545 // routers
Sangho Shin43cee112014-09-25 16:43:34 -0700546 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
547 String routerIp = destSwitch.getStringAttribute("routerIp");
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700548 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw, null);
Sangho Shin43cee112014-09-25 16:43:34 -0700549 }
550 // if it is a transit router, then set rules in the MPLS table
551 else {
552 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw);
553 }
554
555 }
556
Sangho Shinfbc572c2014-10-02 16:37:05 -0700557 /**
558 * Set IP forwarding rule to the gateway of each subnet of switches
559 *
560 * @param targetSw Switch to set rules
561 * @param subnets subnet information
562 * @param mplsLabel destination MPLS label
563 * @param fwdToSw router to forward packets to
564 */
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700565 private void setIpTableRouterSubnet(Switch targetSw, String subnets,
566 String mplsLabel, List<String> fwdToSw) {
567
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700568 Collection<MatchActionOperationEntry> entries =
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700569 new ArrayList<MatchActionOperationEntry>();
570
571 try {
572 JSONArray arry = new JSONArray(subnets);
573 for (int i = 0; i < arry.length(); i++) {
574 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
575 setIpTableRouter(targetSw, subnetIp, mplsLabel, fwdToSw, entries);
576 }
577 } catch (JSONException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700578 e.printStackTrace();
579 }
580
581 if (!entries.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700582 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700583 getSwId(targetSw.getDpid().toString()));
584
585 try {
586 sw13.pushFlows(entries);
587 } catch (IOException e) {
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700588 e.printStackTrace();
589 }
590 }
591
592 }
593
Sangho Shin43cee112014-09-25 16:43:34 -0700594 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700595 * Check if the switch is the edge router or not If any subnet information
596 * is defined in the config file, the we assume it is an edge router
Sangho Shinfbc572c2014-10-02 16:37:05 -0700597 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700598 * @param dpid Dpid of the switch to check
Sangho Shin43cee112014-09-25 16:43:34 -0700599 * @return true if it is an edge router, otherwise false
600 */
601 private boolean IsEdgeRouter(String dpid) {
602
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700603 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700604 String dpidStr = sw.getDpid().toString();
605 if (dpid.equals(dpidStr)) {
606 String subnetInfo = sw.getStringAttribute("subnets");
607 if (subnetInfo == null || subnetInfo.equals("[]")) {
608 return false;
609 }
610 else
611 return true;
612 }
613 }
614
615 return false;
616 }
617
618 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700619 * Set IP forwarding rule - If the destination is the next hop, then do not
620 * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
621 * the MPLS ID
Sangho Shinfbc572c2014-10-02 16:37:05 -0700622 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700623 * @param sw target switch to set rules
Sangho Shin43cee112014-09-25 16:43:34 -0700624 * @param subnetIp Match IP address
625 * @param mplsLabel MPLS label of final destination router
626 * @param fwdToSws next hop routers
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700627 * @param entries
Sangho Shin43cee112014-09-25 16:43:34 -0700628 */
629 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700630 List<String> fwdToSws, Collection<MatchActionOperationEntry> entries) {
Sangho Shin43cee112014-09-25 16:43:34 -0700631
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700632 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700633 List<Action> actions = new ArrayList<>();
634
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700635 // If destination SW is the same as the fwd SW, then do not push MPLS
636 // label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700637
638 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700639 PushMplsAction pushMplsAction = new PushMplsAction();
640 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
641 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700642 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin43cee112014-09-25 16:43:34 -0700643
644 actions.add(pushMplsAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700645 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700646 actions.add(decMplsTtlAction);
647 actions.add(setIdAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700648 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700649 else {
650 String fwdToSw = fwdToSws.get(0);
651 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
652 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
653 actions.add(decTtlAction);
654 }
655 else {
656 PushMplsAction pushMplsAction = new PushMplsAction();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700657 SetMplsIdAction setIdAction = new SetMplsIdAction(
658 Integer.parseInt(mplsLabel));
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700659 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700660 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700661
662 actions.add(pushMplsAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700663 actions.add(copyTtlOutAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700664 actions.add(decMplsTtlAction);
665 actions.add(setIdAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700666 }
667 }
Sangho Shin43cee112014-09-25 16:43:34 -0700668
669 GroupAction groupAction = new GroupAction();
670
671 for (String fwdSw : fwdToSws) {
672 groupAction.addSwitch(new Dpid(fwdSw));
673 }
674 actions.add(groupAction);
675
Sangho Shinc8d2f592014-09-30 16:53:57 -0700676 // TODO: Mactch Action Id should be set correctly
Sangho Shin43cee112014-09-25 16:43:34 -0700677 MatchAction matchAction = new MatchAction(new MatchActionId(0),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700678 new SwitchPort((long) 0, (short) 0), ipMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700679
680 MatchActionOperationEntry maEntry =
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700681 new MatchActionOperationEntry(
682 net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
683 matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700684
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700685 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700686 getSwId(sw.getDpid().toString()));
687
688 try {
689 printMatchActionOperationEntry(sw, maEntry);
Sangho Shin11d4e0f2014-09-30 12:00:33 -0700690 if (entries != null)
691 entries.add(maEntry);
692 else
693 sw13.pushFlow(maEntry);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700694 } catch (IOException e) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700695 e.printStackTrace();
696 }
697
Sangho Shin43cee112014-09-25 16:43:34 -0700698 }
699
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700700 /**
701 * Convert a string DPID to its Switch Id (integer)
Sangho Shinfbc572c2014-10-02 16:37:05 -0700702 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700703 * @param dpid
704 * @return
705 */
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700706 private long getSwId(String dpid) {
707
708 long swId = 0;
709
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700710 String swIdStr = dpid.substring(dpid.lastIndexOf(":") + 1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700711 if (swIdStr != null)
712 swId = Integer.parseInt(swIdStr);
713
714 return swId;
715 }
716
Sangho Shin43cee112014-09-25 16:43:34 -0700717 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700718 * Set MPLS forwarding rules to MPLS table - If the destination is the same
719 * as the next hop to forward packets then, pop the MPLS label according to
720 * PHP rule - Otherwise, just forward packets to next hops using Group
721 * action
Sangho Shinfbc572c2014-10-02 16:37:05 -0700722 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700723 * @param sw Switch to set the rules
Sangho Shin43cee112014-09-25 16:43:34 -0700724 * @param mplsLabel destination MPLS label
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700725 * @param fwdSws next hop switches
Sangho Shin43cee112014-09-25 16:43:34 -0700726 */
727 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws) {
Sangho Shin463bee52014-09-29 15:14:43 -0700728
Sangho Shin43cee112014-09-25 16:43:34 -0700729 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel));
730
731 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700732
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700733 // If the destination is the same as the next hop, then pop MPLS
Sangho Shinc8d2f592014-09-30 16:53:57 -0700734 // Otherwise, just decrease the MPLS TTL.
Sangho Shin463bee52014-09-29 15:14:43 -0700735 if (fwdSws.size() == 1) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700736 String fwdMplsId = getMplsLabel(fwdSws.get(0));
737 if (fwdMplsId.equals(mplsLabel)) {
738 String fwdSw = fwdSws.get(0);
739 if (mplsLabel.equals(getMplsLabel(fwdSw))) {
740 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
741 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
Sangho Shin463bee52014-09-29 15:14:43 -0700742 DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700743
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700744 actions.add(copyTtlInAction);
Sangho Shin463bee52014-09-29 15:14:43 -0700745 actions.add(popAction);
746 actions.add(decNwTtlAction);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700747 }
748 }
Sangho Shinc8d2f592014-09-30 16:53:57 -0700749 else {
750 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
751 actions.add(decMplsTtlAction);
752 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700753 }
Sangho Shin43cee112014-09-25 16:43:34 -0700754 GroupAction groupAction = new GroupAction();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700755 for (String fwdSw : fwdSws)
Sangho Shin43cee112014-09-25 16:43:34 -0700756 groupAction.addSwitch(new Dpid(fwdSw));
757 actions.add(groupAction);
758
759 MatchAction matchAction = new MatchAction(new MatchActionId(0),
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700760 new SwitchPort((long) 0, (short) 0), mplsMatch, actions);
Sangho Shin43cee112014-09-25 16:43:34 -0700761
762 MatchActionOperationEntry maEntry =
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700763 new MatchActionOperationEntry(
764 net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
765 matchAction);
Sangho Shin43cee112014-09-25 16:43:34 -0700766
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700767 IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700768 getSwId(sw.getDpid().toString()));
769
770 try {
771 printMatchActionOperationEntry(sw, maEntry);
772 sw13.pushFlow(maEntry);
773 } catch (IOException e) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700774 e.printStackTrace();
775 }
776
Sangho Shin43cee112014-09-25 16:43:34 -0700777 }
778
Sangho Shin43cee112014-09-25 16:43:34 -0700779 /**
780 * Debugging function to print out the Match Action Entry
Sangho Shinfbc572c2014-10-02 16:37:05 -0700781 *
Sangho Shin43cee112014-09-25 16:43:34 -0700782 * @param maEntry
783 */
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700784 private void printMatchActionOperationEntry(Switch sw,
785 MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -0700786
Sangho Shin0df01982014-09-25 17:11:18 -0700787 StringBuilder logStr = new StringBuilder("In switch " + sw.getDpid() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -0700788
789 MatchAction ma = maEntry.getTarget();
790 Match m = ma.getMatch();
791 List<Action> actions = ma.getActions();
792
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700793 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -0700794 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700795 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -0700796 logStr.append(ip.toString());
797 logStr.append(" then ");
798 }
799 else if (m instanceof MplsMatch) {
800 logStr.append("If the MPLS label matches with ");
801 int mplsLabel = ((MplsMatch) m).getMplsLabel();
802 logStr.append(mplsLabel);
803 logStr.append(" then ");
804 }
805
806 logStr.append(" do { ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700807 for (Action action : actions) {
Sangho Shin43cee112014-09-25 16:43:34 -0700808 if (action instanceof CopyTtlInAction) {
809 logStr.append("copy ttl In, ");
810 }
811 else if (action instanceof CopyTtlOutAction) {
812 logStr.append("copy ttl Out, ");
813 }
814 else if (action instanceof DecMplsTtlAction) {
815 logStr.append("Dec MPLS TTL , ");
816 }
817 else if (action instanceof GroupAction) {
818 logStr.append("Forward packet to < ");
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700819 NeighborSet dpids = ((GroupAction) action).getDpids();
Sangho Shin0df01982014-09-25 17:11:18 -0700820 logStr.append(dpids.toString() + ",");
821
Sangho Shin43cee112014-09-25 16:43:34 -0700822 }
823 else if (action instanceof PopMplsAction) {
824 logStr.append("Pop MPLS label, ");
825 }
826 else if (action instanceof PushMplsAction) {
827 logStr.append("Push MPLS label, ");
828 }
829 else if (action instanceof SetMplsIdAction) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700830 int id = ((SetMplsIdAction) action).getMplsId();
Sangho Shin43cee112014-09-25 16:43:34 -0700831 logStr.append("Set MPLS ID as " + id + ", ");
832
833 }
834 }
835
836 log.debug(logStr.toString());
837
Sangho Shineb083032014-09-22 16:11:34 -0700838 }
839
840 /**
841 * Get MPLS label reading the config file
Sangho Shinfbc572c2014-10-02 16:37:05 -0700842 *
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700843 * @param dipid DPID of the switch
Sangho Shineb083032014-09-22 16:11:34 -0700844 * @return MPLS label for the switch
845 */
846
Sangho Shin43cee112014-09-25 16:43:34 -0700847 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -0700848
849 String mplsLabel = null;
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700850 for (Switch sw : mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700851 String dpidStr = sw.getDpid().toString();
852 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -0700853 mplsLabel = sw.getStringAttribute("nodeSid");
854 break;
Sangho Shin1aa93542014-09-22 09:49:44 -0700855 }
856 }
857
Sangho Shineb083032014-09-22 16:11:34 -0700858 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -0700859 }
860
Sangho Shineb083032014-09-22 16:11:34 -0700861 /**
Sangho Shin1aa93542014-09-22 09:49:44 -0700862 * The function checks if given IP matches to the given subnet mask
Sangho Shinfbc572c2014-10-02 16:37:05 -0700863 *
Sangho Shin1aa93542014-09-22 09:49:44 -0700864 * @param addr - subnet address to match
865 * @param addr1 - IP address to check
866 * @return true if the IP address matches to the subnet, otherwise false
867 */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700868 public boolean netMatch(String addr, String addr1) { // addr is subnet
869 // address and addr1 is
870 // ip address. Function
871 // will return true, if
872 // addr1 is within
873 // addr(subnet)
Sangho Shin1aa93542014-09-22 09:49:44 -0700874
875 String[] parts = addr.split("/");
876 String ip = parts[0];
877 int prefix;
878
879 if (parts.length < 2) {
880 prefix = 0;
881 } else {
882 prefix = Integer.parseInt(parts[1]);
883 }
884
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700885 Inet4Address a = null;
886 Inet4Address a1 = null;
Sangho Shin1aa93542014-09-22 09:49:44 -0700887 try {
888 a = (Inet4Address) InetAddress.getByName(ip);
889 a1 = (Inet4Address) InetAddress.getByName(addr1);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700890 } catch (UnknownHostException e) {
891 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700892
893 byte[] b = a.getAddress();
894 int ipInt = ((b[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700895 ((b[1] & 0xFF) << 16) |
896 ((b[2] & 0xFF) << 8) |
897 ((b[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -0700898
899 byte[] b1 = a1.getAddress();
900 int ipInt1 = ((b1[0] & 0xFF) << 24) |
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700901 ((b1[1] & 0xFF) << 16) |
902 ((b1[2] & 0xFF) << 8) |
903 ((b1[3] & 0xFF) << 0);
Sangho Shin1aa93542014-09-22 09:49:44 -0700904
905 int mask = ~((1 << (32 - prefix)) - 1);
906
907 if ((ipInt & mask) == (ipInt1 & mask)) {
908 return true;
909 }
910 else {
911 return false;
912 }
913 }
Sangho Shineb083032014-09-22 16:11:34 -0700914
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700915 /**
916 * Add a routing rule for the host
Sangho Shinfbc572c2014-10-02 16:37:05 -0700917 *
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700918 * @param sw - Switch to add the rule
919 * @param hostIpAddress Destination host IP address
920 * @param hostMacAddress Destination host MAC address
921 */
Sangho Shineb083032014-09-22 16:11:34 -0700922 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
923 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
924
925 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700926
Sangho Shin463bee52014-09-29 15:14:43 -0700927 /**
928 * Add IP packet to a buffer queue
Sangho Shinfbc572c2014-10-02 16:37:05 -0700929 *
Sangho Shin463bee52014-09-29 15:14:43 -0700930 * @param ipv4
931 */
932 public void addPacket(IPv4 ipv4) {
Sangho Shin61535402014-10-01 11:37:14 -0700933 ipPacketQueue.add(ipv4);
Sangho Shin463bee52014-09-29 15:14:43 -0700934 }
935
936 /**
937 * Retrieve all packets whose destination is the given address.
Sangho Shinfbc572c2014-10-02 16:37:05 -0700938 *
Sangho Shin463bee52014-09-29 15:14:43 -0700939 * @param destIp Destination address of packets to retrieve
940 */
941 public List<IPv4> getIpPacketFromQueue(byte[] destIp) {
942
943 List<IPv4> bufferedPackets = new ArrayList<IPv4>();
944
Sangho Shin61535402014-10-01 11:37:14 -0700945 if (!ipPacketQueue.isEmpty()) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700946 for (IPv4 ip : ipPacketQueue) {
Sangho Shin61535402014-10-01 11:37:14 -0700947 int dest = ip.getDestinationAddress();
948 IPv4Address ip1 = IPv4Address.of(dest);
949 IPv4Address ip2 = IPv4Address.of(destIp);
950 if (ip1.equals(ip2)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700951 bufferedPackets.add((IPv4) (ipPacketQueue.poll()).clone());
Sangho Shin463bee52014-09-29 15:14:43 -0700952 }
953 }
954 }
955
956 return bufferedPackets;
957 }
958
Sangho Shin2f263692014-09-15 14:09:41 -0700959}