stats reported
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 564416c..fae1fe3 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
@@ -2,6 +2,8 @@
 
 import static com.google.common.base.MoreObjects.toStringHelper;
 
+import java.util.Objects;
+
 import org.onlab.onos.net.DeviceId;
 
 public class DefaultFlowRule implements FlowRule {
@@ -12,10 +14,10 @@
     private final TrafficTreatment treatment;
     private final FlowId id;
     private final long created;
-    private long life;
-    private long idle;
-    private long packets;
-    private long bytes;
+    private final long life;
+    private final long idle;
+    private final long packets;
+    private final long bytes;
 
 
     public DefaultFlowRule(DeviceId deviceId,
@@ -32,15 +34,21 @@
         this.created = System.currentTimeMillis();
     }
 
-    // TODO: Decide whether to take the flowId from the underlying flowentry.
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
             TrafficTreatment treatment, int priority,
-            long life, long idle, long packets, long bytes) {
-        this(deviceId, selector, treatment, priority);
+            long life, long idle, long packets, long bytes, Integer flowId) {
+        this.deviceId = deviceId;
+        this.priority = priority;
+        this.selector = selector;
+        this.treatment = treatment;
+
+        this.id = FlowId.valueOf(flowId);
+
         this.life = life;
         this.idle = idle;
         this.packets = packets;
         this.bytes = bytes;
+        this.created = System.currentTimeMillis();
     }
 
 
@@ -97,11 +105,7 @@
      * @see java.lang.Object#equals(java.lang.Object)
      */
     public int hashCode() {
-        final int prime = 31;
-        int result = prime * this.deviceId().hashCode();
-        result = prime * result + selector.hashCode();
-        result = prime * result + treatment.hashCode();
-        return result;
+        return Objects.hash(deviceId, selector, treatment);
     }
 
     @Override
@@ -140,4 +144,5 @@
                 .toString();
     }
 
+
 }
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 ecdd17c..b2e7cf4 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
@@ -6,6 +6,7 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import org.onlab.onos.net.flow.FlowId;
 import org.onlab.onos.net.flow.FlowRule;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
@@ -39,6 +40,7 @@
 import org.projectfloodlight.openflow.types.OFBufferId;
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.U64;
 import org.projectfloodlight.openflow.types.VlanPcp;
 import org.projectfloodlight.openflow.types.VlanVid;
 import org.slf4j.Logger;
@@ -54,6 +56,8 @@
 
     private final int priority;
 
