+
+ @Override
+ public Status sendBarrierMessage(Node node) {
+ if (!node.getType().equals(NodeIDType.OPENFLOW)) {
+ return new Status(StatusCode.NOTACCEPTABLE,
+ "The node does not support Barrier message.");
+ }
+
+ if (controller != null) {
+ long swid = (Long) node.getID();
+ ISwitch sw = controller.getSwitch(swid);
+ if (sw != null) {
+ sw.sendBarrierMessage();
+ clearXid2Rid(swid);
+ return (new Status(StatusCode.SUCCESS, null));
+ } else {
+ return new Status(StatusCode.GONE,
+ "The node does not have a valid Switch reference.");
+ }
+ }
+ return new Status(StatusCode.INTERNALERROR,
+ "Failed to send Barrier message.");
+ }
+
+ /**
+ * This method sends the message asynchronously until the number of messages
+ * sent reaches a threshold. Then a Barrier message is sent automatically
+ * for sync purpose. An unique Request ID associated with the message is
+ * passed down by the caller. The Request ID will be returned to the caller
+ * when an error message is received from the switch.
+ *
+ * @param node
+ * The node
+ * @param msg
+ * The switch
+ * @param msg
+ * The OF message to be sent
+ * @param rid
+ * The Request Id
+ * @return result
+ */
+ private Object asyncMsgSend(Node node, ISwitch sw, OFMessage msg, long rid) {
+ Object result = Boolean.TRUE;
+ long swid = (Long) node.getID();
+ int xid;
+
+ xid = sw.asyncSend(msg);
+ addXid2Rid(swid, xid, rid);
+
+ Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
+ if (swxid2rid == null) {
+ return result;
+ }
+
+ int size = swxid2rid.size();
+ if (size % barrierMessagePriorCount == 0) {
+ result = sendBarrierMessage(node);
+ }
+
+ return result;
+ }
+
+ /**
+ * A number of async messages are sent followed by a synchronous Barrier
+ * message. This method returns the maximum async messages that can be sent
+ * before the Barrier message.
+ *
+ * @return The max count of async messages sent prior to Barrier message
+ */
+ private int getBarrierMessagePriorCount() {
+ String count = System.getProperty("of.barrierMessagePriorCount");
+ int rv = 100;
+
+ if (count != null) {
+ try {
+ rv = Integer.parseInt(count);
+ } catch (Exception e) {
+ }
+ }
+
+ return rv;
+ }
+
+ /**
+ * This method returns the message Request ID previously assigned by the
+ * caller for a given OF message xid
+ *
+ * @param swid
+ * The switch id
+ * @param xid
+ * The OF message xid
+ * @return The Request ID
+ */
+ public long getMessageRid(long swid, int xid) {
+ Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
+ long rid = 0;
+
+ if (swxid2rid != null) {
+ rid = swxid2rid.get(xid);
+ }
+ return rid;
+ }
+
+ /**
+ * This method returns a copy of outstanding xid to rid mappings.for a given
+ * switch
+ *
+ * @param swid
+ * The switch id
+ * @return a copy of xid2rid mappings
+ */
+ public Map<Integer, Long> getSwXid2Rid(long swid) {
+ Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
+
+ if (swxid2rid != null) {
+ return new HashMap<Integer, Long>(swxid2rid);
+ } else {
+ return new HashMap<Integer, Long>();
+ }
+ }
+
+ /**
+ * Adds xid to rid mapping to the local DB
+ *
+ * @param swid
+ * The switch id
+ * @param xid
+ * The OF message xid
+ * @param rid
+ * The message Request ID
+ */
+ private void addXid2Rid(long swid, int xid, long rid) {
+ Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
+ if (swxid2rid != null) {
+ swxid2rid.put(xid, rid);
+ }
+ }
+
+ /**
+ * When an Error message is received, this method will be invoked to remove
+ * the offending xid from the local DB.
+ *
+ * @param swid
+ * The switch id
+ * @param xid
+ * The OF message xid
+ */
+ private void removeXid2Rid(long swid, int xid) {
+ Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
+ if (swxid2rid != null) {
+ swxid2rid.remove(xid);
+ }
+ }
+
+ /**
+ * When a Barrier reply is received, this method will be invoked to clear
+ * the local DB
+ *
+ * @param swid
+ * The switch id
+ */
+ private void clearXid2Rid(long swid) {
+ Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
+ if (swxid2rid != null) {
+ swxid2rid.clear();
+ }
+ }
+
+ @Override
+ public void updateNode(Node node, UpdateType type, Set<Property> props) {
+ long swid = (Long)node.getID();
+
+ switch (type) {
+ case ADDED:
+ Map<Integer, Long> swxid2rid = new HashMap<Integer, Long>();
+ this.xid2rid.put(swid, swxid2rid);
+ break;
+ case CHANGED:
+ break;
+ case REMOVED:
+ this.xid2rid.remove(swid);
+ break;
+ default:
+ }
+ }
+
+ @Override
+ public void updateNodeConnector(NodeConnector nodeConnector,
+ UpdateType type, Set<Property> props) {
+ }
+
+ private void registerWithOSGIConsole() {
+ BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
+ .getBundleContext();
+ bundleContext.registerService(CommandProvider.class.getName(), this,
+ null);
+ }
+
+ @Override
+ public String getHelp() {
+ StringBuffer help = new StringBuffer();
+ help.append("-- Flow Programmer Service --\n");
+ help.append("\t px2r <node id> - Print outstanding xid2rid mappings for a given node id\n");
+ help.append("\t px2rc - Print max num of async msgs prior to the Barrier\n");
+ return help.toString();
+ }
+
+ public void _px2r(CommandInterpreter ci) {
+ String st = ci.nextArgument();
+ if (st == null) {
+ ci.println("Please enter a valid node id");
+ return;
+ }
+
+ long sid;
+ try {
+ sid = HexEncode.stringToLong(st);
+ } catch (NumberFormatException e) {
+ ci.println("Please enter a valid node id");
+ return;
+ }
+
+ Map<Integer, Long> swxid2rid = this.xid2rid.get(sid);
+ if (swxid2rid == null) {
+ ci.println("The node id entered does not exist");
+ return;
+ }
+
+ ci.println("xid rid");
+
+ Set<Integer> xidSet = swxid2rid.keySet();
+ if (xidSet == null) {
+ return;
+ }
+
+ for (Integer xid : xidSet) {
+ ci.println(xid + " " + swxid2rid.get(xid));
+ }
+ }
+
+ public void _px2rc(CommandInterpreter ci) {
+ ci.println("Max num of async messages sent prior to the Barrier message is "
+ + barrierMessagePriorCount);
+ }