Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java b/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
index 738fa2a..f7fbdbb 100644
--- a/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
+++ b/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
@@ -100,6 +100,7 @@
                 context.block();
                 return;
             }
+
             HostId id = HostId.hostId(ethPkt.getDestinationMAC());
 
             // Do we know who this is for? If not, flood and bail.
@@ -112,7 +113,9 @@
             // Are we on an edge switch that our destination is on? If so,
             // simply forward out to the destination and bail.
             if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) {
-                installRule(context, dst.location().port());
+                if (!context.inPacket().receivedFrom().port().equals(dst.location().port())) {
+                    installRule(context, dst.location().port());
+                }
                 return;
             }
 
@@ -175,21 +178,24 @@
         // We don't yet support bufferids in the flowservice so packet out first.
         packetOut(context, portNumber);
 
-        // Install the flow rule to handle this type of message from now on.
-        Ethernet inPkt = context.inPacket().parsed();
-        TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
-        builder.matchEthType(inPkt.getEtherType())
-        .matchEthSrc(inPkt.getSourceMAC())
-        .matchEthDst(inPkt.getDestinationMAC())
-        .matchInport(context.inPacket().receivedFrom().port());
+        if (context.inPacket().parsed().getEtherType() == Ethernet.TYPE_IPV4) {
 
-        TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder();
-        treat.setOutput(portNumber);
+            // Install the flow rule to handle this type of message from now on.
+            Ethernet inPkt = context.inPacket().parsed();
+            TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
+            builder.matchEthType(inPkt.getEtherType())
+            .matchEthSrc(inPkt.getSourceMAC())
+            .matchEthDst(inPkt.getDestinationMAC())
+            .matchInport(context.inPacket().receivedFrom().port());
 
-        FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
-                builder.build(), treat.build(), 0, appId);
+            TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder();
+            treat.setOutput(portNumber);
 
-        flowRuleService.applyFlowRules(f);
+            FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
+                    builder.build(), treat.build(), 0, appId);
+
+            flowRuleService.applyFlowRules(f);
+        }
     }
 
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
index 65c4a16..f705a94 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
@@ -27,9 +27,11 @@
 
     private final ApplicationId appId;
 
+    private boolean expired;
+
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
             TrafficTreatment treatment, int priority, FlowRuleState state,
-            long life, long packets, long bytes, long flowId) {
+            long life, long packets, long bytes, long flowId, boolean expired) {
         this.deviceId = deviceId;
         this.priority = priority;
         this.selector = selector;
@@ -37,7 +39,7 @@
         this.state = state;
         this.appId = ApplicationId.valueOf((int) (flowId >> 32));
         this.id = FlowId.valueOf(flowId);
-
+        this.expired = expired;
         this.life = life;
         this.packets = packets;
         this.bytes = bytes;
@@ -186,4 +188,9 @@
                 .toString();
     }
 
+    @Override
+    public boolean expired() {
+        return expired;
+    }
+
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
index 487659b..2728e21 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
@@ -111,4 +111,11 @@
      */
     long bytes();
 
+    /**
+     * Indicates that this flow has expired at the device.
+     *
+     * @return true if it has expired, false otherwise
+     */
+    boolean expired();
+
 }
diff --git a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
index 89c3399..a6f5ebb 100644
--- a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
@@ -161,7 +161,11 @@
             switch (stored.state()) {
             case ADDED:
             case PENDING_ADD:
-                frp.applyFlowRule(stored);
+                if (flowRule.expired()) {
+                    event = store.removeFlowRule(flowRule);
+                } else {
+                    frp.applyFlowRule(stored);
+                }
                 break;
             case PENDING_REMOVE:
             case REMOVED:
diff --git a/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java b/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java
index e7e08fc..6e07c3e 100644
--- a/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java
@@ -231,6 +231,7 @@
         arp.setOpCode(ARP.OP_REPLY);
         arp.setProtocolType(ARP.PROTO_TYPE_IP);
         arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
+
         arp.setProtocolAddressLength((byte) IpPrefix.INET_LEN);
         arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
         arp.setSenderHardwareAddress(h.mac().getAddress());
@@ -238,7 +239,7 @@
 
         arp.setTargetProtocolAddress(((ARP) request.getPayload())
                 .getSenderProtocolAddress());
-        arp.setSenderProtocolAddress(h.ipAddresses().iterator().next().toInt());
+        arp.setSenderProtocolAddress(h.ipAddresses().iterator().next().toRealInt());
         eth.setPayload(arp);
         return eth;
     }