+    private final FlowId cookie;
+
 
 
     public FlowModBuilder(FlowRule flowRule, OFFactory factory) {
@@ -61,6 +65,7 @@
         this.treatment = flowRule.treatment();
         this.selector = flowRule.selector();
         this.priority = flowRule.priority();
+        this.cookie = flowRule.id();
     }
 
     public OFFlowMod buildFlowMod() {
@@ -69,6 +74,7 @@
 
         //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
         OFFlowMod fm = factory.buildFlowModify()
+                .setCookie(U64.of(cookie.value()))
                 .setBufferId(OFBufferId.NO_BUFFER)
                 .setActions(actions)
                 .setMatch(match)
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
new file mode 100644
index 0000000..33b6205
--- /dev/null
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
@@ -0,0 +1,260 @@
+package org.onlab.onos.provider.of.flow.impl;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.List;
+
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.flow.DefaultFlowRule;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.DefaultTrafficTreatment;
+import org.onlab.onos.net.flow.FlowRule;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.flow.criteria.Criteria;
+import org.onlab.onos.net.flow.instructions.Instructions;
+import org.onlab.onos.openflow.controller.Dpid;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.slf4j.Logger;
+
+public class FlowRuleBuilder {
+    private final Logger log = getLogger(getClass());
+
+    private final OFFlowStatsEntry stat;
+    private final OFFlowRemoved removed;
+
+    private final Match match;
+    private final List<OFAction> actions;
+
+    private final Dpid dpid;
+
+
+
+
+    public FlowRuleBuilder(Dpid dpid, OFFlowStatsEntry entry) {
+        this.stat = entry;
+        this.match = entry.getMatch();
+        this.actions = entry.getActions();
+        this.dpid = dpid;
+        removed = null;
+    }
+
+    public FlowRuleBuilder(Dpid dpid, OFFlowRemoved removed) {
+        this.match = removed.getMatch();
+        this.removed = removed;
+
+        this.dpid = dpid;
+        this.actions = null;
+        this.stat = null;
+
+    }
+
+    public FlowRule build() {
+        if (stat != null) {
+            return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
+                    buildSelector(), buildTreatment(), stat.getPriority(),
+                    stat.getDurationNsec() / 1000000, stat.getIdleTimeout(),
+                    stat.getPacketCount().getValue(), stat.getByteCount().getValue(),
+                    (int) (stat.getCookie().getValue() & 0xFFFFFFFF));
+        } else {
+            // TODO: revisit potentially.
+            return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
+                    buildSelector(), null, removed.getPriority(),
+                    removed.getDurationNsec() / 1000000, removed.getIdleTimeout(),
+                    removed.getPacketCount().getValue(), removed.getByteCount().getValue(),
+                    (int) (removed.getCookie().getValue() & 0xFFFFFFFF));
+        }
+    }
+
+
+    private TrafficTreatment buildTreatment() {
+        TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder();
+        // If this is a drop rule
+        if (actions.size() == 0) {
+            builder.add(Instructions.createDrop());
+            return builder.build();
+        }
+        for (OFAction act : actions) {
+            switch (act.getType()) {
+            case OUTPUT:
+                OFActionOutput out = (OFActionOutput) act;
+                builder.add(Instructions.createOutput(
+                        PortNumber.portNumber(out.getPort().getPortNumber())));
+                break;
+            case SET_VLAN_PCP:
+                OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
+                builder.add(Instructions.modVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan())));
+                break;
+            case SET_VLAN_VID:
+                OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
+                builder.add(Instructions.modVlanId(VlanId.vlanId(pcp.getVlanPcp().getValue())));
+                break;
+            case SET_DL_DST:
+                OFActionSetDlDst dldst = (OFActionSetDlDst) act;
+                builder.add(Instructions.modL2Dst(
+                        MacAddress.valueOf(dldst.getDlAddr().getLong())));
+                break;
+            case SET_DL_SRC:
+                OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
+                builder.add(Instructions.modL2Src(
+                        MacAddress.valueOf(dlsrc.getDlAddr().getLong())));
+
+                break;
+            case SET_NW_DST:
+                OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
+                IPv4Address di = nwdst.getNwAddr();
+                if (di.isCidrMask()) {
+                    builder.add(Instructions.modL3Dst(IpAddress.valueOf(di.getInt(),
+                            di.asCidrMaskLength())));
+                } else {
+                    builder.add(Instructions.modL3Dst(IpAddress.valueOf(di.getInt())));
+                }
+                break;
+            case SET_NW_SRC:
+                OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
+                IPv4Address si = nwsrc.getNwAddr();
+                if (si.isCidrMask()) {
+                    builder.add(Instructions.modL3Dst(IpAddress.valueOf(si.getInt(),
+                            si.asCidrMaskLength())));
+                } else {
+                    builder.add(Instructions.modL3Dst(IpAddress.valueOf(si.getInt())));
+                }
+                break;
+            case SET_TP_DST:
+            case SET_TP_SRC:
+            case POP_MPLS:
+            case POP_PBB:
+            case POP_VLAN:
+            case PUSH_MPLS:
+            case PUSH_PBB:
+            case PUSH_VLAN:
+            case SET_FIELD:
+            case SET_MPLS_LABEL:
+            case SET_MPLS_TC:
+            case SET_MPLS_TTL:
+            case SET_NW_ECN:
+            case SET_NW_TOS:
+            case SET_NW_TTL:
+            case SET_QUEUE:
+            case STRIP_VLAN:
+            case COPY_TTL_IN:
+            case COPY_TTL_OUT:
+            case DEC_MPLS_TTL:
+            case DEC_NW_TTL:
+            case ENQUEUE:
+            case EXPERIMENTER:
+            case GROUP:
+            default:
+                log.warn("Action type {} not yet implemented.", act.getType());
+            }
+        }
+
+        return builder.build();
+    }
+
+    private TrafficSelector buildSelector() {
+        TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
+        for (MatchField<?> field : match.getMatchFields()) {
+            switch (field.id) {
+            case IN_PORT:
+                builder.add(Criteria.matchInPort(PortNumber
+                        .portNumber(match.get(MatchField.IN_PORT).getPortNumber())));
+                break;
+            case ETH_SRC:
+                MacAddress sMac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
+                builder.add(Criteria.matchEthSrc(sMac));
+                break;
+            case ETH_DST:
+                MacAddress dMac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
+                builder.add(Criteria.matchEthSrc(dMac));
+                break;
+            case ETH_TYPE:
+                int ethType = match.get(MatchField.ETH_TYPE).getValue();
+                builder.add(Criteria.matchEthType((short) ethType));
+                break;
+            case IPV4_DST:
+                IPv4Address di = match.get(MatchField.IPV4_DST);
+                IpAddress dip;
+                if (di.isCidrMask()) {
+                    dip = IpAddress.valueOf(di.getInt(), di.asCidrMaskLength());
+                } else {
+                    dip = IpAddress.valueOf(di.getInt());
+                }
+                builder.add(Criteria.matchIPDst(dip));
+                break;
+            case IPV4_SRC:
+                IPv4Address si = match.get(MatchField.IPV4_SRC);
+                IpAddress sip;
+                if (si.isCidrMask()) {
+                    sip = IpAddress.valueOf(si.getInt(), si.asCidrMaskLength());
+                } else {
+                    sip = IpAddress.valueOf(si.getInt());
+                }
+                builder.add(Criteria.matchIPSrc(sip));
+                break;
+            case IP_PROTO:
+                short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
+                builder.add(Criteria.matchIPProtocol((byte) proto));
+                break;
+            case VLAN_PCP:
+                byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
+                builder.add(Criteria.matchVlanPcp(vlanPcp));
+                break;
+            case VLAN_VID:
+                VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
+                builder.add(Criteria.matchVlanId(vlanId));
+                break;
+            case ARP_OP:
+            case ARP_SHA:
+            case ARP_SPA:
+            case ARP_THA:
+            case ARP_TPA:
+            case ICMPV4_CODE:
+            case ICMPV4_TYPE:
+            case ICMPV6_CODE:
+            case ICMPV6_TYPE:
+            case IN_PHY_PORT:
+            case IPV6_DST:
+            case IPV6_FLABEL:
+            case IPV6_ND_SLL:
+            case IPV6_ND_TARGET:
+            case IPV6_ND_TLL:
+            case IPV6_SRC:
+            case IP_DSCP:
+            case IP_ECN:
+            case METADATA:
+            case MPLS_LABEL:
+            case MPLS_TC:
+            case SCTP_DST:
+            case SCTP_SRC:
+            case TCP_DST:
+            case TCP_SRC:
+            case TUNNEL_ID:
+            case UDP_DST:
+            case UDP_SRC:
+            default:
+                log.warn("Match type {} not yet implemented.", field.id);
+
+
+            }
+        }
+        return builder.build();
+    }
+
+}
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 73e00bb..b11eb0c 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
@@ -10,8 +10,6 @@
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.onos.net.DeviceId;
-import org.onlab.onos.net.flow.DefaultFlowRule;
 import org.onlab.onos.net.flow.FlowRule;
 import org.onlab.onos.net.flow.FlowRuleProvider;
 import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
