blob: 4f71b419a898c21cd624314d8ba640df7812f9b1 [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 Shin43cee112014-09-25 16:43:34 -070013import java.util.concurrent.ScheduledExecutorService;
14import java.util.concurrent.TimeUnit;
Sangho Shin2f263692014-09-15 14:09:41 -070015
16import net.floodlightcontroller.core.IFloodlightProviderService;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070017import net.floodlightcontroller.core.IOF13Switch;
Sangho Shin0df01982014-09-25 17:11:18 -070018import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
Sangho Shin2f263692014-09-15 14:09:41 -070019import net.floodlightcontroller.core.module.FloodlightModuleContext;
20import net.floodlightcontroller.core.module.FloodlightModuleException;
21import net.floodlightcontroller.core.module.IFloodlightModule;
22import net.floodlightcontroller.core.module.IFloodlightService;
Sangho Shin43cee112014-09-25 16:43:34 -070023import net.floodlightcontroller.core.util.SingletonTask;
24import net.floodlightcontroller.threadpool.IThreadPoolService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070025import net.onrc.onos.api.packet.IPacketListener;
Sangho Shin2f263692014-09-15 14:09:41 -070026import net.onrc.onos.api.packet.IPacketService;
27import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
28import net.onrc.onos.core.main.config.IConfigInfoService;
Sangho Shin43cee112014-09-25 16:43:34 -070029import net.onrc.onos.core.matchaction.MatchAction;
30import net.onrc.onos.core.matchaction.MatchActionId;
31import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
32import net.onrc.onos.core.matchaction.action.Action;
33import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
34import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
35import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
36import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
37import net.onrc.onos.core.matchaction.action.GroupAction;
38import net.onrc.onos.core.matchaction.action.PopMplsAction;
39import net.onrc.onos.core.matchaction.action.PushMplsAction;
40import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
Saurav Dasfc5e3eb2014-09-25 19:05:21 -070041import net.onrc.onos.core.matchaction.match.Ipv4Match;
Sangho Shin43cee112014-09-25 16:43:34 -070042import net.onrc.onos.core.matchaction.match.Match;
43import net.onrc.onos.core.matchaction.match.MplsMatch;
Sangho Shin2f263692014-09-15 14:09:41 -070044import net.onrc.onos.core.packet.ARP;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070045import net.onrc.onos.core.packet.Ethernet;
46import net.onrc.onos.core.packet.IPv4;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070047import net.onrc.onos.core.topology.ITopologyListener;
Sangho Shin1aa93542014-09-22 09:49:44 -070048import net.onrc.onos.core.topology.ITopologyService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070049import net.onrc.onos.core.topology.MutableTopology;
Sangho Shineb083032014-09-22 16:11:34 -070050import net.onrc.onos.core.topology.Port;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070051import net.onrc.onos.core.topology.Switch;
Sangho Shin1aa93542014-09-22 09:49:44 -070052import net.onrc.onos.core.topology.TopologyEvents;
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070053import net.onrc.onos.core.util.Dpid;
Sangho Shin43cee112014-09-25 16:43:34 -070054import net.onrc.onos.core.util.IPv4Net;
55import net.onrc.onos.core.util.SwitchPort;
Sangho Shin2f263692014-09-15 14:09:41 -070056
Sangho Shin43cee112014-09-25 16:43:34 -070057import org.json.JSONArray;
58import org.json.JSONException;
Saurav Dasbc594a42014-09-25 20:13:50 -070059import org.projectfloodlight.openflow.types.EthType;
Sangho Shin2f263692014-09-15 14:09:41 -070060import org.projectfloodlight.openflow.types.IPv4Address;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070061import org.projectfloodlight.openflow.util.HexString;
Sangho Shin2f263692014-09-15 14:09:41 -070062import org.slf4j.Logger;
63import org.slf4j.LoggerFactory;
64
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070065public class SegmentRoutingManager implements IFloodlightModule,
Sangho Shinac5ee2b2014-09-28 21:27:20 -070066 ITopologyListener, IPacketListener {
Sangho Shin2f263692014-09-15 14:09:41 -070067
68 private static final Logger log = LoggerFactory
69 .getLogger(SegmentRoutingManager.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070070 private ITopologyService topologyService;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070071 private IPacketService packetService;
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -070072 private MutableTopology mutableTopology;
Sangho Shin2f263692014-09-15 14:09:41 -070073
74 private List<ArpEntry> arpEntries;
Sangho Shineb083032014-09-22 16:11:34 -070075 private ArpHandler arpHandler;
76 private GenericIpHandler ipHandler;
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -070077 private IcmpHandler icmpHandler;
Sangho Shin43cee112014-09-25 16:43:34 -070078 private boolean networkConverged;
79 private IThreadPoolService threadPool;
80 private SingletonTask discoveryTask;
Sangho Shin9c0f4c32014-09-26 16:02:38 -070081 private IFloodlightProviderService floodlightProvider;
Sangho Shin2f263692014-09-15 14:09:41 -070082
83 @Override
84 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
85 // TODO Auto-generated method stub
86 return null;
87 }
88
89 @Override
90 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
91 // TODO Auto-generated method stub
92 return null;
93 }
94
95 @Override
96 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
97 Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
98
99 l.add(IFloodlightProviderService.class);
100 l.add(IConfigInfoService.class);
101 l.add(ITopologyService.class);
102 l.add(IPacketService.class);
103 l.add(IFlowPusherService.class);
104 l.add(ITopologyService.class);
105
106 return l;
107
108 }
109
110 @Override
111 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700112 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Sangho Shineb083032014-09-22 16:11:34 -0700113 arpHandler = new ArpHandler(context, this);
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700114 icmpHandler = new IcmpHandler(context, this);
Sangho Shineb083032014-09-22 16:11:34 -0700115 ipHandler = new GenericIpHandler(context, this);
Sangho Shin2f263692014-09-15 14:09:41 -0700116 arpEntries = new ArrayList<ArpEntry>();
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700117 topologyService = context.getServiceImpl(ITopologyService.class);
Sangho Shin43cee112014-09-25 16:43:34 -0700118 threadPool = context.getServiceImpl(IThreadPoolService.class);
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700119 mutableTopology = topologyService.getTopology();
120 topologyService.addListener(this, false);
Sangho Shin2f263692014-09-15 14:09:41 -0700121
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700122 this.packetService = context.getServiceImpl(IPacketService.class);
123 packetService.registerPacketListener(this);
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700124
Sangho Shin2f263692014-09-15 14:09:41 -0700125 }
126
127 @Override
128 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
Sangho Shin43cee112014-09-25 16:43:34 -0700129 networkConverged = false;
Sangho Shin2f263692014-09-15 14:09:41 -0700130
Sangho Shin43cee112014-09-25 16:43:34 -0700131 ScheduledExecutorService ses = threadPool.getScheduledExecutor();
132
133 discoveryTask = new SingletonTask(ses, new Runnable() {
134 @Override
135 public void run() {
136 populateEcmpRoutingRules();
137 }
138 });
139
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700140 discoveryTask.reschedule(15, TimeUnit.SECONDS);
Sangho Shin2f263692014-09-15 14:09:41 -0700141 }
142
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700143 @Override
144 public void receive(Switch sw, Port inPort, Ethernet payload) {
145 if (payload.getEtherType() == Ethernet.TYPE_ARP)
146 arpHandler.processPacketIn(sw, inPort, payload);
147 if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700148 if (((IPv4)payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
Srikanth Vavilapallib1fce732014-09-24 14:09:50 -0700149 icmpHandler.processPacketIn(sw, inPort, payload);
150 else
151 ipHandler.processPacketIn(sw, inPort, payload);
152 }
153 }
Sangho Shin2f263692014-09-15 14:09:41 -0700154 /**
155 * Update ARP Cache using ARP packets
156 * It is used to set destination MAC address to forward packets to known hosts.
157 * But, it will be replace with Host information of Topology service later.
158 *
159 * @param arp APR packets to use for updating ARP entries
160 */
161 public void updateArpCache(ARP arp) {
162
163 ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(), arp.getSenderProtocolAddress());
164 // TODO: Need to check the duplication
165 arpEntries.add(arpEntry);
166 }
167
168 /**
169 * Get MAC address to known hosts
170 *
171 * @param destinationAddress IP address to get MAC address
172 * @return MAC Address to given IP address
173 */
174 public byte[] getMacAddressFromIpAddress(int destinationAddress) {
175
176 // Can't we get the host IP address from the TopologyService ??
177
178 Iterator<ArpEntry> iterator = arpEntries.iterator();
179
180 IPv4Address ipAddress = IPv4Address.of(destinationAddress);
181 byte[] ipAddressInByte = ipAddress.getBytes();
182
183 while (iterator.hasNext() ) {
184 ArpEntry arpEntry = iterator.next();
185 byte[] address = arpEntry.targetIpAddress;
186
187 IPv4Address a = IPv4Address.of(address);
188 IPv4Address b = IPv4Address.of(ipAddressInByte);
189
190 if ( a.equals(b)) {
191 log.debug("Found an arp entry");
192 return arpEntry.targetMacAddress;
193 }
194 }
195
196 return null;
197 }
198
Sangho Shineb083032014-09-22 16:11:34 -0700199 /**
200 * Send an ARP request via ArpHandler
201 * @param destinationAddress
202 * @param sw
203 * @param inPort
204 *
205 */
206 public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
207 arpHandler.sendArpRequest(sw, destinationAddress, inPort);
208 }
Sangho Shin2f263692014-09-15 14:09:41 -0700209
210 /**
211 * Temporary class to to keep ARP entry
212 *
213 */
214 private class ArpEntry {
215
216 byte[] targetMacAddress;
217 byte[] targetIpAddress;
218
219 private ArpEntry(byte[] macAddress, byte[] ipAddress) {
220 this.targetMacAddress = macAddress;
221 this.targetIpAddress = ipAddress;
222 }
Sangho Shin2f263692014-09-15 14:09:41 -0700223 }
Sangho Shineb083032014-09-22 16:11:34 -0700224
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700225 /**
226 * Topology events that have been generated.
227 *
228 * @param topologyEvents the generated Topology Events
229 * @see TopologyEvents
230 */
231 public void topologyEvents(TopologyEvents topologyEvents)
232 {
233 /**
234 * Any Link update events, compute the ECMP path graph for all switch nodes
Sangho Shin43cee112014-09-25 16:43:34 -0700235
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700236 if ((topologyEvents.getAddedLinkDataEntries() != null) ||
237 (topologyEvents.getRemovedLinkDataEntries() != null))
238 {
239 Iterable<Switch> switches= mutableTopology.getSwitches();
240 for (Switch sw : switches) {
241 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
Srikanth Vavilapallif3bfcf92014-09-19 07:42:10 -0700242 log.debug("ECMPShortestPathGraph is computed for switch {}",
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700243 HexString.toHexString(sw.getDpid().value()));
Sangho Shin43cee112014-09-25 16:43:34 -0700244
245
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700246 HashMap<Integer, HashMap<Switch,ArrayList<Path>>> pathGraph =
247 ecmpSPG.getCompleteLearnedSwitchesAndPaths();
248 for (Integer itrIdx: pathGraph.keySet()){
249
250 HashMap<Switch, ArrayList<Path>> swPathsMap =
251 pathGraph.get(itrIdx);
252 for (Switch targetSw: swPathsMap.keySet()){
253 log.debug("ECMPShortestPathGraph:Paths in Pass{} from "
254 + " switch {} to switch {}:****",
255 itrIdx,
256 HexString.toHexString(sw.getDpid().value()),
257 HexString.toHexString(targetSw.getDpid().value()));
258 int i=0;
259 for (Path path:swPathsMap.get(targetSw)){
260 log.debug("****ECMPShortestPathGraph:Path{} is {}",i++,path);
261 }
262 }
263 }
Sangho Shin43cee112014-09-25 16:43:34 -0700264
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700265 HashMap<Integer, HashMap<Switch,ArrayList<ArrayList<Dpid>>>> switchVia =
266 ecmpSPG.getAllLearnedSwitchesAndVia();
267 for (Integer itrIdx: switchVia.keySet()){
268 log.debug("ECMPShortestPathGraph:Switches learned in "
269 + "Iteration{} from switch {}:",
270 itrIdx,
271 HexString.toHexString(sw.getDpid().value()));
272
273 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
274 switchVia.get(itrIdx);
275 for (Switch targetSw: swViaMap.keySet()){
276 log.debug("ECMPShortestPathGraph:****switch {} via:",
277 HexString.toHexString(targetSw.getDpid().value()));
278 int i=0;
279 for (ArrayList<Dpid> via:swViaMap.get(targetSw)){
280 log.debug("ECMPShortestPathGraph:******{}) {}",++i,via);
281 }
282 }
283 }
Sangho Shin43cee112014-09-25 16:43:34 -0700284
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700285 }
286 }
Sangho Shin43cee112014-09-25 16:43:34 -0700287 */
288
289 if ((topologyEvents.getAddedLinkDataEntries() != null) ||
290 (topologyEvents.getRemovedLinkDataEntries() != null))
291 {
292
293 if (networkConverged) {
294 populateEcmpRoutingRules();
295 }
296 }
297
Srikanth Vavilapallib7e5c5e2014-09-18 07:38:27 -0700298 }
Sangho Shin1aa93542014-09-22 09:49:44 -0700299
300 /**
Sangho Shin43cee112014-09-25 16:43:34 -0700301 * Populate routing rules walking through the ECMP shortest paths
Sangho Shin1aa93542014-09-22 09:49:44 -0700302 *
Sangho Shin1aa93542014-09-22 09:49:44 -0700303 */
Sangho Shin43cee112014-09-25 16:43:34 -0700304 private void populateEcmpRoutingRules() {
Sangho Shin1aa93542014-09-22 09:49:44 -0700305
Sangho Shin43cee112014-09-25 16:43:34 -0700306 Iterable<Switch> switches= mutableTopology.getSwitches();
307 for (Switch sw : switches) {
308 ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
309 log.debug("ECMPShortestPathGraph is computed for switch {}",
310 HexString.toHexString(sw.getDpid().value()));
Sangho Shin1aa93542014-09-22 09:49:44 -0700311
Sangho Shin43cee112014-09-25 16:43:34 -0700312 HashMap<Integer, HashMap<Switch,ArrayList<ArrayList<Dpid>>>> switchVia =
313 ecmpSPG.getAllLearnedSwitchesAndVia();
314 for (Integer itrIdx: switchVia.keySet()){
315 log.debug("ECMPShortestPathGraph:Switches learned in "
316 + "Iteration{} from switch {}:",
317 itrIdx,
318 HexString.toHexString(sw.getDpid().value()));
319 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
320 switchVia.get(itrIdx);
321 for (Switch targetSw: swViaMap.keySet()){
322 log.debug("ECMPShortestPathGraph:****switch {} via:",
323 HexString.toHexString(targetSw.getDpid().value()));
324 String destSw = sw.getDpid().toString();
325 List<String> fwdToSw = new ArrayList<String>();
326
327 int i=0;
328 for (ArrayList<Dpid> via:swViaMap.get(targetSw)){
329 log.debug("ECMPShortestPathGraph:******{}) {}",++i,via);
330 if (via.isEmpty()) {
331 fwdToSw.add(destSw);
332 }
333 else {
334 fwdToSw.add(via.get(0).toString());
335 }
336 }
337 setRoutingRule(targetSw, destSw, fwdToSw);
338 }
Sangho Shineb083032014-09-22 16:11:34 -0700339 }
340 }
Sangho Shin43cee112014-09-25 16:43:34 -0700341
342 networkConverged = true;
343 }
344
345 /**
346 *
347 * Set routing rules in targetSw
348 * {forward packets to fwdToSw switches in order to send packets to destSw}
349 * - If the target switch is an edge router and final destnation switch is also
350 * an edge router, then set IP forwarding rules to subnets
351 * - If only the target switch is an edge router, then set IP forwarding rule to
352 * the transit router loopback IP address
353 * - If the target is a transit router, then just set the MPLS forwarding rule
354 *
355 * @param targetSw Switch to set the rules
356 * @param destSw Final destination switches
357 * @param fwdToSw next hop switches
358 */
359 private void setRoutingRule(Switch targetSw, String destSw, List<String> fwdToSw) {
360
361
362 if (fwdToSw.isEmpty()) {
363 fwdToSw.add(destSw);
364 }
365
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700366 // if both target SW and dest SW are an edge router, then set IP table
Sangho Shin43cee112014-09-25 16:43:34 -0700367 if (IsEdgeRouter(targetSw.getDpid().toString()) &&
368 IsEdgeRouter(destSw)) {
369 // We assume that there is at least one transit router b/w edge routers
370 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
371 String subnets = destSwitch.getStringAttribute("subnets");
372 try {
373 JSONArray arry = new JSONArray(subnets);
374 for (int i = 0; i < arry.length(); i++) {
375 String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
376 setIpTableRouter(targetSw, subnetIp, getMplsLabel(destSw)
377 ,fwdToSw);
378
379 }
380 } catch (JSONException e) {
381 // TODO Auto-generated catch block
382 e.printStackTrace();
383 }
384 String routerIp = destSwitch.getStringAttribute("routerIp");
385 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw);
386 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700387 // Only if the target switch is the edge router, then set the IP rules
Sangho Shin43cee112014-09-25 16:43:34 -0700388 else if (IsEdgeRouter(targetSw.getDpid().toString())) {
389 // We assume that there is at least one transit router b/w edge routers
390 Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
391 String routerIp = destSwitch.getStringAttribute("routerIp");
392 setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw);
393 }
394 // if it is a transit router, then set rules in the MPLS table
395 else {
396 setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw);
397 }
398
399 }
400
401 /**
402 * Check if the switch is the edge router or not
403 * If any subnet information is defined in the config file, the we assume
404 * it is an edge router
405 *
406 * @param dpid Dpid of the switch to check
407 * @return true if it is an edge router, otherwise false
408 */
409 private boolean IsEdgeRouter(String dpid) {
410
411 for (Switch sw: mutableTopology.getSwitches()) {
412 String dpidStr = sw.getDpid().toString();
413 if (dpid.equals(dpidStr)) {
414 String subnetInfo = sw.getStringAttribute("subnets");
415 if (subnetInfo == null || subnetInfo.equals("[]")) {
416 return false;
417 }
418 else
419 return true;
420 }
421 }
422
423 return false;
424 }
425
426 /**
427 * Set IP forwarding rule
428 * - If the destination is the next hop, then do not push MPLS,
429 * just decrease the NW TTL
430 * - Otherwise, push MPLS label and set the MPLS ID
431 *
432 * @param sw target switch to set rules
433 * @param subnetIp Match IP address
434 * @param mplsLabel MPLS label of final destination router
435 * @param fwdToSws next hop routers
436 */
437 private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
438 List<String> fwdToSws) {
439
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700440 Ipv4Match ipMatch = new Ipv4Match(subnetIp);
Sangho Shin43cee112014-09-25 16:43:34 -0700441 List<Action> actions = new ArrayList<>();
442
443 // If destination SW is the same as the fwd SW, then do not push MPLS label
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700444
445 if (fwdToSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700446 PushMplsAction pushMplsAction = new PushMplsAction();
447 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
448 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
449
450 actions.add(pushMplsAction);
451 actions.add(setIdAction);
452 actions.add(copyTtlOutAction);
453 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700454 else {
455 String fwdToSw = fwdToSws.get(0);
456 if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
457 DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
458 actions.add(decTtlAction);
459 }
460 else {
461 PushMplsAction pushMplsAction = new PushMplsAction();
462 SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
463 CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();
464
465 actions.add(pushMplsAction);
466 actions.add(setIdAction);
467 actions.add(copyTtlOutAction);
468 }
469 }
Sangho Shin43cee112014-09-25 16:43:34 -0700470
471 GroupAction groupAction = new GroupAction();
472
473 for (String fwdSw : fwdToSws) {
474 groupAction.addSwitch(new Dpid(fwdSw));
475 }
476 actions.add(groupAction);
477
478 //MatchAction matchAction = new MatchAction(maIdGenerator.getNewId(),
479 MatchAction matchAction = new MatchAction(new MatchActionId(0),
480 new SwitchPort((long)0,(short)0), ipMatch, actions);
481
482 MatchActionOperationEntry maEntry =
483 new MatchActionOperationEntry(
484 net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
485 matchAction);
486
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700487 IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700488 getSwId(sw.getDpid().toString()));
489
490 try {
491 printMatchActionOperationEntry(sw, maEntry);
492 sw13.pushFlow(maEntry);
493 } catch (IOException e) {
494 // TODO Auto-generated catch block
495 e.printStackTrace();
496 }
497
Sangho Shin43cee112014-09-25 16:43:34 -0700498 }
499
500
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700501 /**
502 * Convert a string DPID to its Switch Id (integer)
503 *
504 * @param dpid
505 * @return
506 */
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700507 private long getSwId(String dpid) {
508
509 long swId = 0;
510
511 String swIdStr = dpid.substring(dpid.lastIndexOf(":")+1);
512 if (swIdStr != null)
513 swId = Integer.parseInt(swIdStr);
514
515 return swId;
516 }
517
Sangho Shin43cee112014-09-25 16:43:34 -0700518 /**
519 * Set MPLS forwarding rules to MPLS table
520 * - If the destination is the same as the next hop to forward packets
521 * then, pop the MPLS label according to PHP rule
522 * - Otherwise, just forward packets to next hops using Group action
523 *
524 * @param sw Switch to set the rules
525 * @param mplsLabel destination MPLS label
526 * @param fwdSws next hop switches
527 */
528 private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws) {
Saurav Dasd0977442014-09-29 10:36:14 -0700529 if (mplsLabel == null) {
530 log.error("mpls label not configured for sw: {}. Not populating"
531 + " MPLS table entries.", sw.getDpid());
532 return;
533 }
Sangho Shin43cee112014-09-25 16:43:34 -0700534 MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel));
535
536 List<Action> actions = new ArrayList<Action>();
Sangho Shin43cee112014-09-25 16:43:34 -0700537
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700538 if (fwdSws.size() > 1) {
Sangho Shin43cee112014-09-25 16:43:34 -0700539 DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
540 actions.add(decMplsTtlAction);
541 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700542 // If the destination is the same as the next hop, then pop MPLS
543 else {
544 String fwdMplsId = getMplsLabel(fwdSws.get(0));
545 if (fwdMplsId.equals(mplsLabel)) {
546 String fwdSw = fwdSws.get(0);
547 if (mplsLabel.equals(getMplsLabel(fwdSw))) {
548 PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
549 CopyTtlInAction copyTtlInAction = new CopyTtlInAction();
550
551 actions.add(popAction);
552 actions.add(copyTtlInAction);
553 }
554 }
555 }
Sangho Shin43cee112014-09-25 16:43:34 -0700556
557 GroupAction groupAction = new GroupAction();
558 for (String fwdSw: fwdSws)
559 groupAction.addSwitch(new Dpid(fwdSw));
560 actions.add(groupAction);
561
562 MatchAction matchAction = new MatchAction(new MatchActionId(0),
563 new SwitchPort((long)0,(short)0), mplsMatch, actions);
564
565 MatchActionOperationEntry maEntry =
566 new MatchActionOperationEntry(
567 net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
568 matchAction);
569
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700570 IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
571 getSwId(sw.getDpid().toString()));
572
573 try {
574 printMatchActionOperationEntry(sw, maEntry);
575 sw13.pushFlow(maEntry);
576 } catch (IOException e) {
577 // TODO Auto-generated catch block
578 e.printStackTrace();
579 }
580
Sangho Shin43cee112014-09-25 16:43:34 -0700581 }
582
583
584 /**
585 * Debugging function to print out the Match Action Entry
586 *
587 * @param maEntry
588 */
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700589 private void printMatchActionOperationEntry(Switch sw,
590 MatchActionOperationEntry maEntry) {
Sangho Shin43cee112014-09-25 16:43:34 -0700591
Sangho Shin0df01982014-09-25 17:11:18 -0700592 StringBuilder logStr = new StringBuilder("In switch " + sw.getDpid() + ", ");
Sangho Shin43cee112014-09-25 16:43:34 -0700593
594 MatchAction ma = maEntry.getTarget();
595 Match m = ma.getMatch();
596 List<Action> actions = ma.getActions();
597
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700598 if (m instanceof Ipv4Match) {
Sangho Shin43cee112014-09-25 16:43:34 -0700599 logStr.append("If the IP matches with ");
Saurav Dasfc5e3eb2014-09-25 19:05:21 -0700600 IPv4Net ip = ((Ipv4Match) m).getDestination();
Sangho Shin43cee112014-09-25 16:43:34 -0700601 logStr.append(ip.toString());
602 logStr.append(" then ");
603 }
604 else if (m instanceof MplsMatch) {
605 logStr.append("If the MPLS label matches with ");
606 int mplsLabel = ((MplsMatch) m).getMplsLabel();
607 logStr.append(mplsLabel);
608 logStr.append(" then ");
609 }
610
611 logStr.append(" do { ");
612 for (Action action: actions) {
613 if (action instanceof CopyTtlInAction) {
614 logStr.append("copy ttl In, ");
615 }
616 else if (action instanceof CopyTtlOutAction) {
617 logStr.append("copy ttl Out, ");
618 }
619 else if (action instanceof DecMplsTtlAction) {
620 logStr.append("Dec MPLS TTL , ");
621 }
622 else if (action instanceof GroupAction) {
623 logStr.append("Forward packet to < ");
Sangho Shin0df01982014-09-25 17:11:18 -0700624 NeighborSet dpids = ((GroupAction)action).getDpids();
625 logStr.append(dpids.toString() + ",");
626
Sangho Shin43cee112014-09-25 16:43:34 -0700627 }
628 else if (action instanceof PopMplsAction) {
629 logStr.append("Pop MPLS label, ");
630 }
631 else if (action instanceof PushMplsAction) {
632 logStr.append("Push MPLS label, ");
633 }
634 else if (action instanceof SetMplsIdAction) {
635 int id = ((SetMplsIdAction)action).getMplsId();
636 logStr.append("Set MPLS ID as " + id + ", ");
637
638 }
639 }
640
641 log.debug(logStr.toString());
642
Sangho Shineb083032014-09-22 16:11:34 -0700643 }
644
645 /**
646 * Get MPLS label reading the config file
647 *
648 * @param dipid DPID of the switch
649 * @return MPLS label for the switch
650 */
651
Sangho Shin43cee112014-09-25 16:43:34 -0700652 private String getMplsLabel(String dpid) {
Sangho Shineb083032014-09-22 16:11:34 -0700653
654 String mplsLabel = null;
655 for (Switch sw: mutableTopology.getSwitches()) {
Sangho Shin43cee112014-09-25 16:43:34 -0700656 String dpidStr = sw.getDpid().toString();
657 if (dpid.equals(dpidStr)) {
Sangho Shineb083032014-09-22 16:11:34 -0700658 mplsLabel = sw.getStringAttribute("nodeSid");
659 break;
Sangho Shin1aa93542014-09-22 09:49:44 -0700660 }
661 }
662
Sangho Shineb083032014-09-22 16:11:34 -0700663 return mplsLabel;
Sangho Shin1aa93542014-09-22 09:49:44 -0700664 }
665
Sangho Shineb083032014-09-22 16:11:34 -0700666
667
668 /**
Sangho Shin1aa93542014-09-22 09:49:44 -0700669 * The function checks if given IP matches to the given subnet mask
670 *
671 * @param addr - subnet address to match
672 * @param addr1 - IP address to check
673 * @return true if the IP address matches to the subnet, otherwise false
674 */
Sangho Shin1aa93542014-09-22 09:49:44 -0700675 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)
676
677 String[] parts = addr.split("/");
678 String ip = parts[0];
679 int prefix;
680
681 if (parts.length < 2) {
682 prefix = 0;
683 } else {
684 prefix = Integer.parseInt(parts[1]);
685 }
686
687 Inet4Address a =null;
688 Inet4Address a1 =null;
689 try {
690 a = (Inet4Address) InetAddress.getByName(ip);
691 a1 = (Inet4Address) InetAddress.getByName(addr1);
692 } catch (UnknownHostException e){}
693
694 byte[] b = a.getAddress();
695 int ipInt = ((b[0] & 0xFF) << 24) |
696 ((b[1] & 0xFF) << 16) |
697 ((b[2] & 0xFF) << 8) |
698 ((b[3] & 0xFF) << 0);
699
700 byte[] b1 = a1.getAddress();
701 int ipInt1 = ((b1[0] & 0xFF) << 24) |
702 ((b1[1] & 0xFF) << 16) |
703 ((b1[2] & 0xFF) << 8) |
704 ((b1[3] & 0xFF) << 0);
705
706 int mask = ~((1 << (32 - prefix)) - 1);
707
708 if ((ipInt & mask) == (ipInt1 & mask)) {
709 return true;
710 }
711 else {
712 return false;
713 }
714 }
Sangho Shineb083032014-09-22 16:11:34 -0700715
Sangho Shinac5ee2b2014-09-28 21:27:20 -0700716 /**
717 * Add a routing rule for the host
718 *
719 * @param sw - Switch to add the rule
720 * @param hostIpAddress Destination host IP address
721 * @param hostMacAddress Destination host MAC address
722 */
Sangho Shineb083032014-09-22 16:11:34 -0700723 public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
724 ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
725
726 }
Sangho Shin9c0f4c32014-09-26 16:02:38 -0700727
Sangho Shin2f263692014-09-15 14:09:41 -0700728}