Open Kilda Java Documentation
PathVerificationService.java
Go to the documentation of this file.
1 /* Copyright 2017 Telstra Open Source
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package org.openkilda.floodlight.pathverification;
17 
18 import static org.openkilda.messaging.Utils.MAPPER;
19 
32 
33 import com.auth0.jwt.JWT;
34 import com.auth0.jwt.JWTVerifier;
35 import com.auth0.jwt.algorithms.Algorithm;
36 import com.auth0.jwt.exceptions.JWTVerificationException;
37 import com.auth0.jwt.interfaces.DecodedJWT;
38 import com.fasterxml.jackson.core.JsonProcessingException;
39 import com.google.common.annotations.VisibleForTesting;
40 import net.floodlightcontroller.core.FloodlightContext;
41 import net.floodlightcontroller.core.IFloodlightProviderService;
42 import net.floodlightcontroller.core.IListener;
43 import net.floodlightcontroller.core.IOFMessageListener;
44 import net.floodlightcontroller.core.IOFSwitch;
45 import net.floodlightcontroller.core.internal.IOFSwitchService;
46 import net.floodlightcontroller.core.module.FloodlightModuleContext;
47 import net.floodlightcontroller.core.module.FloodlightModuleException;
48 import net.floodlightcontroller.core.module.IFloodlightModule;
49 import net.floodlightcontroller.core.module.IFloodlightService;
50 import net.floodlightcontroller.packet.Data;
51 import net.floodlightcontroller.packet.Ethernet;
52 import net.floodlightcontroller.packet.IPv4;
53 import net.floodlightcontroller.packet.LLDPTLV;
54 import net.floodlightcontroller.packet.UDP;
55 import net.floodlightcontroller.restserver.IRestApiService;
56 import net.floodlightcontroller.util.OFMessageUtils;
57 import org.apache.commons.codec.binary.Hex;
58 import org.apache.kafka.clients.producer.KafkaProducer;
59 import org.apache.kafka.clients.producer.ProducerRecord;
60 import org.projectfloodlight.openflow.protocol.OFMessage;
61 import org.projectfloodlight.openflow.protocol.OFPacketIn;
62 import org.projectfloodlight.openflow.protocol.OFPacketOut;
63 import org.projectfloodlight.openflow.protocol.OFPortDesc;
64 import org.projectfloodlight.openflow.protocol.OFPortDescProp;
65 import org.projectfloodlight.openflow.protocol.OFPortDescPropEthernet;
66 import org.projectfloodlight.openflow.protocol.OFType;
67 import org.projectfloodlight.openflow.protocol.OFVersion;
68 import org.projectfloodlight.openflow.protocol.action.OFAction;
69 import org.projectfloodlight.openflow.protocol.match.MatchField;
70 import org.projectfloodlight.openflow.types.DatapathId;
71 import org.projectfloodlight.openflow.types.EthType;
72 import org.projectfloodlight.openflow.types.IPv4Address;
73 import org.projectfloodlight.openflow.types.IpProtocol;
74 import org.projectfloodlight.openflow.types.MacAddress;
75 import org.projectfloodlight.openflow.types.OFBufferId;
76 import org.projectfloodlight.openflow.types.OFPort;
77 import org.projectfloodlight.openflow.types.TransportPort;
78 import org.projectfloodlight.openflow.types.U64;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
81 
82 import java.io.UnsupportedEncodingException;
83 import java.net.InetSocketAddress;
84 import java.nio.ByteBuffer;
85 import java.nio.charset.Charset;
86 import java.util.ArrayList;
87 import java.util.Arrays;
88 import java.util.Collection;
89 import java.util.HashMap;
90 import java.util.List;
91 import java.util.Map;
92 
93 public class PathVerificationService implements IFloodlightModule, IOFMessageListener, IPathVerificationService {
94  private static final Logger logger = LoggerFactory.getLogger(PathVerificationService.class);
95  private static final Logger logIsl = LoggerFactory.getLogger(
96  String.format("%s.ISL", PathVerificationService.class.getName()));
97 
98  public static final String VERIFICATION_BCAST_PACKET_DST = "08:ED:02:E3:FF:FF";
99  public static final int VERIFICATION_PACKET_UDP_PORT = 61231;
100  public static final String VERIFICATION_PACKET_IP_DST = "192.168.0.255";
101 
102  private String topoDiscoTopic;
103  private IFloodlightProviderService floodlightProvider;
104  private IOFSwitchService switchService;
105  private IRestApiService restApiService;
106  private boolean isAlive = false;
107  private KafkaProducer<String, String> producer;
108  private double islBandwidthQuotient = 1.0;
109  private Algorithm algorithm;
110  private JWTVerifier verifier;
111 
115  @Override
116  public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
117  Collection<Class<? extends IFloodlightService>> services = new ArrayList<>(3);
118  services.add(IFloodlightProviderService.class);
119  services.add(IOFSwitchService.class);
120  services.add(IRestApiService.class);
121  return services;
122  }
123 
124  @Override
125  public Collection<Class<? extends IFloodlightService>> getModuleServices() {
126  Collection<Class<? extends IFloodlightService>> services = new ArrayList<>();
127  services.add(IPathVerificationService.class);
128  return services;
129  }
130 
131  @Override
132  public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
133  Map<Class<? extends IFloodlightService>, IFloodlightService> map = new HashMap<>();
134  map.put(IPathVerificationService.class, this);
135  return map;
136  }
137 
138  @Override
139  public void init(FloodlightModuleContext context) throws FloodlightModuleException {
140  logger.debug("main pathverification service: " + this);
141  ConfigurationProvider provider = ConfigurationProvider.of(context, this);
142  KafkaTopicsConfig topicsConfig = provider.getConfiguration(KafkaTopicsConfig.class);
143  PathVerificationServiceConfig serviceConfig = provider.getConfiguration(PathVerificationServiceConfig.class);
144 
145  initConfiguration(topicsConfig, serviceConfig);
146 
147  initServices(context);
148 
149  producer = new KafkaProducer<>(serviceConfig.createKafkaProducerProperties());
150  }
151 
152  @VisibleForTesting
153  void initConfiguration(KafkaTopicsConfig topicsConfig, PathVerificationServiceConfig serviceConfig)
154  throws FloodlightModuleException {
155  topoDiscoTopic = topicsConfig.getTopoDiscoTopic();
156  islBandwidthQuotient = serviceConfig.getIslBandwidthQuotient();
157 
158  initAlgorithm(serviceConfig.getHmac256Secret());
159  }
160 
161  @VisibleForTesting
162  void initServices(FloodlightModuleContext context) {
163  floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
164  switchService = context.getServiceImpl(IOFSwitchService.class);
165  restApiService = context.getServiceImpl(IRestApiService.class);
166  }
167 
168  @VisibleForTesting
169  void initAlgorithm(String secret) throws FloodlightModuleException {
170  try {
171  algorithm = Algorithm.HMAC256(secret);
172  verifier = JWT.require(algorithm).build();
173  } catch (UnsupportedEncodingException e) {
174  logger.error("Ivalid secret", e);
175  throw new FloodlightModuleException("Invalid secret for HMAC256");
176  }
177  }
178 
179  @VisibleForTesting
180  void setKafkaProducer(KafkaProducer<String, String> mockProducer) {
181  producer = mockProducer;
182  }
183 
184  @Override
185  public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
186  logger.info("Stating " + PathVerificationService.class.getCanonicalName());
187  floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
188  restApiService.addRestletRoutable(new PathVerificationServiceWebRoutable());
189  isAlive = true;
190  }
191 
195  @Override
196  public String getName() {
197  return PathVerificationService.class.getSimpleName();
198  }
199 
200  @Override
201  public boolean isCallbackOrderingPostreq(OFType arg0, String arg1) {
202  return false;
203  }
204 
205  @Override
206  public boolean isCallbackOrderingPrereq(OFType arg0, String arg1) {
207  return false;
208  }
209 
210  @Override
212  public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext context) {
213  logger.debug("PathVerificationService received new message of type {}: {}", msg.getType(), msg.toString());
214  switch (msg.getType()) {
215  case PACKET_IN:
216  return handlePacketIn(sw, (OFPacketIn) msg, context);
217  default:
218  break;
219  }
220  return Command.CONTINUE;
221  }
222 
227  public boolean isAlive() {
228  return isAlive;
229  }
230 
231  protected List<OFAction> getDiscoveryActions(IOFSwitch sw, OFPort port) {
232  // set actions
233  List<OFAction> actions = new ArrayList<>();
234  actions.add(sw.getOFFactory().actions().buildOutput().setPort(port).build());
235  return actions;
236  }
237 
238  @Override
239  public boolean sendDiscoveryMessage(DatapathId srcSwId, OFPort port) {
240  return sendDiscoveryMessage(srcSwId, port, null);
241  }
242 
243  @Override
244  public boolean sendDiscoveryMessage(DatapathId srcSwId, OFPort port, DatapathId dstSwId) {
245  boolean result = false;
246 
247  try {
248  IOFSwitch srcSwitch = switchService.getSwitch(srcSwId);
249  if (srcSwitch != null && srcSwitch.getPort(port) != null) {
250  IOFSwitch dstSwitch = (dstSwId == null) ? null : switchService.getSwitch(dstSwId);
251  OFPacketOut ofPacketOut = generateVerificationPacket(srcSwitch, port, dstSwitch, true);
252 
253  if (ofPacketOut != null) {
254  logger.debug("==> Sending verification packet out {}/{}: {}", srcSwitch.getId().toString(),
255  port.getPortNumber(),
256  Hex.encodeHexString(ofPacketOut.getData()));
257  result = srcSwitch.write(ofPacketOut);
258  } else {
259  logger.error("<== Received null from generateVerificationPacket, inputs where: "
260  + "srcSwitch: {}, port: {}, dstSwitch: {}", srcSwitch, port, dstSwitch);
261  }
262 
263  if (result) {
264  logIsl.info("push discovery package via: {}-{}", srcSwitch.getId(), port.getPortNumber());
265  } else {
266  logger.error(
267  "Failed to send PACKET_OUT(ISL discovery packet) via {}-{}",
268  srcSwitch.getId(), port.getPortNumber());
269  }
270  }
271  } catch (Exception exception) {
272  logger.error(String.format("Unhandled exception in %s", getClass().getName()), exception);
273  }
274 
275  return result;
276  }
277 
278  public OFPacketOut generateVerificationPacket(IOFSwitch srcSw, OFPort port) {
279  return generateVerificationPacket(srcSw, port, null, true);
280  }
281 
291  public OFPacketOut generateVerificationPacket(IOFSwitch srcSw, OFPort port, IOFSwitch dstSw,
292  boolean sign) {
293  try {
294  byte[] dpidArray = new byte[8];
295  ByteBuffer dpidBb = ByteBuffer.wrap(dpidArray);
296 
297  DatapathId dpid = srcSw.getId();
298  dpidBb.putLong(dpid.getLong());
299  byte[] chassisId = new byte[]{4, 0, 0, 0, 0, 0, 0};
300  System.arraycopy(dpidArray, 2, chassisId, 1, 6);
301  // Set the optionalTLV to the full SwitchID
302  byte[] dpidTlvValue = new byte[]{0x0, 0x26, (byte) 0xe1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
303  System.arraycopy(dpidArray, 0, dpidTlvValue, 4, 8);
304 
305  OFPortDesc ofPortDesc = srcSw.getPort(port);
306  byte[] zeroMac = {0, 0, 0, 0, 0, 0};
307  byte[] srcMac = ofPortDesc.getHwAddr().getBytes();
308  if (Arrays.equals(srcMac, zeroMac)) {
309  int portVal = ofPortDesc.getPortNo().getPortNumber();
310  // this is a common scenario
311  logger.debug("Port {}/{} has zero hardware address: overwrite with lower 6 bytes of dpid",
312  dpid.toString(), portVal);
313  System.arraycopy(dpidArray, 2, srcMac, 0, 6);
314  }
315 
316  byte[] portId = new byte[]{2, 0, 0};
317  ByteBuffer portBb = ByteBuffer.wrap(portId, 1, 2);
318  portBb.putShort(port.getShortPortNumber());
319 
321  vp.setChassisId(
322  new LLDPTLV().setType((byte) 1).setLength((short) chassisId.length).setValue(chassisId));
323 
324  vp.setPortId(new LLDPTLV().setType((byte) 2).setLength((short) portId.length).setValue(portId));
325 
326  byte[] ttlValue = new byte[]{0, 0x78};
327  vp.setTtl(
328  new LLDPTLV().setType((byte) 3).setLength((short) ttlValue.length).setValue(ttlValue));
329 
330  LLDPTLV dpidTlv = new LLDPTLV().setType((byte) 127).setLength((short) dpidTlvValue.length)
331  .setValue(dpidTlvValue);
332  vp.getOptionalTLVList().add(dpidTlv);
333  // Add the controller identifier to the TLV value.
334  // vp.getOptionalTLVList().add(controllerTLV);
335 
336  // Add T0 based on format from Floodlight LLDP
337  long time = System.currentTimeMillis();
338  long swLatency = srcSw.getLatency().getValue();
339  byte[] timestampTlvValue = ByteBuffer.allocate(Long.SIZE / 8 + 4).put((byte) 0x00)
340  .put((byte) 0x26).put((byte) 0xe1)
341  .put((byte) 0x01) // 0x01 is what we'll use to differentiate DPID (0x00) from time (0x01)
342  .putLong(time + swLatency /* account for our switch's one-way latency */)
343  .array();
344 
345  LLDPTLV timestampTlv = new LLDPTLV().setType((byte) 127)
346  .setLength((short) timestampTlvValue.length).setValue(timestampTlvValue);
347 
348  vp.getOptionalTLVList().add(timestampTlv);
349 
350  // Type
351  byte[] typeTlvValue = ByteBuffer.allocate(Integer.SIZE / 8 + 4).put((byte) 0x00)
352  .put((byte) 0x26).put((byte) 0xe1)
353  .put((byte) 0x02)
354  .putInt(PathType.ISL.ordinal()).array();
355  LLDPTLV typeTlv = new LLDPTLV().setType((byte) 127)
356  .setLength((short) typeTlvValue.length).setValue(typeTlvValue);
357  vp.getOptionalTLVList().add(typeTlv);
358 
359  if (sign) {
360  String token = JWT.create()
361  .withClaim("dpid", dpid.getLong())
362  .withClaim("ts", time + swLatency)
363  .sign(algorithm);
364 
365  byte[] tokenBytes = token.getBytes(Charset.forName("UTF-8"));
366 
367  byte[] tokenTlvValue = ByteBuffer.allocate(4 + tokenBytes.length).put((byte) 0x00)
368  .put((byte) 0x26).put((byte) 0xe1)
369  .put((byte) 0x03)
370  .put(tokenBytes).array();
371  LLDPTLV tokenTlv = new LLDPTLV().setType((byte) 127)
372  .setLength((short) tokenTlvValue.length).setValue(tokenTlvValue);
373 
374  vp.getOptionalTLVList().add(tokenTlv);
375  }
376 
377  MacAddress dstMac = MacAddress.of(VERIFICATION_BCAST_PACKET_DST);
378  if (dstSw != null) {
379  OFPortDesc sw2OfPortDesc = dstSw.getPort(port);
380  dstMac = sw2OfPortDesc.getHwAddr();
381  }
382 
383  IPv4Address dstIp = IPv4Address.of(VERIFICATION_PACKET_IP_DST);
384  if (dstSw != null) {
385  dstIp = IPv4Address
386  .of(((InetSocketAddress) dstSw.getInetAddress()).getAddress().getAddress());
387  }
388  IPv4 l3 = new IPv4()
389  .setSourceAddress(
390  IPv4Address.of(((InetSocketAddress) srcSw.getInetAddress()).getAddress().getAddress()))
391  .setDestinationAddress(dstIp).setTtl((byte) 64).setProtocol(IpProtocol.UDP);
392 
393  UDP l4 = new UDP();
394  l4.setSourcePort(TransportPort.of(VERIFICATION_PACKET_UDP_PORT));
395  l4.setDestinationPort(TransportPort.of(VERIFICATION_PACKET_UDP_PORT));
396 
397 
398  Ethernet l2 = new Ethernet().setSourceMACAddress(MacAddress.of(srcMac))
399  .setDestinationMACAddress(dstMac).setEtherType(EthType.IPv4);
400  l2.setPayload(l3);
401  l3.setPayload(l4);
402  l4.setPayload(vp);
403 
404  byte[] data = l2.serialize();
405  OFPacketOut.Builder pob = srcSw.getOFFactory().buildPacketOut()
406  .setBufferId(OFBufferId.NO_BUFFER).setActions(getDiscoveryActions(srcSw, port))
407  .setData(data);
408  OFMessageUtils.setInPort(pob, OFPort.CONTROLLER);
409 
410  return pob.build();
411  } catch (Exception exception) {
412  logger.error("error generating verification packet: {}", exception);
413  }
414  return null;
415  }
416 
417  private VerificationPacket deserialize(Ethernet eth) throws Exception {
418  if (eth.getPayload() instanceof IPv4) {
419  IPv4 ip = (IPv4) eth.getPayload();
420 
421  if (ip.getPayload() instanceof UDP) {
422  UDP udp = (UDP) ip.getPayload();
423 
424  if ((udp.getSourcePort().getPort() == PathVerificationService.VERIFICATION_PACKET_UDP_PORT)
425  && (udp.getDestinationPort()
427 
428  return new VerificationPacket((Data) udp.getPayload());
429  }
430  }
431  }
432  throw new Exception("Ethernet packet was not a verification packet: " + eth);
433  }
434 
435  private IListener.Command handlePacketIn(IOFSwitch sw, OFPacketIn pkt, FloodlightContext context) {
436  long time = System.currentTimeMillis();
437  logger.debug("packet_in {} received from {}", pkt.getXid(), sw.getId());
438 
439  VerificationPacket verificationPacket = null;
440 
441  Ethernet eth = IFloodlightProviderService.bcStore.get(context, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
442 
443  try {
444  verificationPacket = deserialize(eth);
445  } catch (Exception exception) {
446  logger.trace("Deserialization failure: {}, exception: {}", exception.getMessage(), exception);
447  return Command.CONTINUE;
448  }
449 
450  try {
451  ByteBuffer portBb = ByteBuffer.wrap(verificationPacket.getPortId().getValue());
452  portBb.position(1);
453 
454  long timestamp = 0;
455  int pathOrdinal = 10;
456  IOFSwitch remoteSwitch = null;
457  boolean signed = false;
458  for (LLDPTLV lldptlv : verificationPacket.getOptionalTLVList()) {
459  if (lldptlv.getType() == 127 && lldptlv.getLength() == 12
460  && lldptlv.getValue()[0] == 0x0
461  && lldptlv.getValue()[1] == 0x26
462  && lldptlv.getValue()[2] == (byte) 0xe1
463  && lldptlv.getValue()[3] == 0x0) {
464  ByteBuffer dpidBb = ByteBuffer.wrap(lldptlv.getValue());
465  remoteSwitch = switchService.getSwitch(DatapathId.of(dpidBb.getLong(4)));
466  } else if (lldptlv.getType() == 127 && lldptlv.getLength() == 12
467  && lldptlv.getValue()[0] == 0x0
468  && lldptlv.getValue()[1] == 0x26
469  && lldptlv.getValue()[2] == (byte) 0xe1
470  && lldptlv.getValue()[3] == 0x01) {
471  ByteBuffer tsBb = ByteBuffer.wrap(lldptlv.getValue()); /* skip OpenFlow OUI (4 bytes above) */
472  long swLatency = sw.getLatency().getValue();
473  timestamp = tsBb.getLong(4); /* include the RX switch latency to "subtract" it */
474  timestamp = timestamp + swLatency;
475  } else if (lldptlv.getType() == 127 && lldptlv.getLength() == 8
476  && lldptlv.getValue()[0] == 0x0
477  && lldptlv.getValue()[1] == 0x26
478  && lldptlv.getValue()[2] == (byte) 0xe1
479  && lldptlv.getValue()[3] == 0x02) {
480  ByteBuffer typeBb = ByteBuffer.wrap(lldptlv.getValue());
481  pathOrdinal = typeBb.getInt(4);
482  } else if (lldptlv.getType() == 127
483  && lldptlv.getValue()[0] == 0x0
484  && lldptlv.getValue()[1] == 0x26
485  && lldptlv.getValue()[2] == (byte) 0xe1
486  && lldptlv.getValue()[3] == 0x03) {
487  ByteBuffer bb = ByteBuffer.wrap(lldptlv.getValue());
488  bb.position(4);
489  byte[] tokenArray = new byte[lldptlv.getLength() - 4];
490  bb.get(tokenArray, 0, tokenArray.length);
491  String token = new String(tokenArray);
492 
493  try {
494  DecodedJWT jwt = verifier.verify(token);
495  signed = true;
496  } catch (JWTVerificationException e) {
497  logger.error("Packet verification failed", e);
498  return Command.STOP;
499  }
500  }
501  }
502 
503  // Corner case where we receive a valid VerificationPacket but the remote switch is not known. This is
504  // going to be a bigger issue when we have multiple speakers with different switches on them. For now
505  // if we don't know the switch, then return.
506  //
507  // TODO: fix the above
508 
509  if (remoteSwitch == null) {
510  return Command.STOP;
511  }
512 
513  if (!signed) {
514  logger.warn("verification packet without sign");
515  return Command.STOP;
516  }
517 
518  U64 latency = (timestamp != 0 && (time - timestamp) > 0) ? U64.of(time - timestamp) : U64.ZERO;
519 
520  OFPort inPort = pkt.getVersion().compareTo(OFVersion.OF_12) < 0 ? pkt.getInPort()
521  : pkt.getMatch().get(MatchField.IN_PORT);
522  OFPort remotePort = OFPort.of(portBb.getShort());
523  logIsl.info("link discovered: {}-{} ===( {} ms )===> {}-{}",
524  remoteSwitch.getId(), remotePort, latency.getValue(), sw.getId(), inPort);
525 
526  // this verification packet was sent from remote switch/port to received switch/port
527  // so the link direction is from remote switch/port to received switch/port
528  List<PathNode> nodes = Arrays.asList(
529  new PathNode(new SwitchId(remoteSwitch.getId().toString()), remotePort.getPortNumber(), 0,
530  latency.getValue()),
531  new PathNode(new SwitchId(sw.getId().toString()), inPort.getPortNumber(), 1));
532 
533  OFPortDesc port = sw.getPort(inPort);
534  long speed = Integer.MAX_VALUE;
535 
536  if (port.getVersion().compareTo(OFVersion.OF_13) > 0) {
537  for (OFPortDescProp prop : port.getProperties()) {
538  if (prop.getType() == 0x0) {
539  speed = ((OFPortDescPropEthernet) prop).getCurrSpeed();
540  }
541  }
542  } else {
543  speed = port.getCurrSpeed();
544  }
545 
546  IslInfoData path = new IslInfoData(latency.getValue(), nodes, speed, IslChangeType.DISCOVERED,
547  getAvailableBandwidth(speed));
548 
549  Message message = new InfoMessage(path, System.currentTimeMillis(), CorrelationContext.getId(), null);
550 
551  final String json = MAPPER.writeValueAsString(message);
552  logger.debug("about to send {}", json);
553  producer.send(new ProducerRecord<>(topoDiscoTopic, json));
554  logger.debug("packet_in processed for {}-{}", sw.getId(), inPort);
555 
556  } catch (JsonProcessingException exception) {
557  logger.error("could not create json for path packet_in: {}", exception.getMessage(), exception);
558  } catch (UnsupportedOperationException exception) {
559  logger.error("could not parse packet_in message: {}", exception.getMessage(),
560  exception);
561  } catch (Exception exception) {
562  logger.error("unknown error during packet_in message processing: {}", exception.getMessage(), exception);
563  throw exception;
564  }
565 
566  return Command.STOP;
567  }
568 
569  private long getAvailableBandwidth(long speed) {
570  return (long) (speed * islBandwidthQuotient);
571  }
572 }
nodes
Definition: nodes.py:41
Map< Class<? extends IFloodlightService >, IFloodlightService > getServiceImpls()
static final ObjectMapper MAPPER
Definition: Utils.java:31
Definition: nodes.py:1
Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext context)
Collection< Class<? extends IFloodlightService > > getModuleDependencies()
OFPacketOut generateVerificationPacket(IOFSwitch srcSw, OFPort port, IOFSwitch dstSw, boolean sign)
static ConfigurationProvider of(FloodlightModuleContext moduleContext, IFloodlightModule module)
list result
Definition: plan-d.py:72
Collection< Class<? extends IFloodlightService > > getModuleServices()
boolean sendDiscoveryMessage(DatapathId srcSwId, OFPort port, DatapathId dstSwId)
net
Definition: plan-b.py:46