blob: 486d0572338ac8aa79dfa096dd4f2fbb82eb18dd [file] [log] [blame]
HIGUCHI Yutaea60e5f2013-06-12 11:10:21 -07001package net.onrc.onos.ofcontroller.bgproute;
pingping-lina2cbfad2013-03-07 08:39:21 +08002
Jonathan Hartd1f23252013-06-13 15:17:05 +12003import java.io.File;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -07004import java.io.IOException;
5import java.net.InetAddress;
Jonathan Hart61ba9372013-05-19 20:10:29 -07006import java.net.UnknownHostException;
pingping-lina2cbfad2013-03-07 08:39:21 +08007import java.util.ArrayList;
Jonathan Hart61ba9372013-05-19 20:10:29 -07008import java.util.Collection;
pingping-lina2cbfad2013-03-07 08:39:21 +08009import java.util.HashMap;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070010import java.util.HashSet;
11import java.util.List;
Jonathan Hart61ba9372013-05-19 20:10:29 -070012import java.util.Map;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070013import java.util.Set;
pingping-lina2cbfad2013-03-07 08:39:21 +080014
Jonathan Hart61ba9372013-05-19 20:10:29 -070015import net.floodlightcontroller.core.IFloodlightProviderService;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070016import net.floodlightcontroller.core.IOFSwitch;
pingping-lina2cbfad2013-03-07 08:39:21 +080017import net.floodlightcontroller.core.module.FloodlightModuleContext;
18import net.floodlightcontroller.core.module.FloodlightModuleException;
19import net.floodlightcontroller.core.module.IFloodlightModule;
20import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070021import net.floodlightcontroller.devicemanager.IDeviceService;
Jonathan Hart50a8d1e2013-06-06 16:00:47 +120022import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070023import net.floodlightcontroller.packet.Ethernet;
pingping-lina2cbfad2013-03-07 08:39:21 +080024import net.floodlightcontroller.restserver.IRestApiService;
25import net.floodlightcontroller.topology.ITopologyListener;
26import net.floodlightcontroller.topology.ITopologyService;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070027import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoRouteService;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070028import net.onrc.onos.ofcontroller.util.DataPath;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070029import net.onrc.onos.ofcontroller.util.FlowEntry;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070030import net.onrc.onos.ofcontroller.util.Port;
31import net.onrc.onos.ofcontroller.util.SwitchPort;
pingping-line2a09ca2013-03-23 09:33:58 +080032import net.sf.json.JSONArray;
33import net.sf.json.JSONObject;
34import net.sf.json.JSONSerializer;
pingping-lina2cbfad2013-03-07 08:39:21 +080035
Jonathan Hartd1f23252013-06-13 15:17:05 +120036import org.codehaus.jackson.JsonParseException;
37import org.codehaus.jackson.map.JsonMappingException;
38import org.codehaus.jackson.map.ObjectMapper;
39import org.codehaus.jackson.type.TypeReference;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070040import org.openflow.protocol.OFFlowMod;
41import org.openflow.protocol.OFMatch;
42import org.openflow.protocol.OFMessage;
43import org.openflow.protocol.OFPacketOut;
44import org.openflow.protocol.OFType;
45import org.openflow.protocol.action.OFAction;
46import org.openflow.protocol.action.OFActionDataLayerDestination;
47import org.openflow.protocol.action.OFActionOutput;
pingping-lina2cbfad2013-03-07 08:39:21 +080048import org.slf4j.Logger;
49import org.slf4j.LoggerFactory;
50
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070051import com.google.common.net.InetAddresses;
52
pingping-lina2cbfad2013-03-07 08:39:21 +080053public class BgpRoute implements IFloodlightModule, IBgpRouteService, ITopologyListener {
54
55 protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);
56
57 protected IFloodlightProviderService floodlightProvider;
58 protected ITopologyService topology;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070059 protected ITopoRouteService topoRouteService;
60 protected IDeviceService devices;
61 protected IRestApiService restApi;
62
pingping-lina2cbfad2013-03-07 08:39:21 +080063 protected static Ptree ptree;
Jonathan Hart61ba9372013-05-19 20:10:29 -070064 protected String bgpdRestIp;
65 protected String routerId;
Jonathan Hartd1f23252013-06-13 15:17:05 +120066 protected String gatewaysFilename = "gateways.json";
pingping-line2a09ca2013-03-23 09:33:58 +080067
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070068 protected Set<InetAddress> routerIpAddresses;
69
70 //We need to identify our flows somehow. But like it says in LearningSwitch.java,
71 //the controller/OS should hand out cookie IDs to prevent conflicts.
72 protected final long APP_COOKIE = 0xa0000000000000L;
73 //Cookie for flows that do L2 forwarding within SDN domain to egress routers
74 protected final long L2_FWD_COOKIE = APP_COOKIE + 1;
75 //Cookie for flows in ingress switches that rewrite the MAC address
76 protected final long MAC_RW_COOKIE = APP_COOKIE + 2;
Jonathan Hart50a8d1e2013-06-06 16:00:47 +120077 //Forwarding uses priority 0, and the mac rewrite entries in ingress switches
78 //need to be higher priority than this otherwise the rewrite may not get done
79 protected final short SDNIP_PRIORITY = 10;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070080
Jonathan Hartd1f23252013-06-13 15:17:05 +120081 protected Map<String, GatewayRouter> gatewayRouters;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070082
Jonathan Hartd1f23252013-06-13 15:17:05 +120083 private void readGatewaysConfiguration(String gatewaysFilename){
84 File gatewaysFile = new File(gatewaysFilename);
85 ObjectMapper mapper = new ObjectMapper();
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070086
Jonathan Hartd1f23252013-06-13 15:17:05 +120087 TypeReference<HashMap<String, GatewayRouter>> typeref
88 = new TypeReference<HashMap<String, GatewayRouter>>() {};
89
90 try {
91 gatewayRouters = mapper.readValue(gatewaysFile, typeref);
92 } catch (JsonParseException e) {
93 log.error("Error in JSON file", e);
94 System.exit(1);
95 } catch (JsonMappingException e) {
96 log.error("Error in JSON file", e);
97 System.exit(1);
98 } catch (IOException e) {
99 log.error("Error reading JSON file", e);
100 System.exit(1);
101 }
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700102 }
pingping-lina2cbfad2013-03-07 08:39:21 +0800103
104 @Override
105 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Jonathan Hart61ba9372013-05-19 20:10:29 -0700106 Collection<Class<? extends IFloodlightService>> l
107 = new ArrayList<Class<? extends IFloodlightService>>();
pingping-lina2cbfad2013-03-07 08:39:21 +0800108 l.add(IBgpRouteService.class);
109 return l;
110 }
111
112 @Override
113 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Jonathan Hart61ba9372013-05-19 20:10:29 -0700114 Map<Class<? extends IFloodlightService>, IFloodlightService> m
115 = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
pingping-line2a09ca2013-03-23 09:33:58 +0800116 m.put(IBgpRouteService.class, this);
pingping-lina2cbfad2013-03-07 08:39:21 +0800117 return m;
118 }
119
pingping-lina2cbfad2013-03-07 08:39:21 +0800120 @Override
121 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Jonathan Hart61ba9372013-05-19 20:10:29 -0700122 Collection<Class<? extends IFloodlightService>> l
123 = new ArrayList<Class<? extends IFloodlightService>>();
pingping-lina2cbfad2013-03-07 08:39:21 +0800124 l.add(IFloodlightProviderService.class);
125 l.add(ITopologyService.class);
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700126 l.add(ITopoRouteService.class);
127 l.add(IDeviceService.class);
128 l.add(IRestApiService.class);
pingping-lina2cbfad2013-03-07 08:39:21 +0800129 return l;
130 }
131
132 @Override
133 public void init(FloodlightModuleContext context)
134 throws FloodlightModuleException {
135
136 ptree = new Ptree(32);
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700137
138 routerIpAddresses = new HashSet<InetAddress>();
pingping-lina2cbfad2013-03-07 08:39:21 +0800139
140 // Register floodlight provider and REST handler.
141 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
pingping-lina2cbfad2013-03-07 08:39:21 +0800142 topology = context.getServiceImpl(ITopologyService.class);
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700143 topoRouteService = context.getServiceImpl(ITopoRouteService.class);
144 devices = context.getServiceImpl(IDeviceService.class);
145 restApi = context.getServiceImpl(IRestApiService.class);
pingping-lina2cbfad2013-03-07 08:39:21 +0800146
Jonathan Hart61ba9372013-05-19 20:10:29 -0700147 //Read in config values
148 bgpdRestIp = context.getConfigParams(this).get("BgpdRestIp");
149 if (bgpdRestIp == null){
150 log.error("BgpdRestIp property not found in config file");
151 System.exit(1);
152 }
153 else {
154 log.info("BgpdRestIp set to {}", bgpdRestIp);
155 }
156
157 routerId = context.getConfigParams(this).get("RouterId");
158 if (routerId == null){
159 log.error("RouterId property not found in config file");
160 System.exit(1);
161 }
162 else {
163 log.info("RouterId set to {}", routerId);
164 }
Jonathan Hartd1f23252013-06-13 15:17:05 +1200165
166 readGatewaysConfiguration(gatewaysFilename);
pingping-lina2cbfad2013-03-07 08:39:21 +0800167 // Test.
168 //test();
169 }
170
171 public Ptree getPtree() {
172 return ptree;
173 }
Jonathan Hart61ba9372013-05-19 20:10:29 -0700174
175 public void clearPtree() {
176 //ptree = null;
177 ptree = new Ptree(32);
pingping-line2a09ca2013-03-23 09:33:58 +0800178 }
Jonathan Hart61ba9372013-05-19 20:10:29 -0700179
pingping-line2a09ca2013-03-23 09:33:58 +0800180 public String getBGPdRestIp() {
Jonathan Hart61ba9372013-05-19 20:10:29 -0700181 return bgpdRestIp;
pingping-line2a09ca2013-03-23 09:33:58 +0800182 }
Jonathan Hart61ba9372013-05-19 20:10:29 -0700183
pingping-line2a09ca2013-03-23 09:33:58 +0800184 public String getRouterId() {
Jonathan Hart61ba9372013-05-19 20:10:29 -0700185 return routerId;
pingping-line2a09ca2013-03-23 09:33:58 +0800186 }
pingping-lina2cbfad2013-03-07 08:39:21 +0800187
188 // Return nexthop address as byte array.
189 public Rib lookupRib(byte[] dest) {
190 if (ptree == null) {
191 log.debug("lookupRib: ptree null");
192 return null;
193 }
194
195 PtreeNode node = ptree.match(dest, 32);
196 if (node == null) {
197 log.debug("lookupRib: ptree node null");
198 return null;
199 }
Jonathan Hart61ba9372013-05-19 20:10:29 -0700200
pingping-lina2cbfad2013-03-07 08:39:21 +0800201 if (node.rib == null) {
202 log.debug("lookupRib: ptree rib null");
203 return null;
204 }
Jonathan Hart61ba9372013-05-19 20:10:29 -0700205
pingping-lina2cbfad2013-03-07 08:39:21 +0800206 ptree.delReference(node);
207
208 return node.rib;
209 }
210
Jonathan Hart61ba9372013-05-19 20:10:29 -0700211 //TODO looks like this should be a unit test
pingping-lina2cbfad2013-03-07 08:39:21 +0800212 @SuppressWarnings("unused")
Jonathan Hart61ba9372013-05-19 20:10:29 -0700213 private void test() throws UnknownHostException {
pingping-lina2cbfad2013-03-07 08:39:21 +0800214 System.out.println("Here it is");
215 Prefix p = new Prefix("128.0.0.0", 8);
216 Prefix q = new Prefix("8.0.0.0", 8);
217 Prefix r = new Prefix("10.0.0.0", 24);
218 Prefix a = new Prefix("10.0.0.1", 32);
219
220 ptree.acquire(p.getAddress(), p.masklen);
221 ptree.acquire(q.getAddress(), q.masklen);
222 ptree.acquire(r.getAddress(), r.masklen);
223
224 System.out.println("Traverse start");
225 for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
226 Prefix p_result = new Prefix(node.key, node.keyBits);
227 }
228
229 PtreeNode n = ptree.match(a.getAddress(), a.masklen);
230 if (n != null) {
231 System.out.println("Matched prefix for 10.0.0.1:");
232 Prefix x = new Prefix(n.key, n.keyBits);
233 ptree.delReference(n);
234 }
235
236 n = ptree.lookup(p.getAddress(), p.masklen);
237 if (n != null) {
238 ptree.delReference(n);
239 ptree.delReference(n);
240 }
241 System.out.println("Traverse start");
242 for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
243 Prefix p_result = new Prefix(node.key, node.keyBits);
244 }
245
246 n = ptree.lookup(q.getAddress(), q.masklen);
247 if (n != null) {
248 ptree.delReference(n);
249 ptree.delReference(n);
250 }
251 System.out.println("Traverse start");
252 for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
253 Prefix p_result = new Prefix(node.key, node.keyBits);
254 }
255
256 n = ptree.lookup(r.getAddress(), r.masklen);
257 if (n != null) {
258 ptree.delReference(n);
259 ptree.delReference(n);
260 }
261 System.out.println("Traverse start");
262 for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
263 Prefix p_result = new Prefix(node.key, node.keyBits);
264 }
265
266 }
267
Jonathan Hart61ba9372013-05-19 20:10:29 -0700268 private void retrieveRib(){
269 String url = "http://" + bgpdRestIp + "/wm/bgp/" + routerId;
270 String response = RestClient.get(url);
271
272 if (response.equals("")){
273 return;
274 }
275
276 response = response.replaceAll("\"", "'");
277 JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(response);
278 JSONArray rib_json_array = jsonObj.getJSONArray("rib");
279 String router_id = jsonObj.getString("router-id");
280
281 int size = rib_json_array.size();
282
283 log.info("Retrived RIB of {} entries from BGPd", size);
284
285 for (int j = 0; j < size; j++) {
286 JSONObject second_json_object = rib_json_array.getJSONObject(j);
287 String prefix = second_json_object.getString("prefix");
288 String nexthop = second_json_object.getString("nexthop");
289
290 //insert each rib entry into the local rib;
291 String[] substring = prefix.split("/");
292 String prefix1 = substring[0];
293 String mask1 = substring[1];
294
295 Prefix p;
296 try {
297 p = new Prefix(prefix1, Integer.valueOf(mask1));
298 } catch (NumberFormatException e) {
299 log.warn("Wrong mask format in RIB JSON: {}", mask1);
300 continue;
301 } catch (UnknownHostException e1) {
302 log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
303 continue;
304 }
305
306 PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
307 Rib rib = new Rib(router_id, nexthop, p.masklen);
308
309 if (node.rib != null) {
310 node.rib = null;
311 ptree.delReference(node);
312 }
313
314 node.rib = rib;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700315
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200316 prefixAdded(node);
Jonathan Hart61ba9372013-05-19 20:10:29 -0700317 }
318 }
319
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200320 public void prefixAdded(PtreeNode node) {
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700321 //Add a flow to rewrite mac for this prefix to all border switches
Jonathan Hartd1f23252013-06-13 15:17:05 +1200322 GatewayRouter thisRouter = gatewayRouters
323 .get(InetAddresses.toAddrString(node.rib.nextHop));
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700324
325 if (thisRouter == null){
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200326 //TODO local router isn't in gateway list so this will get thrown
327 //Need to work out what to do about local prefixes with next hop 0.0.0.0.
328 log.error("Couldn't find next hop router in router {} in config"
329 , node.rib.nextHop.toString());
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700330 return; //just quit out here? This is probably a configuration error
331 }
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200332
Jonathan Hartd1f23252013-06-13 15:17:05 +1200333 for (GatewayRouter ingressRouter : gatewayRouters.values()){
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700334 if (ingressRouter == thisRouter) {
335 continue;
336 }
337
338 DataPath shortestPath = topoRouteService.getShortestPath(
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200339 ingressRouter.getAttachmentPoint(),
340 thisRouter.getAttachmentPoint());
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700341
342 if (shortestPath == null){
343 log.debug("Shortest path between {} and {} not found",
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200344 ingressRouter.getAttachmentPoint(),
345 thisRouter.getAttachmentPoint());
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700346 return; // just quit here?
347 }
348
349 //TODO check the shortest path against the cached version we
350 //calculated before. If they don't match up that's a problem
351
352 //Set up the flow mod
353 OFFlowMod fm =
354 (OFFlowMod) floodlightProvider.getOFMessageFactory()
355 .getMessage(OFType.FLOW_MOD);
356
357 fm.setIdleTimeout((short)0)
358 .setHardTimeout((short)0)
359 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
360 .setCookie(MAC_RW_COOKIE)
361 .setCommand(OFFlowMod.OFPFC_ADD)
362 //.setMatch(match)
363 //.setActions(actions)
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200364 .setPriority(SDNIP_PRIORITY)
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700365 .setLengthU(OFFlowMod.MINIMUM_LENGTH
366 + OFActionDataLayerDestination.MINIMUM_LENGTH
367 + OFActionOutput.MINIMUM_LENGTH);
368
369 OFMatch match = new OFMatch();
370 match.setDataLayerType(Ethernet.TYPE_IPv4);
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200371 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700372
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200373 match.setDataLayerSource(ingressRouter.getRouterMac().toBytes());
374 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
375
376 //match.setDataLayerDestination(ingressRouter.getSdnRouterMac().toBytes());
377 //match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
378
379 InetAddress address = null;
380 try {
381 address = InetAddress.getByAddress(node.key);
382 } catch (UnknownHostException e1) {
383 //Should never happen is the reverse conversion has already been done
384 log.error("Malformed IP address");
385 return;
386 }
387
388 match.setFromCIDR(address.getHostAddress() + "/" + node.rib.masklen, OFMatch.STR_NW_DST);
389 fm.setMatch(match);
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700390
391 //Set up MAC rewrite action
392 OFActionDataLayerDestination macRewriteAction = new OFActionDataLayerDestination();
393 macRewriteAction.setDataLayerAddress(thisRouter.getRouterMac().toBytes());
394
395 //Set up output action
396 OFActionOutput outputAction = new OFActionOutput();
397 outputAction.setMaxLength((short)0xffff); //TODO check what this is (and if needed for mac rewrite)
398
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200399 Port outputPort = shortestPath.flowEntries().get(0).outPort();
400 outputAction.setPort(outputPort.value());
401
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700402 List<OFAction> actions = new ArrayList<OFAction>();
403 actions.add(macRewriteAction);
404 actions.add(outputAction);
405 fm.setActions(actions);
406
407 //Write to switch
408 IOFSwitch sw = floodlightProvider.getSwitches()
409 .get(ingressRouter.getAttachmentPoint().dpid().value());
410
411 if (sw == null){
412 log.warn("Switch not found when pushing flow mod");
413 continue;
414 }
415
416 List<OFMessage> msglist = new ArrayList<OFMessage>();
417 msglist.add(fm);
418 try {
419 sw.write(msglist, null);
420 sw.flush();
421 } catch (IOException e) {
422 log.error("Failure writing flow mod", e);
423 }
424 }
425 }
426
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200427 public void prefixDeleted(PtreeNode node) {
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700428 //Remove MAC rewriting flows from other border switches
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200429
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700430 }
431
432 /*
433 * On startup we need to calculate a full mesh of paths between all gateway
434 * switches
435 */
436 private void calculateFullMesh(){
437 Map<IOFSwitch, SwitchPort> gatewaySwitches = new HashMap<IOFSwitch, SwitchPort>();
438
439 //have to account for switches not being there, paths not being found.
440
Jonathan Hartd1f23252013-06-13 15:17:05 +1200441 for (GatewayRouter router : gatewayRouters.values()){
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700442 SwitchPort switchPort = router.getAttachmentPoint();
443
444 IOFSwitch sw = floodlightProvider.getSwitches().get(switchPort.dpid().value());
445
446 if (sw == null){
447 log.debug("Gateway switch {} not here yet", switchPort.dpid().value());
448 return; // just quit here?
449 }
450
451 //Only need to know 1 external-facing port from each gateway switch
452 //which we can feed into shortest path calculation
453 if (!gatewaySwitches.containsKey(sw)){
454 gatewaySwitches.put(sw, switchPort);
455 }
456
457 }
458 log.debug("size {}", gatewaySwitches.size());
459
460 //For each border router, calculate and install a path from every other
461 //border switch to said border router. However, don't install the entry
462 //in to the first hop switch, as we need to install an entry to rewrite
463 //for each prefix received. This will be done later when prefixes have
464 //actually been received.
465
Jonathan Hartd1f23252013-06-13 15:17:05 +1200466 for (GatewayRouter dstRouter : gatewayRouters.values()){
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700467 SwitchPort routerAttachmentPoint = dstRouter.getAttachmentPoint();
468 for (Map.Entry<IOFSwitch, SwitchPort> src : gatewaySwitches.entrySet()) {
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700469
470 if (routerAttachmentPoint.dpid().value() ==
471 src.getKey().getId()){
472 continue;
473 }
474
475 DataPath shortestPath = topoRouteService.getShortestPath(
476 src.getValue(), routerAttachmentPoint);
477
478 if (shortestPath == null){
479 log.debug("Shortest path between {} and {} not found",
480 src.getValue(), routerAttachmentPoint);
481 return; // just quit here?
482 }
483
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700484 //install flows
485 installPath(shortestPath.flowEntries(), dstRouter);
486 }
487 }
488 }
489
490 private void installPath(List<FlowEntry> flowEntries, GatewayRouter router){
491
492 //Set up the flow mod
493 OFFlowMod fm =
494 (OFFlowMod) floodlightProvider.getOFMessageFactory()
495 .getMessage(OFType.FLOW_MOD);
496
497 OFActionOutput action = new OFActionOutput();
498 action.setMaxLength((short)0xffff);
499 List<OFAction> actions = new ArrayList<OFAction>();
500 actions.add(action);
501
502 fm.setIdleTimeout((short)0)
503 .setHardTimeout((short)0)
504 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
505 .setCookie(L2_FWD_COOKIE)
506 .setCommand(OFFlowMod.OFPFC_ADD)
507 //.setMatch(match)
508 .setActions(actions)
509 .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
510
511 //Don't push the first flow entry. We need to push entries in the
512 //first switch based on IP prefix which we don't know yet.
513 for (int i = 1; i < flowEntries.size(); i++){
514 FlowEntry flowEntry = flowEntries.get(i);
515
516 OFMatch match = new OFMatch();
517 match.setDataLayerDestination(router.getRouterMac().toBytes());
518 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
519 ((OFActionOutput) fm.getActions().get(0)).setPort(flowEntry.outPort().value());
520
521 fm.setMatch(match);
522
523 IOFSwitch sw = floodlightProvider.getSwitches().get(flowEntry.dpid().value());
524
525 if (sw == null){
526 log.warn("Switch not found when pushing flow mod");
527 continue;
528 }
529
530 List<OFMessage> msglist = new ArrayList<OFMessage>();
531 msglist.add(fm);
532 try {
533 sw.write(msglist, null);
534 sw.flush();
535 } catch (IOException e) {
536 log.error("Failure writing flow mod", e);
537 }
538
539 try {
540 fm = fm.clone();
541 } catch (CloneNotSupportedException e1) {
542 log.error("Failure cloning flow mod", e1);
543 }
544 }
545 }
546
pingping-lina2cbfad2013-03-07 08:39:21 +0800547 @Override
548 public void startUp(FloodlightModuleContext context) {
pingping-line2a09ca2013-03-23 09:33:58 +0800549 restApi.addRestletRoutable(new BgpRouteWebRoutable());
Jonathan Hart61ba9372013-05-19 20:10:29 -0700550 topology.addListener(this);
pingping-line2a09ca2013-03-23 09:33:58 +0800551
Jonathan Hart61ba9372013-05-19 20:10:29 -0700552 //Retrieve the RIB from BGPd during startup
553 retrieveRib();
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700554
555 //Don't have to do this as we'll never have switches connected here
556 //calculateFullMesh();
pingping-lina2cbfad2013-03-07 08:39:21 +0800557 }
558
559 @Override
560 public void topologyChanged() {
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700561 //Probably need to look at all changes, not just port changes
562 /*
pingping-lina2cbfad2013-03-07 08:39:21 +0800563 boolean change = false;
564 String changelog = "";
565
566 for (LDUpdate ldu : topology.getLastLinkUpdates()) {
567 if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_DOWN)) {
568 change = true;
569 changelog = changelog + " down ";
570 } else if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_UP)) {
571 change = true;
572 changelog = changelog + " up ";
573 }
574 }
575 log.info ("received topo change" + changelog);
576
577 if (change) {
Jonathan Hart61ba9372013-05-19 20:10:29 -0700578 //RestClient.get ("http://localhost:5000/topo_change");
pingping-lina2cbfad2013-03-07 08:39:21 +0800579 }
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700580 */
Jonathan Hart50a8d1e2013-06-06 16:00:47 +1200581
582 for (LDUpdate update : topology.getLastLinkUpdates()){
583 log.debug("{} event causing internal L2 path recalculation",
584 update.getOperation().toString());
585
586 }
Jonathan Harte7e1c6e2013-06-04 20:50:23 -0700587 calculateFullMesh();
pingping-lina2cbfad2013-03-07 08:39:21 +0800588 }
589}