blob: 3b564689343eb6f013da1b1e8aa9d49eaa97e91a [file] [log] [blame]
Jonathan Hart8f6dc092014-04-18 15:56:43 -07001package net.onrc.onos.apps.sdnip;
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;
pingping-lina2cbfad2013-03-07 08:39:21 +08006import java.util.ArrayList;
Jonathan Hart61ba9372013-05-19 20:10:29 -07007import java.util.Collection;
pingping-lina2cbfad2013-03-07 08:39:21 +08008import java.util.HashMap;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -07009import java.util.List;
Jonathan Hart61ba9372013-05-19 20:10:29 -070010import java.util.Map;
Jonathan Hart4dfc3652013-08-02 20:22:36 +120011import java.util.Set;
Jonathan Hart8b9349e2013-07-26 15:55:28 +120012import java.util.concurrent.BlockingQueue;
13import java.util.concurrent.ExecutorService;
Jonathan Hart98957bf2013-07-01 14:49:24 +120014import java.util.concurrent.Executors;
Jonathan Hart8b9349e2013-07-26 15:55:28 +120015import java.util.concurrent.LinkedBlockingQueue;
Jonathan Hart98957bf2013-07-01 14:49:24 +120016import java.util.concurrent.ScheduledExecutorService;
17import java.util.concurrent.TimeUnit;
pingping-lina2cbfad2013-03-07 08:39:21 +080018
Jonathan Hart61ba9372013-05-19 20:10:29 -070019import net.floodlightcontroller.core.IFloodlightProviderService;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070020import net.floodlightcontroller.core.IOFSwitch;
Jonathan Hart64c0b202013-08-20 15:45:07 +120021import net.floodlightcontroller.core.IOFSwitchListener;
pingping-lina2cbfad2013-03-07 08:39:21 +080022import net.floodlightcontroller.core.module.FloodlightModuleContext;
23import net.floodlightcontroller.core.module.FloodlightModuleException;
24import net.floodlightcontroller.core.module.IFloodlightModule;
25import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart98957bf2013-07-01 14:49:24 +120026import net.floodlightcontroller.core.util.SingletonTask;
pingping-lina2cbfad2013-03-07 08:39:21 +080027import net.floodlightcontroller.restserver.IRestApiService;
Jonathan Hart4dfc3652013-08-02 20:22:36 +120028import net.floodlightcontroller.util.MACAddress;
Jonathan Hart0961fe82014-04-03 09:56:25 -070029import net.onrc.onos.apps.proxyarp.IArpRequester;
30import net.onrc.onos.apps.proxyarp.IProxyArpService;
Jonathan Hart8f6dc092014-04-18 15:56:43 -070031import net.onrc.onos.apps.sdnip.RibUpdate.Operation;
Komal Shah399a2922014-05-28 01:57:40 -070032import net.onrc.onos.apps.sdnip.web.SdnIpWebRoutableNew;
33import net.onrc.onos.core.intent.IntentOperation;
34import net.onrc.onos.core.intent.IntentOperationList;
35import net.onrc.onos.core.intent.ShortestPathIntent;
36import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService;
Jonathan Hart23701d12014-04-03 10:45:48 -070037import net.onrc.onos.core.linkdiscovery.ILinkDiscovery.LDUpdate;
Jonathan Harta99ec672014-04-03 11:30:34 -070038import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
Jonathan Hart51f6f5b2014-04-03 10:32:10 -070039import net.onrc.onos.core.main.config.IConfigInfoService;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070040import net.onrc.onos.core.packet.Ethernet;
41import net.onrc.onos.core.packet.IPv4;
Komal Shah399a2922014-05-28 01:57:40 -070042import net.onrc.onos.core.registry.IControllerRegistryService;
Jonathan Hart23701d12014-04-03 10:45:48 -070043import net.onrc.onos.core.util.CallerId;
44import net.onrc.onos.core.util.DataPath;
45import net.onrc.onos.core.util.Dpid;
46import net.onrc.onos.core.util.FlowEntryAction;
47import net.onrc.onos.core.util.FlowEntryActions;
48import net.onrc.onos.core.util.FlowEntryMatch;
49import net.onrc.onos.core.util.FlowId;
50import net.onrc.onos.core.util.FlowPath;
51import net.onrc.onos.core.util.FlowPathFlags;
52import net.onrc.onos.core.util.FlowPathType;
53import net.onrc.onos.core.util.FlowPathUserState;
54import net.onrc.onos.core.util.IPv4Net;
Yuta HIGUCHIfb564502014-06-16 21:29:00 -070055import net.onrc.onos.core.util.PortNumber;
Jonathan Hart23701d12014-04-03 10:45:48 -070056import net.onrc.onos.core.util.SwitchPort;
pingping-line2a09ca2013-03-23 09:33:58 +080057import net.sf.json.JSONArray;
58import net.sf.json.JSONObject;
59import net.sf.json.JSONSerializer;
pingping-lina2cbfad2013-03-07 08:39:21 +080060
Jonathan Hartec9ee2e2014-04-08 22:45:44 -070061import org.apache.commons.configuration.ConfigurationRuntimeException;
Jonathan Hartd1f23252013-06-13 15:17:05 +120062import org.codehaus.jackson.JsonParseException;
63import org.codehaus.jackson.map.JsonMappingException;
64import org.codehaus.jackson.map.ObjectMapper;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070065import org.openflow.protocol.OFFlowMod;
66import org.openflow.protocol.OFMatch;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070067import org.openflow.protocol.OFPacketOut;
Jonathan Hart9575cb62013-07-05 13:43:49 +120068import org.openflow.protocol.OFPort;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070069import org.openflow.protocol.action.OFAction;
Jonathan Harte7e1c6e2013-06-04 20:50:23 -070070import org.openflow.protocol.action.OFActionOutput;
Jonathan Hart1236a9b2013-06-18 22:10:05 +120071import org.openflow.util.HexString;
pingping-lina2cbfad2013-03-07 08:39:21 +080072import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74
Jonathan Hart4dfc3652013-08-02 20:22:36 +120075import com.google.common.collect.HashMultimap;
Jonathan Hart0ee0f022013-08-03 22:21:54 +120076import com.google.common.collect.Multimap;
Jonathan Hart4dfc3652013-08-02 20:22:36 +120077import com.google.common.collect.Multimaps;
78import com.google.common.collect.SetMultimap;
Jonathan Hart309889c2013-08-13 23:26:24 +120079import com.google.common.net.InetAddresses;
Jonathan Hart8b9349e2013-07-26 15:55:28 +120080import com.google.common.util.concurrent.ThreadFactoryBuilder;
81
Jonathan Hart8f6dc092014-04-18 15:56:43 -070082public class SdnIp implements IFloodlightModule, ISdnIpService,
Ray Milkey269ffb92014-04-03 14:43:30 -070083 IArpRequester,
84 IOFSwitchListener, IConfigInfoService {
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -070085
Jonathan Hart8f6dc092014-04-18 15:56:43 -070086 private static final Logger log = LoggerFactory.getLogger(SdnIp.class);
pingping-lina2cbfad2013-03-07 08:39:21 +080087
Ray Milkey269ffb92014-04-03 14:43:30 -070088 private IFloodlightProviderService floodlightProvider;
89 private ILinkDiscoveryService linkDiscoveryService;
90 private IRestApiService restApi;
91 private IProxyArpService proxyArp;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -070092
Jonathan Hart5e54f2e2014-04-17 13:43:40 -070093 private IPatriciaTree<RibEntry> ptree;
94 private IPatriciaTree<Interface> interfacePtree;
Ray Milkey269ffb92014-04-03 14:43:30 -070095 private BlockingQueue<RibUpdate> ribUpdates;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -070096
Ray Milkey269ffb92014-04-03 14:43:30 -070097 private String bgpdRestIp;
98 private String routerId;
Ray Milkey5df613b2014-04-15 10:50:56 -070099 private static final String DEFAULT_CONFIG_FILENAME = "config.json";
100 private String currentConfigFilename = DEFAULT_CONFIG_FILENAME;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700101
Komal Shah399a2922014-05-28 01:57:40 -0700102 /* ShortestPath Intent Variables */
103 private final String callerId = "SdnIp";
104 private IControllerRegistryService controllerRegistryService;
105 private IPathCalcRuntimeService pathRuntime;
106 /* Shortest Intent Path Variables */
107
Ray Milkey2476cac2014-04-08 11:03:21 -0700108 private static final short ARP_PRIORITY = 20;
Ray Milkey5d406012014-04-08 14:44:41 -0700109
Jonathan Hart938a0152014-04-07 18:27:31 -0700110 // The fields below are unused after the move to FlowManager.
111 // Remove them if no longer needed.
112 /*
113 // We need to identify our flows somehow, in lieu of an OS-wide mechanism
114 // to hand out cookie IDs to prevent conflicts.
115 private static final long APP_COOKIE = 0xa0000000000000L;
116 // Cookie for flows that do L2 forwarding within SDN domain to egress routers
117 private static final long L2_FWD_COOKIE = APP_COOKIE + 1;
118 // Cookie for flows in ingress switches that rewrite the MAC address
119 private static final long MAC_RW_COOKIE = APP_COOKIE + 2;
120 // Cookie for flows that setup BGP paths
121 private static final long BGP_COOKIE = APP_COOKIE + 3;
122 // Forwarding uses priority 0, and the mac rewrite entries in ingress switches
123 // need to be higher priority than this otherwise the rewrite may not get done
124 private static final short SDNIP_PRIORITY = 10;
125 */
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700126
Ray Milkey2476cac2014-04-08 11:03:21 -0700127 private static final short BGP_PORT = 179;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700128
Jonathan Hart938a0152014-04-07 18:27:31 -0700129 private static final int TOPO_DETECTION_WAIT = 2; // seconds
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700130
Jonathan Hart938a0152014-04-07 18:27:31 -0700131 // Configuration stuff
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 private List<String> switches;
133 private Map<String, Interface> interfaces;
134 private Map<InetAddress, BgpPeer> bgpPeers;
135 private SwitchPort bgpdAttachmentPoint;
136 private MACAddress bgpdMacAddress;
137 private short vlan;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700138
Jonathan Hart938a0152014-04-07 18:27:31 -0700139 // True when all switches have connected
Ray Milkey269ffb92014-04-03 14:43:30 -0700140 private volatile boolean switchesConnected = false;
Jonathan Hart938a0152014-04-07 18:27:31 -0700141 // True when we have a full mesh of shortest paths between gateways
Ray Milkey269ffb92014-04-03 14:43:30 -0700142 private volatile boolean topologyReady = false;
Jonathan Hart98957bf2013-07-01 14:49:24 +1200143
Jonathan Hart938a0152014-04-07 18:27:31 -0700144 private List<LDUpdate> linkUpdates;
Ray Milkey269ffb92014-04-03 14:43:30 -0700145 private SingletonTask topologyChangeDetectorTask;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700146
Ray Milkey269ffb92014-04-03 14:43:30 -0700147 private SetMultimap<InetAddress, RibUpdate> prefixesWaitingOnArp;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700148
Ray Milkey269ffb92014-04-03 14:43:30 -0700149 private Map<InetAddress, Path> pathsWaitingOnArp;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700150
Ray Milkey269ffb92014-04-03 14:43:30 -0700151 private ExecutorService bgpUpdatesExecutor;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700152
Ray Milkey269ffb92014-04-03 14:43:30 -0700153 private Map<InetAddress, Path> pushedPaths;
154 private Map<Prefix, Path> prefixToPath;
155 // private Multimap<Prefix, PushedFlowMod> pushedFlows;
156 private Multimap<Prefix, FlowId> pushedFlowIds;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700157
Ray Milkey269ffb92014-04-03 14:43:30 -0700158 private FlowCache flowCache;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700159
Ray Milkey269ffb92014-04-03 14:43:30 -0700160 // TODO: Fix for the new Topology Network Graph
161 // private volatile Topology topology = null;
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700162
Ray Milkey269ffb92014-04-03 14:43:30 -0700163 private class TopologyChangeDetector implements Runnable {
164 @Override
165 public void run() {
166 log.debug("Running topology change detection task");
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700167 // TODO: Fix the code below after topoLinkService was removed
168 /*
Ray Milkey269ffb92014-04-03 14:43:30 -0700169 synchronized (linkUpdates) {
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700170
Ray Milkey269ffb92014-04-03 14:43:30 -0700171 ITopoLinkService topoLinkService = new TopoLinkServiceImpl();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700172
Ray Milkey269ffb92014-04-03 14:43:30 -0700173 List<Link> activeLinks = topoLinkService.getActiveLinks();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700174
Ray Milkey269ffb92014-04-03 14:43:30 -0700175 Iterator<LDUpdate> it = linkUpdates.iterator();
176 while (it.hasNext()){
177 LDUpdate ldu = it.next();
178 Link l = new Link(ldu.getSrc(), ldu.getSrcPort(),
179 ldu.getDst(), ldu.getDstPort());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700180
Ray Milkey269ffb92014-04-03 14:43:30 -0700181 if (activeLinks.contains(l)){
182 it.remove();
183 }
184 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700185 }
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700186 */
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700187
Ray Milkey269ffb92014-04-03 14:43:30 -0700188 if (!topologyReady) {
189 if (linkUpdates.isEmpty()) {
Jonathan Hart938a0152014-04-07 18:27:31 -0700190 // All updates have been seen in network map.
191 // We can check if topology is ready
Ray Milkey269ffb92014-04-03 14:43:30 -0700192 log.debug("No known changes outstanding. Checking topology now");
193 checkStatus();
194 } else {
Jonathan Hart938a0152014-04-07 18:27:31 -0700195 // We know of some link updates that haven't propagated to the database yet
Ray Milkey269ffb92014-04-03 14:43:30 -0700196 log.debug("Some changes not found in network map - {} links missing", linkUpdates.size());
197 topologyChangeDetectorTask.reschedule(TOPO_DETECTION_WAIT, TimeUnit.SECONDS);
198 }
199 }
200 }
201 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700202
Ray Milkey269ffb92014-04-03 14:43:30 -0700203 private void readConfiguration(String configFilename) {
204 File gatewaysFile = new File(configFilename);
205 ObjectMapper mapper = new ObjectMapper();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700206
Ray Milkey269ffb92014-04-03 14:43:30 -0700207 try {
208 Configuration config = mapper.readValue(gatewaysFile, Configuration.class);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700209
Ray Milkey269ffb92014-04-03 14:43:30 -0700210 switches = config.getSwitches();
211 interfaces = new HashMap<String, Interface>();
212 for (Interface intf : config.getInterfaces()) {
213 interfaces.put(intf.getName(), intf);
214 }
215 bgpPeers = new HashMap<InetAddress, BgpPeer>();
216 for (BgpPeer peer : config.getPeers()) {
217 bgpPeers.put(peer.getIpAddress(), peer);
218 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700219
Ray Milkey269ffb92014-04-03 14:43:30 -0700220 bgpdAttachmentPoint = new SwitchPort(
221 new Dpid(config.getBgpdAttachmentDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700222 new PortNumber(config.getBgpdAttachmentPort()));
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700223
Ray Milkey269ffb92014-04-03 14:43:30 -0700224 bgpdMacAddress = config.getBgpdMacAddress();
225 vlan = config.getVlan();
226 } catch (JsonParseException e) {
227 log.error("Error in JSON file", e);
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700228 throw new ConfigurationRuntimeException("Error in JSON file", e);
Ray Milkey269ffb92014-04-03 14:43:30 -0700229 } catch (JsonMappingException e) {
230 log.error("Error in JSON file", e);
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700231 throw new ConfigurationRuntimeException("Error in JSON file", e);
Ray Milkey269ffb92014-04-03 14:43:30 -0700232 } catch (IOException e) {
233 log.error("Error reading JSON file", e);
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700234 throw new ConfigurationRuntimeException("Error in JSON file", e);
Ray Milkey269ffb92014-04-03 14:43:30 -0700235 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700236
Jonathan Hart5e54f2e2014-04-17 13:43:40 -0700237 // Populate the interface Patricia Tree
Ray Milkey269ffb92014-04-03 14:43:30 -0700238 for (Interface intf : interfaces.values()) {
239 Prefix prefix = new Prefix(intf.getIpAddress().getAddress(), intf.getPrefixLength());
Jonathan Hart5e54f2e2014-04-17 13:43:40 -0700240 interfacePtree.put(prefix, intf);
Ray Milkey269ffb92014-04-03 14:43:30 -0700241 }
242 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700243
Ray Milkey269ffb92014-04-03 14:43:30 -0700244 @Override
245 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
246 Collection<Class<? extends IFloodlightService>> l
247 = new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hart8f6dc092014-04-18 15:56:43 -0700248 l.add(ISdnIpService.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700249 l.add(IConfigInfoService.class);
250 return l;
251 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700252
Ray Milkey269ffb92014-04-03 14:43:30 -0700253 @Override
254 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
255 Map<Class<? extends IFloodlightService>, IFloodlightService> m
256 = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
Jonathan Hart8f6dc092014-04-18 15:56:43 -0700257 m.put(ISdnIpService.class, this);
Ray Milkey269ffb92014-04-03 14:43:30 -0700258 m.put(IConfigInfoService.class, this);
259 return m;
260 }
pingping-lina2cbfad2013-03-07 08:39:21 +0800261
Ray Milkey269ffb92014-04-03 14:43:30 -0700262 @Override
263 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
264 Collection<Class<? extends IFloodlightService>> l
265 = new ArrayList<Class<? extends IFloodlightService>>();
266 l.add(IFloodlightProviderService.class);
267 l.add(IRestApiService.class);
Komal Shah399a2922014-05-28 01:57:40 -0700268 l.add(IControllerRegistryService.class);
269 l.add(IPathCalcRuntimeService.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700270 return l;
271 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700272
Ray Milkey269ffb92014-04-03 14:43:30 -0700273 @Override
274 public void init(FloodlightModuleContext context)
275 throws FloodlightModuleException {
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700276
Jonathan Hart5e54f2e2014-04-17 13:43:40 -0700277 ptree = new PatriciaTree<RibEntry>(32);
278 interfacePtree = new PatriciaTree<Interface>(32);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700279
Ray Milkey269ffb92014-04-03 14:43:30 -0700280 ribUpdates = new LinkedBlockingQueue<RibUpdate>();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700281
Ray Milkey269ffb92014-04-03 14:43:30 -0700282 // Register floodlight provider and REST handler.
283 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
284 linkDiscoveryService = context.getServiceImpl(ILinkDiscoveryService.class);
285 restApi = context.getServiceImpl(IRestApiService.class);
286 proxyArp = context.getServiceImpl(IProxyArpService.class);
pingping-linba5c52f2014-02-11 16:52:01 -0800287
Komal Shah399a2922014-05-28 01:57:40 -0700288 controllerRegistryService = context.getServiceImpl(IControllerRegistryService.class);
289 pathRuntime = context.getServiceImpl(IPathCalcRuntimeService.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700290 linkUpdates = new ArrayList<LDUpdate>();
291 ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
292 topologyChangeDetectorTask = new SingletonTask(executor, new TopologyChangeDetector());
Pavlin Radoslavovddd01ba2013-07-03 15:40:44 -0700293
Ray Milkey269ffb92014-04-03 14:43:30 -0700294 pathsWaitingOnArp = new HashMap<InetAddress, Path>();
295 prefixesWaitingOnArp = Multimaps.synchronizedSetMultimap(
296 HashMultimap.<InetAddress, RibUpdate>create());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700297
Ray Milkey269ffb92014-04-03 14:43:30 -0700298 pushedPaths = new HashMap<InetAddress, Path>();
299 prefixToPath = new HashMap<Prefix, Path>();
300// pushedFlows = HashMultimap.<Prefix, PushedFlowMod>create();
301 pushedFlowIds = HashMultimap.<Prefix, FlowId>create();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700302
Ray Milkey269ffb92014-04-03 14:43:30 -0700303 flowCache = new FlowCache(floodlightProvider);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700304
Ray Milkey269ffb92014-04-03 14:43:30 -0700305 bgpUpdatesExecutor = Executors.newSingleThreadExecutor(
306 new ThreadFactoryBuilder().setNameFormat("bgp-updates-%d").build());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700307
Jonathan Hart938a0152014-04-07 18:27:31 -0700308 // Read in config values
Ray Milkey269ffb92014-04-03 14:43:30 -0700309 bgpdRestIp = context.getConfigParams(this).get("BgpdRestIp");
310 if (bgpdRestIp == null) {
311 log.error("BgpdRestIp property not found in config file");
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700312 throw new ConfigurationRuntimeException(
313 "BgpdRestIp property not found in config file");
Ray Milkey269ffb92014-04-03 14:43:30 -0700314 } else {
315 log.info("BgpdRestIp set to {}", bgpdRestIp);
316 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700317
Ray Milkey269ffb92014-04-03 14:43:30 -0700318 routerId = context.getConfigParams(this).get("RouterId");
319 if (routerId == null) {
320 log.error("RouterId property not found in config file");
Jonathan Hartec9ee2e2014-04-08 22:45:44 -0700321 throw new ConfigurationRuntimeException(
322 "RouterId property not found in config file");
Ray Milkey269ffb92014-04-03 14:43:30 -0700323 } else {
324 log.info("RouterId set to {}", routerId);
325 }
pingping-linba5c52f2014-02-11 16:52:01 -0800326
Ray Milkey269ffb92014-04-03 14:43:30 -0700327 String configFilenameParameter = context.getConfigParams(this).get("configfile");
328 if (configFilenameParameter != null) {
Ray Milkey5df613b2014-04-15 10:50:56 -0700329 currentConfigFilename = configFilenameParameter;
Ray Milkey269ffb92014-04-03 14:43:30 -0700330 }
Ray Milkey5df613b2014-04-15 10:50:56 -0700331 log.debug("Config file set to {}", currentConfigFilename);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700332
Ray Milkey5df613b2014-04-15 10:50:56 -0700333 readConfiguration(currentConfigFilename);
Ray Milkey269ffb92014-04-03 14:43:30 -0700334 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700335
Ray Milkey269ffb92014-04-03 14:43:30 -0700336 @Override
337 public void startUp(FloodlightModuleContext context) {
Komal Shah399a2922014-05-28 01:57:40 -0700338 //restApi.addRestletRoutable(new SdnIpWebRoutable());
339 restApi.addRestletRoutable(new SdnIpWebRoutableNew());
Ray Milkey269ffb92014-04-03 14:43:30 -0700340 floodlightProvider.addOFSwitchListener(this);
pingping-linba5c52f2014-02-11 16:52:01 -0800341
Jonathan Hart938a0152014-04-07 18:27:31 -0700342 // Retrieve the RIB from BGPd during startup
Ray Milkey269ffb92014-04-03 14:43:30 -0700343 retrieveRib();
344 }
pingping-lina2cbfad2013-03-07 08:39:21 +0800345
Ray Milkey269ffb92014-04-03 14:43:30 -0700346 @Override
Jonathan Hart5e54f2e2014-04-17 13:43:40 -0700347 public IPatriciaTree<RibEntry> getPtree() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700348 return ptree;
349 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700350
Ray Milkey269ffb92014-04-03 14:43:30 -0700351 @Override
352 public void clearPtree() {
Jonathan Hart5e54f2e2014-04-17 13:43:40 -0700353 ptree = new PatriciaTree<RibEntry>(32);
Ray Milkey269ffb92014-04-03 14:43:30 -0700354 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700355
Ray Milkey269ffb92014-04-03 14:43:30 -0700356 @Override
Jonathan Hart31e15f12014-04-10 10:33:00 -0700357 public String getBgpdRestIp() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700358 return bgpdRestIp;
359 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700360
Ray Milkey269ffb92014-04-03 14:43:30 -0700361 @Override
362 public String getRouterId() {
363 return routerId;
364 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700365
Ray Milkey269ffb92014-04-03 14:43:30 -0700366 private void retrieveRib() {
367 String url = "http://" + bgpdRestIp + "/wm/bgp/" + routerId;
368 String response = RestClient.get(url);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700369
Jonathan Hart938a0152014-04-07 18:27:31 -0700370 if ("".equals(response)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700371 return;
372 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700373
Ray Milkey269ffb92014-04-03 14:43:30 -0700374 response = response.replaceAll("\"", "'");
375 JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(response);
Jonathan Hart938a0152014-04-07 18:27:31 -0700376 JSONArray ribArray = jsonObj.getJSONArray("rib");
Ray Milkey5df613b2014-04-15 10:50:56 -0700377 String inboundRouterId = jsonObj.getString("router-id");
Jonathan Hart61ba9372013-05-19 20:10:29 -0700378
Jonathan Hart938a0152014-04-07 18:27:31 -0700379 int size = ribArray.size();
Jonathan Hart61ba9372013-05-19 20:10:29 -0700380
Ray Milkey269ffb92014-04-03 14:43:30 -0700381 log.info("Retrived RIB of {} entries from BGPd", size);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700382
Ray Milkey269ffb92014-04-03 14:43:30 -0700383 for (int j = 0; j < size; j++) {
Jonathan Hart938a0152014-04-07 18:27:31 -0700384 JSONObject ribEntry = ribArray.getJSONObject(j);
385 String prefix = ribEntry.getString("prefix");
386 String nexthop = ribEntry.getString("nexthop");
Jonathan Hart61ba9372013-05-19 20:10:29 -0700387
Jonathan Hart938a0152014-04-07 18:27:31 -0700388 // Insert each rib entry into the local rib
Ray Milkey269ffb92014-04-03 14:43:30 -0700389 String[] substring = prefix.split("/");
390 String prefix1 = substring[0];
391 String mask1 = substring[1];
Jonathan Hart61ba9372013-05-19 20:10:29 -0700392
Ray Milkey269ffb92014-04-03 14:43:30 -0700393 Prefix p;
394 try {
Yuta HIGUCHI0fe749a2014-05-27 09:35:16 -0700395 p = new Prefix(prefix1, Integer.parseInt(mask1));
Ray Milkey269ffb92014-04-03 14:43:30 -0700396 } catch (NumberFormatException e) {
397 log.warn("Wrong mask format in RIB JSON: {}", mask1);
398 continue;
399 } catch (IllegalArgumentException e1) {
400 log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
401 continue;
402 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700403
Ray Milkey5df613b2014-04-15 10:50:56 -0700404 RibEntry rib = new RibEntry(inboundRouterId, nexthop);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700405
Ray Milkey269ffb92014-04-03 14:43:30 -0700406 try {
407 ribUpdates.put(new RibUpdate(Operation.UPDATE, p, rib));
408 } catch (InterruptedException e) {
409 log.debug("Interrupted while pushing onto update queue");
410 }
411 }
412 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700413
Ray Milkey269ffb92014-04-03 14:43:30 -0700414 @Override
415 public void newRibUpdate(RibUpdate update) {
416 try {
417 ribUpdates.put(update);
418 } catch (InterruptedException e) {
419 log.debug("Interrupted while putting on ribUpdates queue", e);
420 Thread.currentThread().interrupt();
421 }
422 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700423
Jonathan Hart938a0152014-04-07 18:27:31 -0700424 public void processRibAdd(RibUpdate update) {
425 synchronized (this) {
426 Prefix prefix = update.getPrefix();
Ray Milkey5d406012014-04-08 14:44:41 -0700427
Jonathan Hart938a0152014-04-07 18:27:31 -0700428 log.debug("Processing prefix add {}", prefix);
Ray Milkey5d406012014-04-08 14:44:41 -0700429
Jonathan Hart938a0152014-04-07 18:27:31 -0700430 RibEntry rib = ptree.put(prefix, update.getRibEntry());
Ray Milkey5d406012014-04-08 14:44:41 -0700431
Jonathan Hart938a0152014-04-07 18:27:31 -0700432 if (rib != null && !rib.equals(update.getRibEntry())) {
433 // There was an existing nexthop for this prefix. This update supersedes that,
434 // so we need to remove the old flows for this prefix from the switches
Ray Milkey7531a342014-04-11 15:08:12 -0700435 executeDeletePrefix(prefix, rib);
Jonathan Hart938a0152014-04-07 18:27:31 -0700436 }
Ray Milkey5d406012014-04-08 14:44:41 -0700437
Jonathan Hart938a0152014-04-07 18:27:31 -0700438 if (update.getRibEntry().getNextHop().equals(
439 InetAddresses.forString("0.0.0.0"))) {
440 // Route originated by SDN domain
441 // We don't handle these at the moment
442 log.debug("Own route {} to {}", prefix,
443 update.getRibEntry().getNextHop().getHostAddress());
444 return;
445 }
Ray Milkey5d406012014-04-08 14:44:41 -0700446
Ray Milkey7531a342014-04-11 15:08:12 -0700447 executeRibAdd(update);
Ray Milkey269ffb92014-04-03 14:43:30 -0700448 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700449 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700450
Ray Milkey7531a342014-04-11 15:08:12 -0700451 private void executeRibAdd(RibUpdate update) {
Pavlin Radoslavov9fc535a2014-04-11 13:00:12 -0700452 // TODO: Fix the code below. Note that "deviceStorage" was removed.
453
454 /*
Ray Milkey269ffb92014-04-03 14:43:30 -0700455 Prefix prefix = update.getPrefix();
456 RibEntry rib = update.getRibEntry();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700457
Ray Milkey269ffb92014-04-03 14:43:30 -0700458 InetAddress dstIpAddress = rib.getNextHop();
459 MACAddress nextHopMacAddress = null;
pingping-linba5c52f2014-02-11 16:52:01 -0800460
Ray Milkey269ffb92014-04-03 14:43:30 -0700461 // See if we know the MAC address of the next hop
462 // TODO if we do not treat the next hop as a device in the future, we need to update this
Ray Milkey269ffb92014-04-03 14:43:30 -0700463 IDeviceObject nextHopDevice =
464 deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(dstIpAddress));
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700465
Ray Milkey269ffb92014-04-03 14:43:30 -0700466 if (nextHopDevice == null){
467 log.debug("NextHopDevice for IP: {} is null", dstIpAddress);
468 prefixesWaitingOnArp.put(dstIpAddress,
469 new RibUpdate(Operation.UPDATE, prefix, rib));
470 proxyArp.sendArpRequest(dstIpAddress, this, true);
471 return;
pingping-linba5c52f2014-02-11 16:52:01 -0800472
Ray Milkey269ffb92014-04-03 14:43:30 -0700473 }
474 nextHopMacAddress = MACAddress.valueOf(nextHopDevice.getMACAddress());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700475
Ray Milkey269ffb92014-04-03 14:43:30 -0700476 // Find the attachment point (egress interface) of the next hop
477 Interface egressInterface = null;
478 if (bgpPeers.containsKey(dstIpAddress)) {
479 //Route to a peer
480 log.debug("Route to peer {}", dstIpAddress);
481 BgpPeer peer = bgpPeers.get(dstIpAddress);
482 egressInterface = interfaces.get(peer.getInterfaceName());
483 } else {
484 //Route to non-peer
485 log.debug("Route to non-peer {}", dstIpAddress);
Jonathan Hart5e54f2e2014-04-17 13:43:40 -0700486 egressInterface = interfacePtree.match(
Ray Milkey269ffb92014-04-03 14:43:30 -0700487 new Prefix(dstIpAddress.getAddress(), 32));
488 if (egressInterface == null) {
489 log.warn("No outgoing interface found for {}", dstIpAddress.getHostAddress());
490 return;
491 }
492 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700493
Ray Milkey269ffb92014-04-03 14:43:30 -0700494 if (nextHopMacAddress == null) {
495 prefixesWaitingOnArp.put(dstIpAddress,
496 new RibUpdate(Operation.UPDATE, prefix, rib));
497 proxyArp.sendArpRequest(dstIpAddress, this, true);
498 return;
499 } else {
500 if (!bgpPeers.containsKey(dstIpAddress)) {
501 //If the prefix is for a non-peer we need to ensure there's a path,
502 //and push one if there isn't.
503 Path path = pushedPaths.get(dstIpAddress);
504 if (path == null) {
505 path = new Path(egressInterface, dstIpAddress);
506 calculateAndPushPath(path, nextHopMacAddress);
507 pushedPaths.put(dstIpAddress, path);
508 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700509
Ray Milkey269ffb92014-04-03 14:43:30 -0700510 path.incrementUsers();
511 prefixToPath.put(prefix, path);
512 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700513
Ray Milkey269ffb92014-04-03 14:43:30 -0700514 //For all prefixes we need to add the first-hop mac-rewriting flows
515 addPrefixFlows(prefix, egressInterface, nextHopMacAddress);
516 }
Pavlin Radoslavov9fc535a2014-04-11 13:00:12 -0700517 */
Ray Milkey269ffb92014-04-03 14:43:30 -0700518 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700519
Ray Milkey269ffb92014-04-03 14:43:30 -0700520 /**
521 * Add a flow to match dst-IP prefix and rewrite MAC for one IP prefix
Ray Milkeyb41100a2014-04-10 10:42:15 -0700522 * to all other border switches.
Ray Milkey269ffb92014-04-03 14:43:30 -0700523 */
524 private void addPrefixFlows(Prefix prefix, Interface egressInterface,
525 MACAddress nextHopMacAddress) {
526 log.debug("Adding flows for prefix {}, next hop mac {}",
527 prefix, nextHopMacAddress);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700528
Ray Milkey269ffb92014-04-03 14:43:30 -0700529 FlowPath flowPath = new FlowPath();
530 flowPath.setInstallerId(new CallerId("SDNIP"));
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700531
Ray Milkey269ffb92014-04-03 14:43:30 -0700532 // Set flowPath FlowPathType and FlowPathUserState
533 flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
534 flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
pingping-linba5c52f2014-02-11 16:52:01 -0800535
Ray Milkey269ffb92014-04-03 14:43:30 -0700536 // Insert dst-ip prefix based forwarding and MAC rewrite flow entry
537 // only to the first-host switches
538 FlowPathFlags flowPathFlags = new FlowPathFlags();
539 flowPathFlags.setFlags(FlowPathFlags.KEEP_ONLY_FIRST_HOP_ENTRY);
540 flowPath.setFlowPathFlags(flowPathFlags);
pingping-linba5c52f2014-02-11 16:52:01 -0800541
Ray Milkey269ffb92014-04-03 14:43:30 -0700542 // Create the DataPath object: dstSwitchPort
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700543 SwitchPort dstPort =
544 new SwitchPort(new Dpid(egressInterface.getDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700545 new PortNumber(egressInterface.getPort()));
pingping-linba5c52f2014-02-11 16:52:01 -0800546
Ray Milkey269ffb92014-04-03 14:43:30 -0700547 // We only need one flow mod per switch, so pick one interface on each switch
548 Map<Long, Interface> srcInterfaces = new HashMap<Long, Interface>();
549 for (Interface intf : interfaces.values()) {
550 if (!srcInterfaces.containsKey(intf.getDpid())
551 && !intf.equals(egressInterface)) {
552 srcInterfaces.put(intf.getDpid(), intf);
553 }
554 }
555 for (Interface srcInterface : srcInterfaces.values()) {
pingping-linba5c52f2014-02-11 16:52:01 -0800556
Ray Milkey269ffb92014-04-03 14:43:30 -0700557 if (egressInterface.equals(srcInterface)) {
558 continue;
559 }
pingping-linba5c52f2014-02-11 16:52:01 -0800560
Ray Milkey269ffb92014-04-03 14:43:30 -0700561 // Create flowPath FlowId
562 flowPath.setFlowId(new FlowId());
pingping-linba5c52f2014-02-11 16:52:01 -0800563
Ray Milkey269ffb92014-04-03 14:43:30 -0700564 // Create DataPath object: srcSwitchPort
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700565 SwitchPort srcPort =
566 new SwitchPort(new Dpid(srcInterface.getDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700567 new PortNumber(srcInterface.getPort()));
pingping-linba5c52f2014-02-11 16:52:01 -0800568
Ray Milkey269ffb92014-04-03 14:43:30 -0700569 DataPath dataPath = new DataPath();
570 dataPath.setSrcPort(srcPort);
571 dataPath.setDstPort(dstPort);
572 flowPath.setDataPath(dataPath);
pingping-linba5c52f2014-02-11 16:52:01 -0800573
Ray Milkey269ffb92014-04-03 14:43:30 -0700574 // Create flow path matching condition(s): IPv4 Prefix
575 FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700576 flowEntryMatch.enableEthernetFrameType(Ethernet.TYPE_IPV4);
Ray Milkey269ffb92014-04-03 14:43:30 -0700577 IPv4Net dstIPv4Net = new IPv4Net(prefix.toString());
578 flowEntryMatch.enableDstIPv4Net(dstIPv4Net);
579 flowPath.setFlowEntryMatch(flowEntryMatch);
Jonathan Hart1912afc2013-10-11 12:02:44 +1300580
Ray Milkey269ffb92014-04-03 14:43:30 -0700581 /*
582 * Create the Flow Entry Action(s): dst-MAC rewrite action
583 */
584 FlowEntryActions flowEntryActions = new FlowEntryActions();
585 FlowEntryAction flowEntryAction1 = new FlowEntryAction();
586 flowEntryAction1.setActionSetEthernetDstAddr(nextHopMacAddress);
587 // flowEntryAction1.actionSetEthernetDstAddr(nextHopMacAddress);
588 flowEntryActions.addAction(flowEntryAction1);
589 flowPath.setFlowEntryActions(flowEntryActions);
pingping-linba5c52f2014-02-11 16:52:01 -0800590
Ray Milkey269ffb92014-04-03 14:43:30 -0700591 // Flow Path installation, only to first hop switches
592 // TODO: Add the flow by using the new Path Intent framework
593 /*
594 if (flowManagerService.addFlow(flowPath) == null) {
595 log.error("Failed to install flow path to the first hop for " +
596 "prefix: {}, nextHopMacAddress: {}", prefix.getAddress(),
597 nextHopMacAddress);
598 }
599 else {
600 log.debug("Successfully installed flow path to the first hop " +
601 "for prefix: {}, nextHopMacAddress: {}", prefix.getAddress(),
602 nextHopMacAddress);
pingping-linba5c52f2014-02-11 16:52:01 -0800603
Ray Milkey269ffb92014-04-03 14:43:30 -0700604 pushedFlowIds.put(prefix, flowPath.flowId());
605 }
606 */
607 }
608 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700609
Jonathan Hart938a0152014-04-07 18:27:31 -0700610 public void processRibDelete(RibUpdate update) {
611 synchronized (this) {
612 Prefix prefix = update.getPrefix();
Ray Milkey5d406012014-04-08 14:44:41 -0700613
Jonathan Hart938a0152014-04-07 18:27:31 -0700614 if (ptree.remove(prefix, update.getRibEntry())) {
615 /*
Jonathan Hart5e54f2e2014-04-17 13:43:40 -0700616 * Only delete flows if an entry was actually removed from the tree.
Jonathan Hart938a0152014-04-07 18:27:31 -0700617 * If no entry was removed, the <prefix, nexthop> wasn't there so
618 * it's probably already been removed and we don't need to do anything
619 */
Ray Milkey7531a342014-04-11 15:08:12 -0700620 executeDeletePrefix(prefix, update.getRibEntry());
Jonathan Hart938a0152014-04-07 18:27:31 -0700621 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700622 }
623 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700624
Ray Milkey7531a342014-04-11 15:08:12 -0700625 private void executeDeletePrefix(Prefix prefix, RibEntry ribEntry) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700626 deletePrefixFlows(prefix);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700627
Ray Milkey269ffb92014-04-03 14:43:30 -0700628 log.debug("Deleting {} to {}", prefix, ribEntry.getNextHop());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700629
Ray Milkey269ffb92014-04-03 14:43:30 -0700630 if (!bgpPeers.containsKey(ribEntry.getNextHop())) {
631 log.debug("Getting path for route with non-peer nexthop");
632 Path path = prefixToPath.remove(prefix);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700633
Ray Milkey269ffb92014-04-03 14:43:30 -0700634 if (path != null) {
635 //path could be null if we added to the Ptree but didn't push
636 //flows yet because we were waiting to resolve ARP
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700637
Ray Milkey269ffb92014-04-03 14:43:30 -0700638 path.decrementUsers();
639 if (path.getUsers() <= 0 && !path.isPermanent()) {
640 deletePath(path);
641 pushedPaths.remove(path.getDstIpAddress());
642 }
643 }
644 }
645 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700646
Ray Milkey269ffb92014-04-03 14:43:30 -0700647 // TODO have not tested this module
648 private void deletePrefixFlows(Prefix prefix) {
649 log.debug("Deleting flows for prefix {}", prefix);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700650
Pavlin Radoslavov3255ae52014-04-09 13:01:54 -0700651 //
652 // TODO: Delete the flow by using the new Path Intent framework
653 // NOTE: During the refactoring of the code below, if obtaining
654 // the values of the removed flowIds is needed, the first
655 // removeAll() statement should be replaced with the second removeAll()
656 // statement.
657 //
658 pushedFlowIds.removeAll(prefix);
659 /*
Ray Milkey269ffb92014-04-03 14:43:30 -0700660 Collection<FlowId> flowIds = pushedFlowIds.removeAll(prefix);
661 for (FlowId flowId : flowIds) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700662 if (log.isTraceEnabled()) {
663 //Trace the flow status by flowPath in the switch before deleting it
664 log.trace("Pushing a DELETE flow mod to flowPath : {}",
665 flowManagerService.getFlow(flowId).toString());
666 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700667
Ray Milkey269ffb92014-04-03 14:43:30 -0700668 if( flowManagerService.deleteFlow(flowId))
669 {
670 log.debug("Successfully deleted FlowId: {}",flowId);
671 }
672 else
673 {
674 log.debug("Failed to delete FlowId: {}",flowId);
675 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700676 }
Pavlin Radoslavov3255ae52014-04-09 13:01:54 -0700677 */
Ray Milkey269ffb92014-04-03 14:43:30 -0700678 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700679
Ray Milkey269ffb92014-04-03 14:43:30 -0700680 // TODO need to record the path and then delete here
681 private void deletePath(Path path) {
682 log.debug("Deleting flows for path to {}",
683 path.getDstIpAddress().getHostAddress());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700684
Ray Milkey269ffb92014-04-03 14:43:30 -0700685 // TODO need update
686 /*for (PushedFlowMod pfm : path.getFlowMods()) {
687 if (log.isTraceEnabled()) {
688 log.trace("Pushing a DELETE flow mod to {}, dst MAC {}",
689 new Object[] {HexString.toHexString(pfm.getDpid()),
690 HexString.toHexString(pfm.getFlowMod().getMatch().getDataLayerDestination())
691 });
692 }
pingping-linba5c52f2014-02-11 16:52:01 -0800693
Ray Milkey269ffb92014-04-03 14:43:30 -0700694 sendDeleteFlowMod(pfm.getFlowMod(), pfm.getDpid());
695 }*/
696 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700697
698
Ray Milkey269ffb92014-04-03 14:43:30 -0700699 //TODO test next-hop changes
700 //TODO check delete/add synchronization
pingping-linba5c52f2014-02-11 16:52:01 -0800701
Ray Milkey269ffb92014-04-03 14:43:30 -0700702 /**
703 * On startup, we need to calculate a full mesh of paths between all gateway
Ray Milkeyb41100a2014-04-10 10:42:15 -0700704 * switches.
Ray Milkey269ffb92014-04-03 14:43:30 -0700705 */
706 private void setupFullMesh() {
Pavlin Radoslavov9fc535a2014-04-11 13:00:12 -0700707 // TODO: Fix the code below. Note that "deviceStorage" was removed.
708
709 /*
710
Ray Milkey269ffb92014-04-03 14:43:30 -0700711 //For each border router, calculate and install a path from every other
712 //border switch to said border router. However, don't install the entry
713 //in to the first hop switch, as we need to install an entry to rewrite
714 //for each prefix received. This will be done later when prefixes have
715 //actually been received.
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700716
Ray Milkey269ffb92014-04-03 14:43:30 -0700717 for (BgpPeer peer : bgpPeers.values()) {
718 Interface peerInterface = interfaces.get(peer.getInterfaceName());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700719
Ray Milkey269ffb92014-04-03 14:43:30 -0700720 //We know there's not already a Path here pushed, because this is
721 //called before all other routing
722 Path path = new Path(peerInterface, peer.getIpAddress());
723 path.setPermanent();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700724
Ray Milkey269ffb92014-04-03 14:43:30 -0700725 //See if we know the MAC address of the peer. If not we can't
726 //do anything until we learn it
Ray Milkey269ffb92014-04-03 14:43:30 -0700727 MACAddress macAddress = null;
Ray Milkey269ffb92014-04-03 14:43:30 -0700728 IDeviceObject nextHopDevice =
729 deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(peer.getIpAddress()));
pingping-linba5c52f2014-02-11 16:52:01 -0800730
Ray Milkey269ffb92014-04-03 14:43:30 -0700731 if(nextHopDevice == null){
732 log.debug("There is no DeviceObject for {}", peer.getIpAddress().getHostAddress());
733 //Put in the pending paths list first
734 pathsWaitingOnArp.put(peer.getIpAddress(), path);
735 proxyArp.sendArpRequest(peer.getIpAddress(), this, true);
736 continue;
737 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700738
Ray Milkey269ffb92014-04-03 14:43:30 -0700739 macAddress = MACAddress.valueOf(nextHopDevice.getMACAddress());
pingping-linba5c52f2014-02-11 16:52:01 -0800740
Ray Milkey269ffb92014-04-03 14:43:30 -0700741 if (macAddress == null) {
742 log.debug("Don't know MAC for {}", peer.getIpAddress().getHostAddress());
743 //Put in the pending paths list first
744 pathsWaitingOnArp.put(peer.getIpAddress(), path);
745 proxyArp.sendArpRequest(peer.getIpAddress(), this, true);
746 continue;
747 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700748
Ray Milkey269ffb92014-04-03 14:43:30 -0700749 //If we know the MAC, lets go ahead and push the paths to this peer
750 calculateAndPushPath(path, macAddress);
751 }
Pavlin Radoslavov9fc535a2014-04-11 13:00:12 -0700752 */
Ray Milkey269ffb92014-04-03 14:43:30 -0700753 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700754
Ray Milkey269ffb92014-04-03 14:43:30 -0700755 private void calculateAndPushPath(Path path, MACAddress dstMacAddress) {
756 Interface dstInterface = path.getDstInterface();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -0700757
Ray Milkey269ffb92014-04-03 14:43:30 -0700758 log.debug("Setting up path to {}, {}", path.getDstIpAddress().getHostAddress(),
759 dstMacAddress);
pingping-linba5c52f2014-02-11 16:52:01 -0800760
Ray Milkey269ffb92014-04-03 14:43:30 -0700761 FlowPath flowPath = new FlowPath();
pingping-linba5c52f2014-02-11 16:52:01 -0800762
Ray Milkey269ffb92014-04-03 14:43:30 -0700763 flowPath.setInstallerId(new CallerId("SDNIP"));
pingping-linba5c52f2014-02-11 16:52:01 -0800764
Ray Milkey269ffb92014-04-03 14:43:30 -0700765 // Set flowPath FlowPathType and FlowPathUserState
766 flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
767 flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
pingping-linba5c52f2014-02-11 16:52:01 -0800768
Ray Milkey269ffb92014-04-03 14:43:30 -0700769 // Insert the dest-mac based forwarding flow entry to the non-first-hop switches
770 FlowPathFlags flowPathFlags = new FlowPathFlags();
771 flowPathFlags.setFlags(FlowPathFlags.DISCARD_FIRST_HOP_ENTRY);
772 flowPath.setFlowPathFlags(flowPathFlags);
773
774 // Create the DataPath object: dstSwitchPort
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700775 SwitchPort dstPort =
776 new SwitchPort(new Dpid(dstInterface.getDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700777 new PortNumber(dstInterface.getPort()));
pingping-linba5c52f2014-02-11 16:52:01 -0800778
Ray Milkey269ffb92014-04-03 14:43:30 -0700779 for (Interface srcInterface : interfaces.values()) {
pingping-linba5c52f2014-02-11 16:52:01 -0800780
Ray Milkey269ffb92014-04-03 14:43:30 -0700781 if (dstInterface.equals(srcInterface)) {
782 continue;
783 }
pingping-linba5c52f2014-02-11 16:52:01 -0800784
Ray Milkey269ffb92014-04-03 14:43:30 -0700785 // Create flowPath FlowId
786 flowPath.setFlowId(new FlowId());
pingping-linba5c52f2014-02-11 16:52:01 -0800787
Ray Milkey269ffb92014-04-03 14:43:30 -0700788 // Create the DataPath object: srcSwitchPort
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700789 SwitchPort srcPort =
790 new SwitchPort(new Dpid(srcInterface.getDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700791 new PortNumber(srcInterface.getPort()));
pingping-linba5c52f2014-02-11 16:52:01 -0800792
Ray Milkey269ffb92014-04-03 14:43:30 -0700793 DataPath dataPath = new DataPath();
794 dataPath.setSrcPort(srcPort);
795 dataPath.setDstPort(dstPort);
796 flowPath.setDataPath(dataPath);
pingping-linba5c52f2014-02-11 16:52:01 -0800797
Ray Milkey269ffb92014-04-03 14:43:30 -0700798 // Create the Flow Path Match condition(s)
799 FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700800 flowEntryMatch.enableEthernetFrameType(Ethernet.TYPE_IPV4);
Ray Milkey269ffb92014-04-03 14:43:30 -0700801 flowEntryMatch.enableDstMac(dstMacAddress);
802 flowPath.setFlowEntryMatch(flowEntryMatch);
pingping-linba5c52f2014-02-11 16:52:01 -0800803
Ray Milkey269ffb92014-04-03 14:43:30 -0700804 // NOTE: No need to add ACTION_OUTPUT. It is implied when creating
805 // Shortest Path Flow, and is always the last action for the Flow Entries
806 log.debug("FlowPath of MAC based forwarding: {}", flowPath.toString());
807 // TODO: Add the flow by using the new Path Intent framework
808 /*
809 if (flowManagerService.addFlow(flowPath) == null) {
810 log.error("Failed to set up MAC based forwarding path to {}, {}",
811 path.getDstIpAddress().getHostAddress(),dstMacAddress);
812 }
813 else {
814 log.debug("Successfully set up MAC based forwarding path to {}, {}",
815 path.getDstIpAddress().getHostAddress(),dstMacAddress);
816 }
817 */
818 }
819 }
pingping-linba5c52f2014-02-11 16:52:01 -0800820
Komal Shah399a2922014-05-28 01:57:40 -0700821 @Override
822 public void beginRoutingNew() {
823 setupBgpPathsNew();
824
825 //setupFullMesh();
826
827 //Suppress link discovery on external-facing router ports
828
829 for (Interface intf : interfaces.values()) {
830 linkDiscoveryService.addToSuppressLLDPs(intf.getDpid(), intf.getPort());
831 }
832
833 bgpUpdatesExecutor.execute(new Runnable() {
834 @Override
835 public void run() {
836 doUpdatesThread();
837 }
838 });
839 }
840
Ray Milkey269ffb92014-04-03 14:43:30 -0700841 /**
Komal Shah399a2922014-05-28 01:57:40 -0700842 * Setup the Paths to the BGP Daemon.
843 *
844 * Run a loop for all of the bgpPeers
845 * Push flow from BGPd to the peer
846 * Push flow from peer to BGPd
847 * Parameters to pass to the intent are as follows:
848 * String id,
849 * long srcSwitch, long srcPort, long srcMac, int srcIP,
850 * long dstSwitch, long dstPort, long dstMac, int dstIP
851 */
852 private void setupBgpPathsNew() {
853 IntentOperationList operations = new IntentOperationList();
854 for (BgpPeer bgpPeer : bgpPeers.values()) {
855 Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
856 //Inet4Address.
857 int srcIP = InetAddresses.coerceToInteger(peerInterface.getIpAddress());
858 int dstIP = InetAddresses.coerceToInteger(bgpPeer.getIpAddress());
859 String fwdIntentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
860 String bwdIntentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
861 SwitchPort srcPort =
862 new SwitchPort(bgpdAttachmentPoint.dpid(),
863 bgpdAttachmentPoint.port());
864 SwitchPort dstPort =
865 new SwitchPort(new Dpid(peerInterface.getDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700866 new PortNumber(peerInterface.getSwitchPort().port()));
Komal Shah399a2922014-05-28 01:57:40 -0700867 ShortestPathIntent fwdIntent = new ShortestPathIntent(fwdIntentId,
868 srcPort.dpid().value(), srcPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, srcIP,
869 dstPort.dpid().value(), dstPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, dstIP);
870 ShortestPathIntent bwdIntent = new ShortestPathIntent(bwdIntentId,
871 srcPort.dpid().value(), srcPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, dstIP,
872 dstPort.dpid().value(), dstPort.port().value(), ShortestPathIntent.EMPTYMACADDRESS, srcIP);
873 IntentOperation.Operator operator = IntentOperation.Operator.ADD;
874 operations.add(operator, fwdIntent);
875 operations.add(operator, bwdIntent);
876 }
877 pathRuntime.executeIntentOperations(operations);
878 }
879
880 /*
Jonathan Hart938a0152014-04-07 18:27:31 -0700881 * Proactively install all BGP traffic paths from BGP host attachment point
Ray Milkeyb41100a2014-04-10 10:42:15 -0700882 * in SDN network to all the virtual gateways to BGP peers in other networks.
Ray Milkey269ffb92014-04-03 14:43:30 -0700883 */
884 private void setupBgpPaths() {
Jonathan Hart832a7cb2013-06-24 11:25:35 +1200885
Ray Milkey269ffb92014-04-03 14:43:30 -0700886 for (BgpPeer bgpPeer : bgpPeers.values()) {
pingping-linba5c52f2014-02-11 16:52:01 -0800887
Ray Milkey269ffb92014-04-03 14:43:30 -0700888 FlowPath flowPath = new FlowPath();
889 flowPath.setInstallerId(new CallerId("SDNIP"));
pingping-linba5c52f2014-02-11 16:52:01 -0800890
Ray Milkey269ffb92014-04-03 14:43:30 -0700891 // Set flowPath FlowPathType and FlowPathUserState
892 flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
893 flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
pingping-linba5c52f2014-02-11 16:52:01 -0800894
Ray Milkey269ffb92014-04-03 14:43:30 -0700895 // Install flow paths between BGPd and its peers
896 // There is no need to set the FlowPathFlags
897 flowPath.setFlowPathFlags(new FlowPathFlags(0));
pingping-linba5c52f2014-02-11 16:52:01 -0800898
Ray Milkey269ffb92014-04-03 14:43:30 -0700899 Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
Ray Milkey269ffb92014-04-03 14:43:30 -0700900 // Create the Flow Path Match condition(s)
901 FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700902 flowEntryMatch.enableEthernetFrameType(Ethernet.TYPE_IPV4);
pingping-linba5c52f2014-02-11 16:52:01 -0800903
Ray Milkey269ffb92014-04-03 14:43:30 -0700904 // Match both source address and dest address
905 IPv4Net dstIPv4Net = new IPv4Net(bgpPeer.getIpAddress().getHostAddress() + "/32");
Komal Shah399a2922014-05-28 01:57:40 -0700906
Ray Milkey269ffb92014-04-03 14:43:30 -0700907 flowEntryMatch.enableDstIPv4Net(dstIPv4Net);
pingping-linba5c52f2014-02-11 16:52:01 -0800908
Ray Milkey269ffb92014-04-03 14:43:30 -0700909 IPv4Net srcIPv4Net = new IPv4Net(peerInterface.getIpAddress().getHostAddress() + "/32");
910 flowEntryMatch.enableSrcIPv4Net(srcIPv4Net);
pingping-linba5c52f2014-02-11 16:52:01 -0800911
Ray Milkey269ffb92014-04-03 14:43:30 -0700912 // Match TCP protocol
913 flowEntryMatch.enableIpProto(IPv4.PROTOCOL_TCP);
pingping-linba5c52f2014-02-11 16:52:01 -0800914
Ray Milkey269ffb92014-04-03 14:43:30 -0700915 // Match destination TCP port
916 flowEntryMatch.enableDstTcpUdpPort(BGP_PORT);
917 flowPath.setFlowEntryMatch(flowEntryMatch);
pingping-linba5c52f2014-02-11 16:52:01 -0800918
Ray Milkey269ffb92014-04-03 14:43:30 -0700919 /**
920 * Create the DataPath: BGP -> BGP peer
921 */
922 // Flow path for src-TCP-port
923 DataPath dataPath = new DataPath();
pingping-linba5c52f2014-02-11 16:52:01 -0800924
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700925 SwitchPort srcPort =
926 new SwitchPort(bgpdAttachmentPoint.dpid(),
927 bgpdAttachmentPoint.port());
Ray Milkey269ffb92014-04-03 14:43:30 -0700928 dataPath.setSrcPort(srcPort);
pingping-linba5c52f2014-02-11 16:52:01 -0800929
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700930 SwitchPort dstPort =
931 new SwitchPort(new Dpid(peerInterface.getDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700932 new PortNumber(peerInterface.getSwitchPort().port()));
Ray Milkey269ffb92014-04-03 14:43:30 -0700933 dataPath.setDstPort(dstPort);
pingping-linba5c52f2014-02-11 16:52:01 -0800934
Ray Milkey269ffb92014-04-03 14:43:30 -0700935 flowPath.setDataPath(dataPath);
pingping-linba5c52f2014-02-11 16:52:01 -0800936
Ray Milkey269ffb92014-04-03 14:43:30 -0700937 // TODO: Add the flow by using the new Path Intent framework
938 /*
939 if (flowManagerService.addFlow(flowPath) == null) {
940 log.error("Failed to set up path BGP -> peer {}"+"; dst-TCP-port:179",
941 bgpPeer.getIpAddress().getHostAddress());
942 }
943 else {
944 log.debug("Successfully set up path BGP -> peer {}"+"; dst-TCP-port:179",
945 bgpPeer.getIpAddress().getHostAddress());
946 }
947 */
pingping-linba5c52f2014-02-11 16:52:01 -0800948
Ray Milkey269ffb92014-04-03 14:43:30 -0700949 // Disable dst-TCP-port, and set src-TCP-port
950 flowEntryMatch.disableDstTcpUdpPort();
951 flowEntryMatch.enableSrcTcpUdpPort(BGP_PORT);
952 flowPath.setFlowEntryMatch(flowEntryMatch);
pingping-linba5c52f2014-02-11 16:52:01 -0800953
Ray Milkey269ffb92014-04-03 14:43:30 -0700954 // Create a new FlowId
955 flowPath.setFlowId(new FlowId());
pingping-linba5c52f2014-02-11 16:52:01 -0800956
Ray Milkey269ffb92014-04-03 14:43:30 -0700957 // TODO: Add the flow by using the new Path Intent framework
958 /*
959 if (flowManagerService.addFlow(flowPath) == null) {
960 log.error("Failed to set up path BGP -> Peer {}" + "; src-TCP-port:179",
961 bgpPeer.getIpAddress().getHostAddress());
962 }
963 else {
964 log.debug("Successfully set up path BGP -> Peer {}" + "; src-TCP-port:179",
965 bgpPeer.getIpAddress().getHostAddress());
966 }
967 */
pingping-linba5c52f2014-02-11 16:52:01 -0800968
Ray Milkey269ffb92014-04-03 14:43:30 -0700969 /**
970 * Create the DataPath: BGP <-BGP peer
971 */
972 // Reversed BGP flow path for src-TCP-port
973 flowPath.setFlowId(new FlowId());
pingping-linba5c52f2014-02-11 16:52:01 -0800974
Ray Milkey2476cac2014-04-08 11:03:21 -0700975 DataPath reverseDataPath = new DataPath();
pingping-linba5c52f2014-02-11 16:52:01 -0800976
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700977 SwitchPort reverseDstPort =
Komal Shah399a2922014-05-28 01:57:40 -0700978 new SwitchPort(bgpdAttachmentPoint.dpid(),
979 bgpdAttachmentPoint.port());
Ray Milkey2476cac2014-04-08 11:03:21 -0700980 reverseDataPath.setDstPort(reverseDstPort);
pingping-linba5c52f2014-02-11 16:52:01 -0800981
Pavlin Radoslavov29a2a882014-04-08 17:40:54 -0700982 SwitchPort reverseSrcPort =
Komal Shah399a2922014-05-28 01:57:40 -0700983 new SwitchPort(new Dpid(peerInterface.getDpid()),
Yuta HIGUCHIfb564502014-06-16 21:29:00 -0700984 new PortNumber(peerInterface.getSwitchPort().port()));
Ray Milkey2476cac2014-04-08 11:03:21 -0700985 reverseDataPath.setSrcPort(reverseSrcPort);
986 flowPath.setDataPath(reverseDataPath);
pingping-linba5c52f2014-02-11 16:52:01 -0800987
Jonathan Hart938a0152014-04-07 18:27:31 -0700988 // Reverse the dst IP and src IP addresses
Ray Milkey269ffb92014-04-03 14:43:30 -0700989 flowEntryMatch.enableDstIPv4Net(srcIPv4Net);
990 flowEntryMatch.enableSrcIPv4Net(dstIPv4Net);
991 flowPath.setFlowEntryMatch(flowEntryMatch);
pingping-linba5c52f2014-02-11 16:52:01 -0800992
Ray Milkey269ffb92014-04-03 14:43:30 -0700993 log.debug("Reversed BGP FlowPath: {}", flowPath.toString());
pingping-linba5c52f2014-02-11 16:52:01 -0800994
Ray Milkey269ffb92014-04-03 14:43:30 -0700995 // TODO: Add the flow by using the new Path Intent framework
996 /*
997 if (flowManagerService.addFlow(flowPath) == null) {
pingping-linba5c52f2014-02-11 16:52:01 -0800998
Ray Milkey269ffb92014-04-03 14:43:30 -0700999 log.error("Failed to set up path BGP <- Peer {}" + "; src-TCP-port:179",
1000 bgpPeer.getIpAddress().getHostAddress());
1001 }
1002 else {
1003 log.debug("Successfully set up path BGP <- Peer {}" + "; src-TCP-port:179",
1004 bgpPeer.getIpAddress().getHostAddress());
1005 }
1006 */
pingping-linba5c52f2014-02-11 16:52:01 -08001007
Ray Milkey269ffb92014-04-03 14:43:30 -07001008 // Reversed BGP flow path for dst-TCP-port
1009 flowPath.setFlowId(new FlowId());
pingping-linba5c52f2014-02-11 16:52:01 -08001010
Ray Milkey269ffb92014-04-03 14:43:30 -07001011 // Disable src-TCP-port, and set the dst-TCP-port
1012 flowEntryMatch.disableSrcTcpUdpPort();
1013 flowEntryMatch.enableDstTcpUdpPort(BGP_PORT);
1014 flowPath.setFlowEntryMatch(flowEntryMatch);
pingping-linba5c52f2014-02-11 16:52:01 -08001015
Ray Milkey269ffb92014-04-03 14:43:30 -07001016 log.debug("Reversed BGP FlowPath: {}", flowPath.toString());
pingping-linba5c52f2014-02-11 16:52:01 -08001017
Ray Milkey269ffb92014-04-03 14:43:30 -07001018 // TODO: Add the flow by using the new Path Intent framework
1019 /*
1020 if (flowManagerService.addFlow(flowPath) == null) {
1021 log.error("Failed to setting up path BGP <- Peer {}" + "; dst-TCP-port:179",
1022 bgpPeer.getIpAddress().getHostAddress());
1023 }
1024 else {
1025 log.debug("Successfully setting up path BGP <- Peer {}" + "; dst-TCP-port:179",
1026 bgpPeer.getIpAddress().getHostAddress());
1027 }
1028 */
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001029
Ray Milkey269ffb92014-04-03 14:43:30 -07001030 /**
1031 * ICMP paths between BGPd and its peers
1032 */
Jonathan Hart938a0152014-04-07 18:27:31 -07001033 // match ICMP protocol BGP <- Peer
Ray Milkey269ffb92014-04-03 14:43:30 -07001034 flowPath.setFlowId(new FlowId());
pingping-linba5c52f2014-02-11 16:52:01 -08001035
Ray Milkey269ffb92014-04-03 14:43:30 -07001036 flowEntryMatch.enableIpProto(IPv4.PROTOCOL_ICMP);
1037 flowEntryMatch.disableSrcTcpUdpPort();
1038 flowEntryMatch.disableDstTcpUdpPort();
pingping-linba5c52f2014-02-11 16:52:01 -08001039
Ray Milkey269ffb92014-04-03 14:43:30 -07001040 flowPath.setFlowEntryMatch(flowEntryMatch);
pingping-linba5c52f2014-02-11 16:52:01 -08001041
Ray Milkey2476cac2014-04-08 11:03:21 -07001042 flowPath.setDataPath(reverseDataPath);
pingping-linba5c52f2014-02-11 16:52:01 -08001043
Ray Milkey269ffb92014-04-03 14:43:30 -07001044 log.debug("Reversed ICMP FlowPath: {}", flowPath.toString());
pingping-linba5c52f2014-02-11 16:52:01 -08001045
Ray Milkey269ffb92014-04-03 14:43:30 -07001046 // TODO: Add the flow by using the new Path Intent framework
1047 /*
1048 if (flowManagerService.addFlow(flowPath) == null) {
pingping-linba5c52f2014-02-11 16:52:01 -08001049
Ray Milkey269ffb92014-04-03 14:43:30 -07001050 log.error("Failed to set up ICMP path BGP <- Peer {}",
1051 bgpPeer.getIpAddress().getHostAddress());
1052 }
1053 else {
1054 log.debug("Successfully set up ICMP path BGP <- Peer {}",
1055 bgpPeer.getIpAddress().getHostAddress());
1056 }
1057 */
pingping-linba5c52f2014-02-11 16:52:01 -08001058
Jonathan Hart938a0152014-04-07 18:27:31 -07001059 // match ICMP protocol BGP -> Peer
Ray Milkey269ffb92014-04-03 14:43:30 -07001060 flowPath.setFlowId(new FlowId());
pingping-linba5c52f2014-02-11 16:52:01 -08001061
Ray Milkey269ffb92014-04-03 14:43:30 -07001062 flowEntryMatch.enableDstIPv4Net(dstIPv4Net);
1063 flowEntryMatch.enableSrcIPv4Net(srcIPv4Net);
1064 flowPath.setFlowEntryMatch(flowEntryMatch);
pingping-linba5c52f2014-02-11 16:52:01 -08001065
Ray Milkey269ffb92014-04-03 14:43:30 -07001066 flowPath.setDataPath(dataPath);
pingping-linba5c52f2014-02-11 16:52:01 -08001067
Ray Milkey269ffb92014-04-03 14:43:30 -07001068 log.debug("ICMP flowPath: {}", flowPath.toString());
pingping-linba5c52f2014-02-11 16:52:01 -08001069
Ray Milkey269ffb92014-04-03 14:43:30 -07001070 // TODO: Add the flow by using the new Path Intent framework
1071 /*
1072 if (flowManagerService.addFlow(flowPath) == null) {
pingping-linba5c52f2014-02-11 16:52:01 -08001073
Ray Milkey269ffb92014-04-03 14:43:30 -07001074 log.error("Failed to set up ICMP path BGP -> Peer {}",
1075 bgpPeer.getIpAddress().getHostAddress());
1076 }
1077 else {
1078 log.debug("Successfully set up ICMP path BGP -> Peer {}",
1079 bgpPeer.getIpAddress().getHostAddress());
1080 }
1081 */
1082 }
1083 }
pingping-linba5c52f2014-02-11 16:52:01 -08001084
Ray Milkey269ffb92014-04-03 14:43:30 -07001085 @Override
1086 public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
1087 log.debug("Received ARP response: {} => {}",
1088 ipAddress.getHostAddress(), macAddress);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001089
Ray Milkey269ffb92014-04-03 14:43:30 -07001090 /*
1091 * We synchronize on this to prevent changes to the ptree while we're pushing
1092 * flows to the switches. If the ptree changes, the ptree and switches
1093 * could get out of sync.
1094 */
1095 synchronized (this) {
1096 Path path = pathsWaitingOnArp.remove(ipAddress);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001097
Ray Milkey269ffb92014-04-03 14:43:30 -07001098 if (path != null) {
1099 log.debug("Pushing path to {} at {} on {}", new Object[]{
1100 path.getDstIpAddress().getHostAddress(), macAddress,
1101 path.getDstInterface().getSwitchPort()});
Jonathan Hart938a0152014-04-07 18:27:31 -07001102 // These paths should always be to BGP peers. Paths to non-peers are
1103 // handled once the first prefix is ready to push
Ray Milkey269ffb92014-04-03 14:43:30 -07001104 if (pushedPaths.containsKey(path.getDstIpAddress())) {
Jonathan Hart938a0152014-04-07 18:27:31 -07001105 // A path already got pushed to this endpoint while we were waiting
1106 // for ARP. We'll copy over the permanent attribute if it is set on this path.
Ray Milkey269ffb92014-04-03 14:43:30 -07001107 if (path.isPermanent()) {
1108 pushedPaths.get(path.getDstIpAddress()).setPermanent();
1109 }
1110 } else {
1111 calculateAndPushPath(path, macAddress);
1112 pushedPaths.put(path.getDstIpAddress(), path);
1113 }
1114 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001115
Ray Milkey269ffb92014-04-03 14:43:30 -07001116 Set<RibUpdate> prefixesToPush = prefixesWaitingOnArp.removeAll(ipAddress);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001117
Ray Milkey269ffb92014-04-03 14:43:30 -07001118 for (RibUpdate update : prefixesToPush) {
Jonathan Hart938a0152014-04-07 18:27:31 -07001119 // These will always be adds
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001120
Ray Milkey269ffb92014-04-03 14:43:30 -07001121 RibEntry rib = ptree.lookup(update.getPrefix());
1122 if (rib != null && rib.equals(update.getRibEntry())) {
1123 log.debug("Pushing prefix {} next hop {}", update.getPrefix(),
1124 rib.getNextHop().getHostAddress());
Jonathan Hart938a0152014-04-07 18:27:31 -07001125 // We only push prefix flows if the prefix is still in the ptree
1126 // and the next hop is the same as our update. The prefix could
1127 // have been removed while we were waiting for the ARP, or the
1128 // next hop could have changed.
Ray Milkey7531a342014-04-11 15:08:12 -07001129 executeRibAdd(update);
Ray Milkey269ffb92014-04-03 14:43:30 -07001130 } else {
1131 log.debug("Received ARP response, but {},{} is no longer in ptree",
1132 update.getPrefix(), update.getRibEntry());
1133 }
1134 }
1135 }
1136 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001137
Jonathan Hart938a0152014-04-07 18:27:31 -07001138 // TODO wait the priority module of the flow Manager
Ray Milkey269ffb92014-04-03 14:43:30 -07001139 private void setupArpFlows() {
1140 OFMatch match = new OFMatch();
1141 match.setDataLayerType(Ethernet.TYPE_ARP);
1142 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001143
Ray Milkey269ffb92014-04-03 14:43:30 -07001144 OFFlowMod fm = new OFFlowMod();
1145 fm.setMatch(match);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001146
Ray Milkey269ffb92014-04-03 14:43:30 -07001147 OFActionOutput action = new OFActionOutput();
1148 action.setPort(OFPort.OFPP_CONTROLLER.getValue());
1149 action.setMaxLength((short) 0xffff);
1150 List<OFAction> actions = new ArrayList<OFAction>(1);
1151 actions.add(action);
1152 fm.setActions(actions);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001153
Ray Milkey269ffb92014-04-03 14:43:30 -07001154 fm.setIdleTimeout((short) 0)
1155 .setHardTimeout((short) 0)
1156 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
1157 .setCookie(0)
1158 .setCommand(OFFlowMod.OFPFC_ADD)
1159 .setPriority(ARP_PRIORITY)
1160 .setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001161
Ray Milkey269ffb92014-04-03 14:43:30 -07001162 for (String strdpid : switches) {
1163 flowCache.write(HexString.toLong(strdpid), fm);
1164 }
1165 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001166
Jonathan Hart938a0152014-04-07 18:27:31 -07001167 // TODO need update, waiting for the priority feature from flow Manager
Ray Milkey269ffb92014-04-03 14:43:30 -07001168 private void setupDefaultDropFlows() {
1169 OFFlowMod fm = new OFFlowMod();
1170 fm.setMatch(new OFMatch());
Jonathan Hart938a0152014-04-07 18:27:31 -07001171 fm.setActions(new ArrayList<OFAction>()); // No action means drop
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001172
Ray Milkey269ffb92014-04-03 14:43:30 -07001173 fm.setIdleTimeout((short) 0)
1174 .setHardTimeout((short) 0)
1175 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
1176 .setCookie(0)
1177 .setCommand(OFFlowMod.OFPFC_ADD)
1178 .setPriority((short) 0)
1179 .setLengthU(OFFlowMod.MINIMUM_LENGTH);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001180
Ray Milkey269ffb92014-04-03 14:43:30 -07001181 OFFlowMod fmLLDP;
1182 OFFlowMod fmBDDP;
1183 try {
1184 fmLLDP = fm.clone();
1185 fmBDDP = fm.clone();
1186 } catch (CloneNotSupportedException e1) {
1187 log.error("Error cloning flow mod", e1);
1188 return;
1189 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001190
Ray Milkey269ffb92014-04-03 14:43:30 -07001191 OFMatch matchLLDP = new OFMatch();
1192 matchLLDP.setDataLayerType((short) 0x88cc);
1193 matchLLDP.setWildcards(matchLLDP.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
1194 fmLLDP.setMatch(matchLLDP);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001195
Ray Milkey269ffb92014-04-03 14:43:30 -07001196 OFMatch matchBDDP = new OFMatch();
1197 matchBDDP.setDataLayerType((short) 0x8942);
1198 matchBDDP.setWildcards(matchBDDP.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
1199 fmBDDP.setMatch(matchBDDP);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001200
Ray Milkey269ffb92014-04-03 14:43:30 -07001201 OFActionOutput action = new OFActionOutput();
1202 action.setPort(OFPort.OFPP_CONTROLLER.getValue());
1203 action.setMaxLength((short) 0xffff);
1204 List<OFAction> actions = new ArrayList<OFAction>(1);
1205 actions.add(action);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001206
Ray Milkey269ffb92014-04-03 14:43:30 -07001207 fmLLDP.setActions(actions);
1208 fmBDDP.setActions(actions);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001209
Ray Milkey269ffb92014-04-03 14:43:30 -07001210 fmLLDP.setPriority(ARP_PRIORITY);
1211 fmLLDP.setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);
1212 fmBDDP.setPriority(ARP_PRIORITY);
1213 fmBDDP.setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001214
Ray Milkey269ffb92014-04-03 14:43:30 -07001215 List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(3);
1216 flowModList.add(fm);
1217 flowModList.add(fmLLDP);
1218 flowModList.add(fmBDDP);
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001219
Ray Milkey269ffb92014-04-03 14:43:30 -07001220 for (String strdpid : switches) {
1221 flowCache.write(HexString.toLong(strdpid), flowModList);
1222 }
1223 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001224
Ray Milkey269ffb92014-04-03 14:43:30 -07001225 private void beginRouting() {
1226 log.debug("Topology is now ready, beginning routing function");
1227 // TODO: Fix for the new Topology Network Graph
1228 // topology = topologyNetService.newDatabaseTopology();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001229
Ray Milkey269ffb92014-04-03 14:43:30 -07001230 // Wait Pavlin's API. We need the following functions.
1231 /*setupArpFlows();
1232 setupDefaultDropFlows();*/
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001233
Ray Milkey269ffb92014-04-03 14:43:30 -07001234 setupBgpPaths();
1235 setupFullMesh();
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001236
Ray Milkey269ffb92014-04-03 14:43:30 -07001237 //Suppress link discovery on external-facing router ports
1238 for (Interface intf : interfaces.values()) {
Pavlin Radoslavov7d21c0a2014-04-10 10:32:59 -07001239 linkDiscoveryService.addToSuppressLLDPs(intf.getDpid(), intf.getPort());
Ray Milkey269ffb92014-04-03 14:43:30 -07001240 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001241
Ray Milkey269ffb92014-04-03 14:43:30 -07001242 bgpUpdatesExecutor.execute(new Runnable() {
1243 @Override
1244 public void run() {
1245 doUpdatesThread();
1246 }
1247 });
1248 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001249
Jonathan Hart938a0152014-04-07 18:27:31 -07001250 // Before inserting the paths for BGP traffic, we should check whether
1251 // all the switches in the configuration file are discovered by ONOS
Ray Milkey269ffb92014-04-03 14:43:30 -07001252 private void checkSwitchesConnected() {
Jonathan Hart938a0152014-04-07 18:27:31 -07001253 // TODO: Fix the code below after topoSwitchSerice was removed
1254 /*
Ray Milkey269ffb92014-04-03 14:43:30 -07001255 for (String dpid : switches) {
Ray Milkey5d406012014-04-08 14:44:41 -07001256
Ray Milkey269ffb92014-04-03 14:43:30 -07001257 Iterator<ISwitchObject> activeSwitches = topoSwitchService.
1258 getActiveSwitches().iterator();
1259 while(activeSwitches.hasNext())
1260 {
1261 ISwitchObject switchObject = activeSwitches.next();
1262 if (switchObject.getDPID().equals(dpid)) {
1263 break;
1264 }
1265 if(activeSwitches.hasNext() == false) {
1266 log.debug("Not all switches are here yet");
1267 return;
1268 }
1269 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001270 }
1271 switchesConnected = true;
Jonathan Hart938a0152014-04-07 18:27:31 -07001272 */
Ray Milkey269ffb92014-04-03 14:43:30 -07001273 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001274
Jonathan Hart938a0152014-04-07 18:27:31 -07001275 // Actually we only need to go half way round to verify full mesh connectivity
Ray Milkey269ffb92014-04-03 14:43:30 -07001276 private void checkTopologyReady() {
1277 for (Interface dstInterface : interfaces.values()) {
1278 for (Interface srcInterface : interfaces.values()) {
1279 if (dstInterface.equals(srcInterface)) {
1280 continue;
1281 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001282
Ray Milkey269ffb92014-04-03 14:43:30 -07001283 // TODO: Fix for the new Topology Network Graph
1284 /*
1285 DataPath shortestPath = topologyNetService.getDatabaseShortestPath(
1286 srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001287
Ray Milkey269ffb92014-04-03 14:43:30 -07001288 if (shortestPath == null){
1289 log.debug("Shortest path between {} and {} not found",
1290 srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
1291 return;
1292 }
1293 */
1294 }
1295 }
1296 topologyReady = true;
1297 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001298
Ray Milkey269ffb92014-04-03 14:43:30 -07001299 private void checkStatus() {
1300 if (!switchesConnected) {
1301 checkSwitchesConnected();
1302 }
1303 boolean oldTopologyReadyStatus = topologyReady;
1304 if (switchesConnected && !topologyReady) {
1305 checkTopologyReady();
1306 }
1307 if (!oldTopologyReadyStatus && topologyReady) {
1308 beginRouting();
1309 }
1310 }
Jonathan Harta23ffdb2013-08-14 14:36:54 +12001311
Ray Milkey269ffb92014-04-03 14:43:30 -07001312 private void doUpdatesThread() {
1313 boolean interrupted = false;
1314 try {
1315 while (true) {
1316 try {
1317 RibUpdate update = ribUpdates.take();
1318 switch (update.getOperation()) {
1319 case UPDATE:
1320 if (validateUpdate(update)) {
1321 processRibAdd(update);
1322 } else {
1323 log.debug("Rib UPDATE out of order: {} via {}",
1324 update.getPrefix(), update.getRibEntry().getNextHop());
1325 }
1326 break;
1327 case DELETE:
1328 if (validateUpdate(update)) {
1329 processRibDelete(update);
1330 } else {
1331 log.debug("Rib DELETE out of order: {} via {}",
1332 update.getPrefix(), update.getRibEntry().getNextHop());
1333 }
1334 break;
Ray Milkey0b122ed2014-04-14 10:06:03 -07001335 default:
1336 log.error("Unknown operation {}", update.getOperation());
1337 break;
Ray Milkey269ffb92014-04-03 14:43:30 -07001338 }
1339 } catch (InterruptedException e) {
1340 log.debug("Interrupted while taking from updates queue", e);
1341 interrupted = true;
1342 } catch (Exception e) {
1343 log.debug("exception", e);
1344 }
1345 }
1346 } finally {
1347 if (interrupted) {
1348 Thread.currentThread().interrupt();
1349 }
1350 }
1351 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001352
Ray Milkey269ffb92014-04-03 14:43:30 -07001353 private boolean validateUpdate(RibUpdate update) {
1354 RibEntry newEntry = update.getRibEntry();
1355 RibEntry oldEntry = ptree.lookup(update.getPrefix());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001356
Ray Milkey269ffb92014-04-03 14:43:30 -07001357 //If there is no existing entry we must assume this is the most recent
1358 //update. However this might not always be the case as we might have a
1359 //POST then DELETE reordering.
1360 //if (oldEntry == null || !newEntry.getNextHop().equals(oldEntry.getNextHop())) {
1361 if (oldEntry == null) {
1362 return true;
1363 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001364
Ray Milkey269ffb92014-04-03 14:43:30 -07001365 // This handles the case where routes are gathered in the initial
1366 // request because they don't have sequence number info
1367 if (newEntry.getSysUpTime() == -1 && newEntry.getSequenceNum() == -1) {
1368 return true;
1369 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001370
Ray Milkey269ffb92014-04-03 14:43:30 -07001371 if (newEntry.getSysUpTime() > oldEntry.getSysUpTime()) {
1372 return true;
Ray Milkey269ffb92014-04-03 14:43:30 -07001373 }
Ray Milkey4985f212014-04-10 16:57:05 -07001374
1375 return newEntry.getSysUpTime() == oldEntry.getSysUpTime() &&
1376 newEntry.getSequenceNum() > oldEntry.getSequenceNum();
Ray Milkey269ffb92014-04-03 14:43:30 -07001377 }
pingping-lina2cbfad2013-03-07 08:39:21 +08001378
Ray Milkey269ffb92014-04-03 14:43:30 -07001379 // The code below should be reimplemented after removal of Floodlight's
1380 // ITopologyService API. It should be implemented on top of network graph
1381 // notifications. (It was pretty hacky anyway...)
1382 /*
1383 @Override
1384 public void topologyChanged() {
1385 if (topologyReady) {
1386 return;
1387 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001388
Ray Milkey269ffb92014-04-03 14:43:30 -07001389 boolean refreshNeeded = false;
1390 for (LDUpdate ldu : topologyService.getLastLinkUpdates()){
1391 if (!ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_UPDATED)){
1392 //We don't need to recalculate anything for just link updates
1393 //They happen very frequently
1394 refreshNeeded = true;
1395 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001396
Ray Milkey269ffb92014-04-03 14:43:30 -07001397 log.debug("Topo change {}", ldu.getOperation());
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001398
Ray Milkey269ffb92014-04-03 14:43:30 -07001399 if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_ADDED)){
1400 synchronized (linkUpdates) {
1401 linkUpdates.add(ldu);
1402 }
1403 }
1404 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001405
Ray Milkey269ffb92014-04-03 14:43:30 -07001406 if (refreshNeeded && !topologyReady){
1407 topologyChangeDetectorTask.reschedule(TOPO_DETECTION_WAIT, TimeUnit.SECONDS);
1408 }
1409 }
1410 */
Jonathan Hart64c0b202013-08-20 15:45:07 +12001411
Ray Milkey269ffb92014-04-03 14:43:30 -07001412 @Override
1413 public void addedSwitch(IOFSwitch sw) {
1414 if (!topologyReady) {
1415 sw.clearAllFlowMods();
1416 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001417
Ray Milkey269ffb92014-04-03 14:43:30 -07001418 flowCache.switchConnected(sw);
1419 }
Jonathan Hart64c0b202013-08-20 15:45:07 +12001420
Ray Milkey269ffb92014-04-03 14:43:30 -07001421 @Override
1422 public void removedSwitch(IOFSwitch sw) {
Jonathan Hart938a0152014-04-07 18:27:31 -07001423 // Not used
Ray Milkey269ffb92014-04-03 14:43:30 -07001424 }
Jonathan Hart64c0b202013-08-20 15:45:07 +12001425
Ray Milkey269ffb92014-04-03 14:43:30 -07001426 @Override
1427 public void switchPortChanged(Long switchId) {
Jonathan Hart938a0152014-04-07 18:27:31 -07001428 // Not used
Ray Milkey269ffb92014-04-03 14:43:30 -07001429 }
Jonathan Hart64c0b202013-08-20 15:45:07 +12001430
Ray Milkey269ffb92014-04-03 14:43:30 -07001431 @Override
1432 public String getName() {
Jonathan Hart8f6dc092014-04-18 15:56:43 -07001433 return "SdnIp";
Ray Milkey269ffb92014-04-03 14:43:30 -07001434 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001435
Ray Milkey269ffb92014-04-03 14:43:30 -07001436 /*
1437 * IConfigInfoService methods
1438 */
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001439
Ray Milkey269ffb92014-04-03 14:43:30 -07001440 @Override
1441 public boolean isInterfaceAddress(InetAddress address) {
Jonathan Hart5e54f2e2014-04-17 13:43:40 -07001442 Interface intf = interfacePtree.match(new Prefix(address.getAddress(), 32));
Ray Milkey269ffb92014-04-03 14:43:30 -07001443 return (intf != null && intf.getIpAddress().equals(address));
1444 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001445
Ray Milkey269ffb92014-04-03 14:43:30 -07001446 @Override
1447 public boolean inConnectedNetwork(InetAddress address) {
Jonathan Hart5e54f2e2014-04-17 13:43:40 -07001448 Interface intf = interfacePtree.match(new Prefix(address.getAddress(), 32));
Ray Milkey269ffb92014-04-03 14:43:30 -07001449 return (intf != null && !intf.getIpAddress().equals(address));
1450 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001451
Ray Milkey269ffb92014-04-03 14:43:30 -07001452 @Override
1453 public boolean fromExternalNetwork(long inDpid, short inPort) {
1454 for (Interface intf : interfaces.values()) {
1455 if (intf.getDpid() == inDpid && intf.getPort() == inPort) {
1456 return true;
1457 }
1458 }
1459 return false;
1460 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001461
Ray Milkey269ffb92014-04-03 14:43:30 -07001462 @Override
1463 public Interface getOutgoingInterface(InetAddress dstIpAddress) {
Jonathan Hart5e54f2e2014-04-17 13:43:40 -07001464 return interfacePtree.match(new Prefix(dstIpAddress.getAddress(), 32));
Ray Milkey269ffb92014-04-03 14:43:30 -07001465 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001466
Ray Milkey269ffb92014-04-03 14:43:30 -07001467 @Override
1468 public boolean hasLayer3Configuration() {
1469 return !interfaces.isEmpty();
1470 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001471
Ray Milkey269ffb92014-04-03 14:43:30 -07001472 @Override
1473 public MACAddress getRouterMacAddress() {
1474 return bgpdMacAddress;
1475 }
Yuta HIGUCHIe7eac182014-03-19 19:18:30 -07001476
Ray Milkey269ffb92014-04-03 14:43:30 -07001477 @Override
1478 public short getVlan() {
1479 return vlan;
1480 }
pingping-lina2cbfad2013-03-07 08:39:21 +08001481}