@@ -291,7 +292,6 @@
                 case DEVICE_MASTERSHIP_CHANGED:
                 case DEVICE_SUSPENDED:
                 case DEVICE_UPDATED:
-                case PORT_UPDATED:
                  // nothing to do in these cases; handled when links get reported
                     break;
                 case DEVICE_REMOVED:
@@ -301,9 +301,12 @@
                     }
                     break;
                 case PORT_ADDED:
+                case PORT_UPDATED:
                     synchronized (externalPorts) {
-                        externalPorts.put(device, event.port().number());
-                        internalPorts.remove(device, event.port().number());
+                        if (event.port().isEnabled()) {
+                            externalPorts.put(device, event.port().number());
+                            internalPorts.remove(device, event.port().number());
+                        }
                     }
                     break;
                 case PORT_REMOVED:
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/DefaultOpenFlowPacketContext.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/DefaultOpenFlowPacketContext.java
index 4cd29c4..0f69bac 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/DefaultOpenFlowPacketContext.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/DefaultOpenFlowPacketContext.java
@@ -48,7 +48,7 @@
         OFPacketOut.Builder builder = sw.factory().buildPacketOut();
         OFAction act = buildOutput(outPort.getPortNumber());
         pktout = builder.setXid(pktin.getXid())
-                .setInPort(pktin.getInPort())
+                .setInPort(inport())
                 .setBufferId(pktin.getBufferId())
                 .setActions(Collections.singletonList(act))
                 .build();
@@ -63,7 +63,7 @@
         OFAction act = buildOutput(outPort.getPortNumber());
         pktout = builder.setXid(pktin.getXid())
                 .setBufferId(OFBufferId.NO_BUFFER)
-                .setInPort(pktin.getInPort())
+                .setInPort(inport())
                 .setActions(Collections.singletonList(act))
                 .setData(ethFrame.serialize())
                 .build();
@@ -88,10 +88,16 @@
 
     @Override
     public Integer inPort() {
+        return inport().getPortNumber();
+    }
+
+
+    private OFPort inport() {
+        //FIXME: this has to change in fucking loxi
         try {
-            return pktin.getInPort().getPortNumber();
+            return pktin.getInPort();
         } catch (UnsupportedOperationException e) {
-            return pktin.getMatch().get(MatchField.IN_PORT).getPortNumber();
+            return pktin.getMatch().get(MatchField.IN_PORT);
         }
     }
 
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
index 3f2984b..04aef8d 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OFChannelHandler.java
@@ -651,7 +651,7 @@
          * @param error The error message
          */
         protected void logError(OFChannelHandler h, OFErrorMsg error) {
-            log.debug("{} from switch {} in state {}",
+            log.info("{} from switch {} in state {}",
                     new Object[] {
                     error,
                     h.getSwitchInfoString(),
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java
index 6cf4fa4..868eb86 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/drivers/impl/DriverManager.java
@@ -6,6 +6,7 @@
 import java.util.List;
 
 import org.onlab.onos.openflow.controller.Dpid;
+import org.onlab.onos.openflow.controller.RoleState;
 import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
 import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver;
 import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriverFactory;
@@ -61,6 +62,11 @@
         return new AbstractOpenFlowSwitch(dpid, desc) {
 
             @Override
+            public void setRole(RoleState state) {
+                this.role = RoleState.MASTER;
+            }
+
+            @Override
             public void write(List<OFMessage> msgs) {
                 channel.write(msgs);
             }
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
index 51e4a98..86ab701 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
@@ -73,7 +73,7 @@
         List<OFAction> actions = buildActions();
 
         //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
-        OFFlowMod fm = factory.buildFlowModify()
+        OFFlowMod fm = factory.buildFlowAdd()
                 .setCookie(U64.of(cookie.value()))
                 .setBufferId(OFBufferId.NO_BUFFER)
                 .setActions(actions)
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
index 6d773de..ac00f05 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
@@ -18,6 +18,7 @@
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
+import org.projectfloodlight.openflow.protocol.OFFlowRemovedReason;
 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
 import org.projectfloodlight.openflow.protocol.action.OFAction;
 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
@@ -70,14 +71,15 @@
                     buildSelector(), buildTreatment(), stat.getPriority(),
                     FlowRuleState.ADDED, stat.getDurationNsec() / 1000000,
                     stat.getPacketCount().getValue(), stat.getByteCount().getValue(),
-                    stat.getCookie().getValue());
+                    stat.getCookie().getValue(), false);
         } else {
             // TODO: revisit potentially.
             return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
                     buildSelector(), null, removed.getPriority(),
                     FlowRuleState.REMOVED, removed.getDurationNsec() / 1000000,
                     removed.getPacketCount().getValue(), removed.getByteCount().getValue(),
-                    removed.getCookie().getValue());
+                    removed.getCookie().getValue(),
+                    removed.getReason() == OFFlowRemovedReason.IDLE_TIMEOUT.ordinal());
         }
     }
 
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
index c8d9c25..bf29ae4 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -158,7 +158,7 @@
             case BARRIER_REPLY:
             case ERROR:
             default:
