Implementing port update in trivial core.
diff --git a/net/api/src/main/java/org/onlab/onos/net/DefaultPort.java b/net/api/src/main/java/org/onlab/onos/net/DefaultPort.java
new file mode 100644
index 0000000..56a2979
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/DefaultPort.java
@@ -0,0 +1,70 @@
+package org.onlab.onos.net;
+
+import java.util.Objects;
+
+import static com.google.common.base.Objects.toStringHelper;
+
+/**
+ * Default port implementation.
+ */
+public class DefaultPort implements Port {
+
+    private final Element element;
+    private final PortNumber number;
+    private final boolean isEnabled;
+
+    /**
+     * Creates a network element attributed to the specified provider.
+     *
+     * @param element   parent network element
+     * @param number    port number
+     * @param isEnabled indicator whether the port is up and active
+     */
+    public DefaultPort(Element element, PortNumber number,
+                       boolean isEnabled) {
+        this.element = element;
+        this.number = number;
+        this.isEnabled = isEnabled;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(number, isEnabled);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof DefaultPort) {
+            final DefaultPort other = (DefaultPort) obj;
+            return Objects.equals(this.element.id(), other.element.id()) &&
+                    Objects.equals(this.number, other.number) &&
+                    Objects.equals(this.isEnabled, other.isEnabled);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("element", element.id())
+                .add("number", number)
+                .add("isEnabled", isEnabled)
+                .toString();
+    }
+
+    @Override
+    public PortNumber number() {
+        return number;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return isEnabled;
+    }
+
+    @Override
+    public Element element() {
+        return element;
+    }
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/Port.java b/net/api/src/main/java/org/onlab/onos/net/Port.java
index cf9a2ce..e98278b 100644
--- a/net/api/src/main/java/org/onlab/onos/net/Port.java
+++ b/net/api/src/main/java/org/onlab/onos/net/Port.java
@@ -20,11 +20,11 @@
     boolean isEnabled();
 
     /**
-     * Returns the identifier of the network element to which this port belongs.
+     * Returns the parent network element to which this port belongs.
      *
      * @return parent network element
      */
-    Element parent();
+    Element element();
 
     // set of port attributes
 
diff --git a/net/api/src/main/java/org/onlab/onos/net/device/DeviceEvent.java b/net/api/src/main/java/org/onlab/onos/net/device/DeviceEvent.java
index 984f575..10b3b19 100644
--- a/net/api/src/main/java/org/onlab/onos/net/device/DeviceEvent.java
+++ b/net/api/src/main/java/org/onlab/onos/net/device/DeviceEvent.java
@@ -2,12 +2,15 @@
 
 import org.onlab.onos.event.AbstractEvent;
 import org.onlab.onos.net.Device;
+import org.onlab.onos.net.Port;
 
 /**
  * Describes infrastructure device event.
  */
 public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
 
+    private final Port port;
+
     /**
      * Type of device events.
      */
@@ -42,7 +45,22 @@
          * Signifies that the current controller instance relationship has
          * changed with respect to a device.
          */
-        DEVICE_MASTERSHIP_CHANGED
+        DEVICE_MASTERSHIP_CHANGED,
+
+        /**
+         * Signifies that a port has been added.
+         */
+        PORT_ADDED,
+
+        /**
+         * Signifies that a port has been updated.
+         */
+        PORT_UPDATED,
+
+        /**
+         * Signifies that a port has been removed.
+         */
+        PORT_REMOVED
     }
 
     /**
@@ -53,7 +71,20 @@
      * @param device event device subject
      */
     public DeviceEvent(Type type, Device device) {
+        this(type, device, null);
+    }
+
+    /**
+     * Creates an event of a given type and for the specified device, port
+     * and the current time.
+     *
+     * @param type   device event type
+     * @param device event device subject
+     * @param port   optional port subject
+     */
+    public DeviceEvent(Type type, Device device, Port port) {
         super(type, device);
+        this.port = port;
     }
 
     /**
@@ -61,10 +92,21 @@
      *
      * @param type   device event type
      * @param device event device subject
+     * @param port   optional port subject
      * @param time   occurrence time
      */
-    public DeviceEvent(Type type, Device device, long time) {
+    public DeviceEvent(Type type, Device device, Port port, long time) {
         super(type, device, time);
+        this.port = port;
+    }
+
+    /**
+     * Returns the port subject.
+     *
+     * @return port subject or null if the event is not port specific.
+     */
+    Port port() {
+        return port;
     }
 
 }