@@ -131,7 +129,8 @@
             case FLOW_REMOVED:
                 //TODO: make this better
                 OFFlowRemoved removed = (OFFlowRemoved) msg;
-                FlowRule fr = new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)), null, null, 0);
+
+                FlowRule fr = new FlowRuleBuilder(dpid, removed).build();
                 providerService.flowRemoved(fr);
                 break;
             case STATS_REPLY:
@@ -154,6 +153,7 @@
             for (OFFlowStatsEntry reply : replies.getEntries()) {
                 entries.add(new FlowRuleBuilder(dpid, reply).build());
             }
+            log.debug("sending flowstats to core {}", entries);
             providerService.pushFlowMetrics(entries);
         }
 
diff --git a/tools/build/conf/src/main/resources/onos/checkstyle.xml b/tools/build/conf/src/main/resources/onos/checkstyle.xml
index 842e818..06413aa 100644
--- a/tools/build/conf/src/main/resources/onos/checkstyle.xml
+++ b/tools/build/conf/src/main/resources/onos/checkstyle.xml
@@ -175,8 +175,10 @@
             <property name="max" value="200"/>
         </module>
 
-        <module name="ParameterNumber"/>
-
+        <module name="ParameterNumber">
+            <property name="max" value="10"/>
+            <property name="tokens" value="CTOR_DEF"/>
+        </module>
         <!-- Checks for whitespace                               -->
         <!-- See http://checkstyle.sf.net/config_whitespace.html -->
         <module name="EmptyForIteratorPad"/>
@@ -272,6 +274,7 @@
         <!-- <module name="TodoComment"/> -->
         <module name="UpperEll"/>
 
+
       </module>
 
     </module>