blob: 0c1f933af71bea8d27ef3953412b59c0023700be [file] [log] [blame]
Saurav Dasfb93c252014-08-18 20:40:13 -07001package net.onrc.onos.core.configmanager;
2
3import java.io.File;
4import java.io.IOException;
5import java.util.ArrayList;
6import java.util.Collection;
7import java.util.Collections;
8import java.util.HashMap;
9import java.util.HashSet;
10import java.util.List;
11import java.util.Map;
12import java.util.Set;
13import java.util.concurrent.ConcurrentHashMap;
14import java.util.concurrent.ConcurrentMap;
15
16import net.floodlightcontroller.core.module.FloodlightModuleContext;
17import net.floodlightcontroller.core.module.FloodlightModuleException;
18import net.floodlightcontroller.core.module.IFloodlightModule;
19import net.floodlightcontroller.core.module.IFloodlightService;
20import net.onrc.onos.core.configmanager.NetworkConfig.LinkConfig;
21import net.onrc.onos.core.configmanager.NetworkConfig.SwitchConfig;
22import net.onrc.onos.core.linkdiscovery.Link;
23import net.onrc.onos.core.util.Dpid;
24import net.onrc.onos.core.util.LinkTuple;
25import net.onrc.onos.core.util.SwitchPort;
26
27import org.codehaus.jackson.JsonParseException;
28import org.codehaus.jackson.map.JsonMappingException;
29import org.codehaus.jackson.map.ObjectMapper;
30import org.projectfloodlight.openflow.util.HexString;
31import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34/**
35 * NetworkConfigManager manages all network configuration for switches, links
36 * and any other state that needs to be configured for correct network
37 * operation.
38 *
39 */
40public class NetworkConfigManager implements IFloodlightModule,
41 INetworkConfigService {
42 protected static final Logger log = LoggerFactory
43 .getLogger(NetworkConfigManager.class);
44 public static final String DEFAULT_NETWORK_CONFIG_FILE =
45 "conf/example-network.conf";
46 /**
47 * JSON Config file needs to use one of the following types for defining the
48 * kind of switch or link it wishes to configure.
49 */
50 private static final String SEGMENT_ROUTER = "Router_SR";
51 private static final String ROADM = "Roadm";
52 private static final String OF10SWITCH = "Switch_OF10";
53
54 private static final String PKT_LINK = "pktLink";
55 private static final String WDM_LINK = "wdmLink";
56 private static final String PKT_OPT_LINK = "pktOptLink";
57
58 NetworkConfig networkConfig;
59 private ConcurrentMap<Long, SwitchConfig> configuredSwitches;
60 private ConcurrentMap<LinkTuple, LinkConfig> configuredLinks;
61 private Map<String, Long> nameToDpid;
62
63 // **************
64 // INetworkConfigService
65 // **************
66
67 public SwitchConfigStatus checkSwitchConfig(Dpid dpid) {
68 SwitchConfig swc = configuredSwitches.get(dpid.value());
69 if (networkConfig.getRestrictSwitches()) {
70 // default deny behavior
71 if (swc == null) {
72 // switch is not configured - we deny this switch
73 return new SwitchConfigStatus(NetworkConfigState.DENY, null,
74 "Switch not configured, in network denying switches by default.");
75 }
76 if (swc.isAllowed()) {
77 // switch is allowed in config, return configured attributes
78 return new SwitchConfigStatus(NetworkConfigState.ACCEPT_ADD, swc);
79 } else {
80 // switch has been configured off (administratively down)
81 return new SwitchConfigStatus(NetworkConfigState.DENY, null,
82 "Switch configured down (allowed=false).");
83 }
84 } else {
85 // default allow behavior
86 if (swc == null) {
87 // no config to add
88 return new SwitchConfigStatus(NetworkConfigState.ACCEPT, null);
89 }
90 if (swc.isAllowed()) {
91 // switch is allowed in config, return configured attributes
92 return new SwitchConfigStatus(NetworkConfigState.ACCEPT_ADD, swc);
93 } else {
94 // switch has been configured off (administratively down)
95 return new SwitchConfigStatus(NetworkConfigState.DENY, null,
96 "Switch configured down (allowed=false).");
97 }
98 }
99
100 }
101
102 public LinkConfigStatus checkLinkConfig(Link link) {
103 LinkConfig lkc = getConfiguredLink(link);
104 // links are always disallowed if any one of the nodes that make up the
105 // link are disallowed
106 Dpid linkNode1 = new Dpid(link.getSrc());
107 SwitchConfigStatus scs1 = checkSwitchConfig(linkNode1);
108 if (scs1.getConfigState() == NetworkConfigState.DENY) {
109 return new LinkConfigStatus(NetworkConfigState.DENY, null,
110 "Link-node: " + linkNode1 + " denied by config: " + scs1.getMsg());
111 }
112 Dpid linkNode2 = new Dpid(link.getDst());
113 SwitchConfigStatus scs2 = checkSwitchConfig(linkNode2);
114 if (scs2.getConfigState() == NetworkConfigState.DENY) {
115 return new LinkConfigStatus(NetworkConfigState.DENY, null,
116 "Link-node: " + linkNode2 + " denied by config: " + scs2.getMsg());
117 }
118 if (networkConfig.getRestrictLinks()) {
119 // default deny behavior
120 if (lkc == null) {
121 // link is not configured - we deny this link
122 return new LinkConfigStatus(NetworkConfigState.DENY, null,
123 "Link not configured, in network denying links by default.");
124 }
125 if (lkc.isAllowed()) {
126 // link is allowed in config, return configured attributes
127 return new LinkConfigStatus(NetworkConfigState.ACCEPT_ADD, lkc);
128 } else {
129 // link has been configured off (administratively down)
130 return new LinkConfigStatus(NetworkConfigState.DENY, null,
131 "Link configured down (allowed=false).");
132 }
133 } else {
134 // default allow behavior
135 if (lkc == null) {
136 // no config to add
137 return new LinkConfigStatus(NetworkConfigState.ACCEPT, null);
138 }
139 if (lkc.isAllowed()) {
140 // link is allowed in config, return configured attributes
141 return new LinkConfigStatus(NetworkConfigState.ACCEPT_ADD, lkc);
142 } else {
143 // link has been configured off (administratively down)
144 return new LinkConfigStatus(NetworkConfigState.DENY, null,
145 "Link configured down (allowed=false).");
146 }
147 }
148
149 }
150
151 @Override
152 public List<SwitchConfig> getConfiguredAllowedSwitches() {
153 List<SwitchConfig> allowed = new ArrayList<SwitchConfig>();
154 for (SwitchConfig swc : configuredSwitches.values()) {
155 if (swc.isAllowed()) {
156 allowed.add(swc);
157 }
158 }
159 return allowed;
160 }
161
162 @Override
163 public List<LinkConfig> getConfiguredAllowedLinks() {
164 List<LinkConfig> allowed = new ArrayList<LinkConfig>();
165 for (LinkConfig lkc : configuredLinks.values()) {
166 if (lkc.isAllowed()) {
167 allowed.add(lkc);
168 }
169 }
170 return allowed;
171 }
172
173 @Override
174 public List<List<String>> getOpticalReachabiltyConfig() {
175 if (networkConfig.getOpticalReachability() != null) {
176 return networkConfig.getOpticalReachability();
177 }
178 return Collections.emptyList();
179 }
180
181 @Override
182 public Dpid getDpidForName(String name) {
183 if (nameToDpid.get(name) != null) {
184 return new Dpid(nameToDpid.get(name));
185 }
186 return null;
187 }
188
189 // **************
190 // Private methods
191 // **************
192
193 private void loadNetworkConfig(FloodlightModuleContext context) {
194 ObjectMapper mapper = new ObjectMapper();
195 networkConfig = new NetworkConfig();
196
197 Map<String, String> configParams = context.getConfigParams(this);
198 String file = configParams.get("networkConfigFile");
199 if (file == null) {
200 // use default file which no-ops
201 log.info("Using default file for network configuration");
202 file = DEFAULT_NETWORK_CONFIG_FILE;
203 } else {
204 log.info("Loading network configuration from " + file);
205 }
206
207 try {
208 networkConfig = mapper.readValue(new File(file), NetworkConfig.class);
209 } catch (JsonParseException e) {
210 String err = String.format("JsonParseException while loading network "
211 + "config from file: %s: %s", file, e.getMessage());
212 throw new NetworkConfigException.ErrorConfig(err);
213 } catch (JsonMappingException e) {
214 String err = String.format(
215 "JsonMappingException while loading network config "
216 + "from file: %s: %s", file, e.getMessage());
217 throw new NetworkConfigException.ErrorConfig(err);
218 } catch (IOException e) {
219 String err = String.format("IOException while loading network config "
220 + "from file: %s %s", file, e.getMessage());
221 throw new NetworkConfigException.ErrorConfig(err);
222 }
223
224 log.info("Network config specifies: {} switches and {} links",
225 (networkConfig.getRestrictSwitches())
226 ? networkConfig.getSwitchConfig().size() : "default allow",
227 (networkConfig.getRestrictLinks())
228 ? networkConfig.getLinkConfig().size() : "default allow");
229 }
230
231 private void parseNetworkConfig() {
232 List<SwitchConfig> swConfList = networkConfig.getSwitchConfig();
233 List<LinkConfig> lkConfList = networkConfig.getLinkConfig();
234 validateSwitchConfig(swConfList);
235 createTypeSpecificSwitchConfig(swConfList);
236 validateLinkConfig(lkConfList);
237 createTypeSpecificLinkConfig(lkConfList);
238 // TODO validate reachability matrix 'names' for configured dpids
239 }
240
241 private void createTypeSpecificSwitchConfig(List<SwitchConfig> swConfList) {
242 for (SwitchConfig swc : swConfList) {
243 nameToDpid.put(swc.getName(), swc.getDpid());
244 String swtype = swc.getType();
245 switch (swtype) {
246 case SEGMENT_ROUTER:
247 SwitchConfig sr = new SegmentRouterConfig(swc);
248 configuredSwitches.put(sr.getDpid(), sr);
249 break;
250 case ROADM:
251 SwitchConfig rd = new RoadmConfig(swc);
252 configuredSwitches.put(rd.getDpid(), rd);
253 break;
254 case OF10SWITCH:
255 SwitchConfig of10 = new SwitchOF10Config(swc);
256 configuredSwitches.put(of10.getDpid(), of10);
257 break;
258 default:
259 throw new NetworkConfigException.UnknownSwitchType(swtype,
260 swc.getName());
261 }
262 }
263 }
264
265 private void createTypeSpecificLinkConfig(List<LinkConfig> lkConfList) {
266 for (LinkConfig lkc : lkConfList) {
267 String lktype = lkc.getType();
268 switch (lktype) {
269 case PKT_LINK:
270 PktLinkConfig pk = new PktLinkConfig(lkc);
271 for (LinkTuple lt : pk.getLinkTupleList()) {
272 configuredLinks.put(lt, pk);
273 }
274 break;
275 case WDM_LINK:
276 WdmLinkConfig wd = new WdmLinkConfig(lkc);
277 for (LinkTuple lt : wd.getLinkTupleList()) {
278 configuredLinks.put(lt, wd);
279 }
280 break;
281 case PKT_OPT_LINK:
282 PktOptLinkConfig po = new PktOptLinkConfig(lkc);
283 for (LinkTuple lt : po.getLinkTupleList()) {
284 configuredLinks.put(lt, po);
285 }
286 break;
287 default:
288 throw new NetworkConfigException.UnknownLinkType(lktype,
289 lkc.getNodeDpid1(), lkc.getNodeDpid2());
290 }
291 }
292 }
293
294 private void validateSwitchConfig(List<SwitchConfig> swConfList) {
295 Set<Long> swDpids = new HashSet<Long>();
296 Set<String> swNames = new HashSet<String>();
297 for (SwitchConfig swc : swConfList) {
298 if (swc.getNodeDpid() == null || swc.getDpid() == 0) {
299 throw new NetworkConfigException.DpidNotSpecified(swc.getName());
300 }
301 // ensure both String and Long values of dpid are set
302 if (swc.getDpid() != HexString.toLong(swc.getNodeDpid())) {
303 throw new NetworkConfigException.SwitchDpidNotConverted(
304 swc.getName());
305 }
306 if (swc.getName() == null) {
307 throw new NetworkConfigException.NameNotSpecified(swc.getDpid());
308 }
309 if (swc.getType() == null) {
310 throw new NetworkConfigException.SwitchTypeNotSpecified(
311 swc.getDpid());
312 }
313 if (!swDpids.add(swc.getDpid())) {
314 throw new NetworkConfigException.DuplicateDpid(swc.getDpid());
315 }
316 if (!swNames.add(swc.getName())) {
317 throw new NetworkConfigException.DuplicateName(swc.getName());
318 }
319 // TODO Add more validations
320 }
321 }
322
323 private void validateLinkConfig(List<LinkConfig> lkConfList) {
324 for (LinkConfig lkc : lkConfList) {
325 if (lkc.getNodeDpid1() == null || lkc.getNodeDpid2() == null) {
326 throw new NetworkConfigException.LinkDpidNotSpecified(
327 lkc.getNodeDpid1(), lkc.getNodeDpid2());
328 }
329 // ensure both String and Long values are set
330 if (lkc.getDpid1() != HexString.toLong(lkc.getNodeDpid1()) ||
331 lkc.getDpid2() != HexString.toLong(lkc.getNodeDpid2())) {
332 throw new NetworkConfigException.LinkDpidNotConverted(
333 lkc.getNodeDpid1(), lkc.getNodeDpid2());
334 }
335 if (lkc.getType() == null) {
336 throw new NetworkConfigException.LinkTypeNotSpecified(
337 lkc.getNodeDpid1(), lkc.getNodeDpid2());
338 }
339 if (configuredSwitches.get(lkc.getDpid1()) == null) {
340 throw new NetworkConfigException.LinkForUnknownSwitchConfig(
341 lkc.getNodeDpid1());
342 }
343 if (configuredSwitches.get(lkc.getDpid2()) == null) {
344 throw new NetworkConfigException.LinkForUnknownSwitchConfig(
345 lkc.getNodeDpid2());
346 }
347 // TODO add more validations
348 }
349
350 }
351
352 private LinkConfig getConfiguredLink(Link link) {
353 LinkConfig lkc = null;
354 // first try the unidirectional link with the ports assigned
355 lkc = configuredLinks.get(new LinkTuple(
356 new SwitchPort(link.getSrc(), link.getSrcPort()),
357 new SwitchPort(link.getDst(), link.getDstPort())));
358 if (lkc == null) {
359 // try without ports, as configuration may be for all links
360 // between the two switches
361 lkc = configuredLinks.get(new LinkTuple(
362 new SwitchPort(link.getSrc(), (short) 0),
363 new SwitchPort(link.getDst(), (short) 0)));
364 }
365 return lkc;
366 }
367
368
369 // **************
370 // IFloodlightModule
371 // **************
372
373 @Override
374 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
375 Collection<Class<? extends IFloodlightService>> l =
376 new ArrayList<Class<? extends IFloodlightService>>();
377 l.add(INetworkConfigService.class);
378 return l;
379 }
380
381 @Override
382 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
383 Map<Class<? extends IFloodlightService>, IFloodlightService> m =
384 new HashMap<>();
385 m.put(INetworkConfigService.class, this);
386 return m;
387 }
388
389 @Override
390 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
391 // TODO Auto-generated method stub
392 return null;
393 }
394
395 @Override
396 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
397 loadNetworkConfig(context);
398 configuredSwitches = new ConcurrentHashMap<Long, SwitchConfig>();
399 configuredLinks = new ConcurrentHashMap<LinkTuple, LinkConfig>();
400 nameToDpid = new HashMap<String, Long>();
401 }
402
403 @Override
404 public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
405 parseNetworkConfig();
406 }
407
408}