diff --git a/net/api/src/test/java/org/onlab/onos/net/device/DeviceEventTest.java b/net/api/src/test/java/org/onlab/onos/net/device/DeviceEventTest.java
index df2b419..6f1219a 100644
--- a/net/api/src/test/java/org/onlab/onos/net/device/DeviceEventTest.java
+++ b/net/api/src/test/java/org/onlab/onos/net/device/DeviceEventTest.java
@@ -3,9 +3,13 @@
 import org.junit.Test;
 import org.onlab.onos.event.AbstractEventTest;
 import org.onlab.onos.net.DefaultDevice;
+import org.onlab.onos.net.DefaultPort;
 import org.onlab.onos.net.Device;
+import org.onlab.onos.net.Port;
+import org.onlab.onos.net.PortNumber;
 import org.onlab.onos.net.provider.ProviderId;
 
+import static org.junit.Assert.assertEquals;
 import static org.onlab.onos.net.DeviceId.deviceId;
 
 /**
@@ -21,17 +25,19 @@
     @Test
     public void withTime() {
         Device device = createDevice();
+        Port port = new DefaultPort(device, PortNumber.portNumber(123L), true);
         DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED,
-                                            device, 123L);
+                                            device, port, 123L);
         validateEvent(event, DeviceEvent.Type.DEVICE_ADDED, device, 123L);
+        assertEquals("incorrect port", port, event.port());
     }
 
     @Test
     public void withoutTime() {
         Device device = createDevice();
+        Port port = new DefaultPort(device, PortNumber.portNumber(123L), true);
         long before = System.currentTimeMillis();
-        DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED,
-                                            device);
+        DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
         long after = System.currentTimeMillis();
         validateEvent(event, DeviceEvent.Type.DEVICE_ADDED, device, before, after);
     }
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceStore.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceStore.java
index eeb11cb..0179507 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceStore.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceStore.java
@@ -1,6 +1,7 @@
 package org.onlab.onos.net.trivial.impl;
 
 import org.onlab.onos.net.DefaultDevice;
+import org.onlab.onos.net.DefaultPort;
 import org.onlab.onos.net.Device;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.MastershipRole;
@@ -13,7 +14,9 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -21,18 +24,19 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
-import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED;
-import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_REMOVED;
+import static org.onlab.onos.net.device.DeviceEvent.Type.*;
 
 /**
  * Manages inventory of infrastructure devices.
  */
 class SimpleDeviceStore {
 
+    public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
+
     private final Map<DeviceId, DefaultDevice> devices = new ConcurrentHashMap<>();
     private final Map<DeviceId, MastershipRole> roles = new ConcurrentHashMap<>();
     private final Set<DeviceId> availableDevices = new HashSet<>();
+    private final Map<DeviceId, Map<PortNumber, Port>> devicePorts = new HashMap<>();
 
     /**
      * Returns an iterable collection of all devices known to the system.
@@ -82,7 +86,7 @@
             devices.put(deviceId, device);
             availableDevices.add(deviceId);
         }
-        return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
+        return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device, null);
     }
 
     // Updates the device and returns the appropriate event if necessary.
@@ -101,13 +105,14 @@
                 devices.put(device.id(), updated);
                 availableDevices.add(device.id());
             }
-            return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, device);
+            return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, device, null);
         }
 
         // Otherwise merely attempt to change availability
         synchronized (this) {
             boolean added = availableDevices.add(device.id());
-            return added ? new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device) : null;
+            return !added ? null :
+                    new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null);
         }
     }
 
@@ -120,9 +125,10 @@
     DeviceEvent markOffline(DeviceId deviceId) {
         synchronized (this) {
             Device device = devices.get(deviceId);
-            checkArgument(device != null, "Device with ID %s is not found", deviceId);
+            checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
             boolean removed = availableDevices.remove(deviceId);
-            return removed ? new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device) : null;
+            return !removed ? null :
+                    new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null);
         }
     }
 
@@ -136,7 +142,79 @@
      */
     List<DeviceEvent> updatePorts(DeviceId deviceId,
                                   List<PortDescription> portDescriptions) {
-        return new ArrayList<>();
+        List<DeviceEvent> events = new ArrayList<>();
+        synchronized (this) {
+            Device device = devices.get(deviceId);
+            checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
+            Map<PortNumber, Port> ports = getPortMap(deviceId);
+
+            // Add new ports
+            Set<PortNumber> processed = new HashSet<>();
+            for (PortDescription portDescription : portDescriptions) {
+                Port port = ports.get(portDescription.portNumber());
+                DeviceEvent event = port == null ?
+                        createPort(device, portDescription, ports) :
+                        updatePort(device, port, portDescription, ports);
+                processed.add(portDescription.portNumber());
+            }
+
+            events.addAll(pruneOldPorts(device, ports, processed));
+        }
+        return events;
+    }
+
+    // Creates a new port based on the port description adds it to the map and
+    // Returns corresponding event.
+    private DeviceEvent createPort(Device device, PortDescription portDescription,
+                                   Map<PortNumber, Port> ports) {
+        DefaultPort port = new DefaultPort(device, portDescription.portNumber(),
+                                           portDescription.isEnabled());
+        ports.put(port.number(), port);
+        return new DeviceEvent(PORT_ADDED, device, port);
+    }
+
+    // CHecks if the specified port requires update and if so, it replaces the
+    // existing entry in the map and returns corresponding event.
+    private DeviceEvent updatePort(Device device, Port port,
+                                   PortDescription portDescription,
+                                   Map<PortNumber, Port> ports) {
+        if (port.isEnabled() != portDescription.isEnabled()) {
+            DefaultPort updatedPort =
+                    new DefaultPort(device, portDescription.portNumber(),
+                                    portDescription.isEnabled());
+            ports.put(port.number(), updatedPort);
+            return new DeviceEvent(PORT_UPDATED, device, port);
+        }
+        return null;
+    }
+
+    // Prunes the specified list of ports based on which ports are in the
+    // processed list and returns list of corresponding events.
+    private List<DeviceEvent> pruneOldPorts(Device device,
+                                            Map<PortNumber, Port> ports,
+                                            Set<PortNumber> processed) {
+        List<DeviceEvent> events = new ArrayList<>();
+        Iterator<PortNumber> iterator = ports.keySet().iterator();
+        while (iterator.hasNext()) {
+            PortNumber portNumber = iterator.next();
+            if (processed.contains(portNumber)) {
+                events.add(new DeviceEvent(PORT_REMOVED, device,
+                                           ports.get(portNumber)));
+                iterator.remove();
+            }
+        }
+        return events;
+    }
+
+    // Gets the map of ports for the specified device; if one does not already
+    // exist, it creates and registers a new one.
+    private Map<PortNumber, Port> getPortMap(DeviceId deviceId) {
+        Map<PortNumber, Port> ports = devicePorts.get(deviceId);
+        if (ports == null) {
+            ports = new HashMap<>();
+            devicePorts.put(deviceId, ports);
+        }
+        return ports;
     }
 
     /**
@@ -194,9 +272,10 @@
     DeviceEvent setRole(DeviceId deviceId, MastershipRole role) {
         synchronized (this) {
             Device device = getDevice(deviceId);
-            checkArgument(device != null, "Device with ID %s not found");
+            checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
             MastershipRole oldRole = roles.put(deviceId, role);
-            return oldRole == role ? null : new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device);
+            return oldRole == role ? null :
+                    new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device, null);
         }
     }
 
@@ -209,7 +288,9 @@
         synchronized (this) {
             roles.remove(deviceId);
             Device device = devices.remove(deviceId);
-            return device != null ? new DeviceEvent(DEVICE_REMOVED, device) : null;
+            return device == null ? null :
+                    new DeviceEvent(DEVICE_REMOVED, device, null);
         }
     }
+
 }
diff --git a/of/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver13/OFActionBsnVer13.java b/of/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver13/OFActionBsnVer13.java
index 02a568d..cc9d8d0 100644
--- a/of/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver13/OFActionBsnVer13.java
+++ b/of/openflowj/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver13/OFActionBsnVer13.java
@@ -24,6 +24,8 @@
 import org.projectfloodlight.openflow.util.*;
 import org.projectfloodlight.openflow.exceptions.*;
 import org.jboss.netty.buffer.ChannelBuffer;
+
+import java.nio.ByteBuffer;
 import java.util.Set;
 
 abstract class OFActionBsnVer13 {
@@ -36,7 +38,7 @@
 
     static class Reader implements OFMessageReader<OFActionBsn> {
         @Override
-        public OFActionBsn readFrom(ChannelBuffer bb) throws OFParseError {
+        public OFActionBsn readFrom(ByteBuffer bb) throws OFParseError {
             if(bb.readableBytes() < MINIMUM_LENGTH)
                 return null;
             int start = bb.readerIndex();