-                log.warn("Unhandled message type: {}", msg.getType());
+                log.debug("Unhandled message type: {}", msg.getType());
             }
 
         }
diff --git a/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java b/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java
index 132b185..0c4502b 100644
--- a/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java
+++ b/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/LinkDiscovery.java
@@ -131,7 +131,7 @@
         }
         timeout = Timer.getTimer().newTimeout(this, 0,
                 TimeUnit.MILLISECONDS);
-        this.log.debug("Started discovery manager for switch {}",
+        this.log.info("Started discovery manager for switch {}",
                 sw.getId());
 
     }
diff --git a/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java b/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
index 41cb586..94f7a33 100644
--- a/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
+++ b/providers/openflow/packet/src/main/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProvider.java
@@ -1,6 +1,5 @@
 package org.onlab.onos.provider.of.packet.impl;
 
-import static org.onlab.onos.openflow.controller.RoleState.SLAVE;
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.nio.ByteBuffer;
@@ -95,9 +94,6 @@
         if (sw == null) {
             log.warn("Device {} isn't available?", devId);
             return;
-        } else if (sw.getRole().equals(SLAVE)) {
-            log.warn("Can't write to Device {} as slave", devId);
-            return;
         }
 
         Ethernet eth = new Ethernet();
diff --git a/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java b/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
index 66c0aea..030563c 100644
--- a/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
+++ b/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
@@ -140,12 +140,12 @@
         sw.sent.clear();
 
         //wrong Role
-        sw.setRole(RoleState.SLAVE);
-        provider.emit(passPkt);
-        assertEquals("invalid switch", sw, controller.current);
-        assertEquals("message sent incorrectly", 0, sw.sent.size());
+        //sw.setRole(RoleState.SLAVE);
+        //provider.emit(passPkt);
+        //assertEquals("invalid switch", sw, controller.current);
+        //assertEquals("message sent incorrectly", 0, sw.sent.size());
 
-        sw.setRole(RoleState.MASTER);
+        //sw.setRole(RoleState.MASTER);
 
         //missing switch
         OutboundPacket swFailPkt = outPacket(DID_MISSING, TR, eth);
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java b/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
index f466122..b205f90 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
@@ -180,6 +180,15 @@
         return address;
     }
 
+    public int toRealInt() {
+        int val = 0;
+        for (int i = 0; i < octets.length; i++) {
+          val <<= 8;
+          val |= octets[i] & 0xff;
+        }
+        return val;
+    }
+
     /**
      * Helper for computing the mask value from CIDR.
      *