diff --git a/src/main/images/Floodlight Icons.sketch/Data b/src/main/images/Floodlight Icons.sketch/Data
index bb5c893b9e5d4172708bd150a5c1137548333db9..0fbceabe0c97c926b15762291f968aca11db5a96 100644
Binary files a/src/main/images/Floodlight Icons.sketch/Data and b/src/main/images/Floodlight Icons.sketch/Data differ
diff --git a/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png b/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png
index 77fc493ec2b292f44d48e5a360f0459b45dab267..4a36e7cbb504eacc1a3a70237183873e35cbb61c 100644
Binary files a/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png and b/src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png differ
diff --git a/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png b/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png
index 942c917bac3f2f0d351c47e4ad18001e31c4132d..50ebe22932430361c768192df9e1f4a2e3c2423a 100644
Binary files a/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png and b/src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png differ
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
index 3ccef428d1b25d5e96a6e89a14dd7fc5778ad1b1..780e56f3efe539536d929bf9a31e5fe5842f0b8d 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
@@ -104,6 +104,16 @@ public class Device implements IDevice {
         List<AttachmentPoint>oldAP =
                 new ArrayList<AttachmentPoint>(attachmentPoints);
 
+        // Remove invalid attachment points before sorting.
+        List<AttachmentPoint>tempAP =
+                new ArrayList<AttachmentPoint>();
+        for(AttachmentPoint ap: oldAP) {
+            if (deviceManager.isValidAttachmentPoint(ap.getSw(), ap.getPort())){
+                tempAP.add(ap);
+            }
+        }
+        oldAP = tempAP;
+
         Collections.sort(oldAP, deviceManager.apComparator);
 
         // Map of attachment point by L2 domain Id.
diff --git a/src/main/resources/web/img/switch.png b/src/main/resources/web/img/switch.png
index d241d92d74d012aa886823a597936b7dcab759c3..f8e69108f7d9c26ae92fcc41d7fb286cfc390edb 100644
Binary files a/src/main/resources/web/img/switch.png and b/src/main/resources/web/img/switch.png differ
diff --git a/src/main/resources/web/index.html b/src/main/resources/web/index.html
index 1812037aed3ce286cdcd31ace15edd21f4a16e9c..54e1cb398d464d81dee4bda46e9353f96cfb24e2 100644
--- a/src/main/resources/web/index.html
+++ b/src/main/resources/web/index.html
@@ -50,31 +50,8 @@
 
 <div class="header"></div>
 
-<!-- FIXME closing these alerts returns to the dashboard; why? -->
-
-
 <div class="container">
 
-<!--
-<div class="row">
-<div class="span12">
-<div class="alert alert-info">
-Floodlight is the awesomest OpenFlow controller, and you're running it right now.
-<a class="close" data-dismiss="alert" href="#">&times;</a>
-</div>
-</div>
-</div>
-
-<div class="row">
-<div class="span12">
-<div class="alert alert-error">
-This Web interface is <strong>incomplete and buggy</strong>! Don't be surprised if you see errors or missing data.
-<a class="close" data-dismiss="alert" href="#">&times;</a>
-</div>
-</div>
-</div>
--->
-
 <div id="content"></div>
 
 <hr>
diff --git a/src/main/resources/web/js/main.js b/src/main/resources/web/js/main.js
index 7e0ac8106a78109f9b48da40c70f61d43c749ad3..2362757ac690fb3c27bc6a6a54fbe3e2eead68a6 100644
--- a/src/main/resources/web/js/main.js
+++ b/src/main/resources/web/js/main.js
@@ -47,8 +47,8 @@ var AppRouter = Backbone.Router.extend({
     },
 
     topology:function () {
-    	//console.log("switching to topology view");
-    	var topo = new Topology();
+        //console.log("switching to topology view");
+        var topo = new Topology();
         $('#content').html(new TopologyView({model:topo, hosts:hl}).render().el);
         // TODO factor this code out
         $('ul.nav > li').removeClass('active');
@@ -56,30 +56,30 @@ var AppRouter = Backbone.Router.extend({
     },
     
     switchDetails:function (id) {
-    	//console.log("switching [sic] to single switch view");
-    	var sw = swl.get(id);
-    	$('#content').html(new SwitchView({model:sw}).render().el);
+        //console.log("switching [sic] to single switch view");
+        var sw = swl.get(id);
+        $('#content').html(new SwitchView({model:sw}).render().el);
         $('ul.nav > li').removeClass('active');
         $('li > a[href*="/switches"]').parent().addClass('active');
     },
     
     switchList:function () {
-    	//console.log("switching [sic] to switch list view");
+        //console.log("switching [sic] to switch list view");
         $('#content').html(new SwitchListView({model:swl}).render().el);
         $('ul.nav > li').removeClass('active');
         $('li > a[href*="/switches"]').parent().addClass('active');
     },
 
     hostDetails:function (id) {
-    	//console.log("switching to single host view");
-    	var h = hl.get(id);
-    	$('#content').html(new HostView({model:h}).render().el);
+        //console.log("switching to single host view");
+        var h = hl.get(id);
+        $('#content').html(new HostView({model:h}).render().el);
         $('ul.nav > li').removeClass('active');
         $('li > a[href*="/hosts"]').parent().addClass('active');
     },
     
     hostList:function () {
-    	//console.log("switching to host list view");
+        //console.log("switching to host list view");
         $('#content').html(new HostListView({model:hl}).render().el);
         $('ul.nav > li').removeClass('active');
         $('li > a[href*="/hosts"]').parent().addClass('active');
@@ -99,21 +99,21 @@ tpl.loadTemplates(['home', 'status', 'topology', 'header', 'switch', 'switch-lis
         
         $(document).ready(function () {
             // trigger Backbone routing when clicking on links, thanks to Atinux and pbnv
-	    app.navigate("", true);
-
-                window.document.addEventListener('click', function(e) {
-        	    e = e || window.event
-        	    var target = e.target || e.srcElement
-        	    if ( target.nodeName.toLowerCase() === 'a' ) {
-        	        e.preventDefault()
-        	        var uri = target.getAttribute('href')
-        	        app.navigate(uri.substr(1), true)
-        	    }
-        	});
-        	window.addEventListener('popstate', function(e) {
-        	    app.navigate(location.pathname.substr(1), true);
-        	});
-	    
+            app.navigate("", true);
+
+            window.document.addEventListener('click', function(e) {
+                e = e || window.event
+                var target = e.target || e.srcElement
+                if ( target.nodeName.toLowerCase() === 'a' ) {
+                    e.preventDefault()
+                    var uri = target.getAttribute('href')
+                    app.navigate(uri.substr(1), true)
+                }
+            });
+            window.addEventListener('popstate', function(e) {
+                app.navigate(location.pathname.substr(1), true);
+            });
+
         });
     });
 
diff --git a/src/main/resources/web/js/models/flowmodel.js b/src/main/resources/web/js/models/flowmodel.js
index 4923f610c415ca1e8e518e02c5bd3229c00f5a6b..80777c334f15c01bf7590bdf456320a2657a23ad 100644
--- a/src/main/resources/web/js/models/flowmodel.js
+++ b/src/main/resources/web/js/models/flowmodel.js
@@ -16,13 +16,13 @@
 
 window.Flow = Backbone.Model.extend({
 
-	defaults: {
-		receiveBytes: 0,
-		receivePackets: 0,
-		transmitBytes: 0,
-		transmitPackets: 0,
-	},
-	
+    defaults: {
+        receiveBytes: 0,
+        receivePackets: 0,
+        transmitBytes: 0,
+        transmitPackets: 0,
+    },
+
     // initialize:function () {}
 
 });
diff --git a/src/main/resources/web/js/models/hostmodel.js b/src/main/resources/web/js/models/hostmodel.js
index ec37d1573c043dd9f61cbdb159696da2e7c49774..47ae4207e97fb2168c81e900e42f38ac853fe2c4 100644
--- a/src/main/resources/web/js/models/hostmodel.js
+++ b/src/main/resources/web/js/models/hostmodel.js
@@ -62,11 +62,11 @@ window.HostCollection = Backbone.Collection.extend({
     }
 
     /*
-	 * findByName:function (key) { // TODO: Modify service to include firstName
-	 * in search var url = (key == '') ? '/host/' : "/host/search/" + key;
-	 * console.log('findByName: ' + key); var self = this; $.ajax({ url:url,
-	 * dataType:"json", success:function (data) { console.log("search success: " +
-	 * data.length); self.reset(data); } }); }
-	 */
+     * findByName:function (key) { // TODO: Modify service to include firstName
+     * in search var url = (key == '') ? '/host/' : "/host/search/" + key;
+     * console.log('findByName: ' + key); var self = this; $.ajax({ url:url,
+     * dataType:"json", success:function (data) { console.log("search success: " +
+     * data.length); self.reset(data); } }); }
+     */
 
 });
diff --git a/src/main/resources/web/js/models/statusmodel.js b/src/main/resources/web/js/models/statusmodel.js
index aac2f8d2aab44609bae4805d2667ade896f058ce..31bdff37565b54d2ccd2a66d1cac348d5ac8a0b8 100644
--- a/src/main/resources/web/js/models/statusmodel.js
+++ b/src/main/resources/web/js/models/statusmodel.js
@@ -16,14 +16,14 @@
 
 window.Status = Backbone.Model.extend({    
     defaults: {
-    	host: 'localhost',
-    	ofport: 6633,
-    	uptime: 'unknown',
-    	free: 0,
-    	total: 0,
-    	healthy: 'unknown',
-    	modules: [],
-    	moduleText: ''
+        host: 'localhost',
+        ofport: 6633,
+        uptime: 'unknown',
+        free: 0,
+        total: 0,
+        healthy: 'unknown',
+        modules: [],
+        moduleText: ''
     },
     
     initialize:function () {
@@ -54,7 +54,8 @@ window.Status = Backbone.Model.extend({
                 console.log("fetched controller status: modules loaded");
                 // console.log(data);
                 self.set({modules:_.keys(data)});
-                self.set({moduleText:_.reduce(_.keys(data), function(s, m){return s+m.replace("net.floodlightcontroller", "n.f")+", "}, '')});
+                self.set({moduleText:_.reduce(_.keys(data), function(s, m)
+                    {return s+m.replace("net.floodlightcontroller", "n.f")+", "}, '')});
             }
         });
 
diff --git a/src/main/resources/web/js/models/switchmodel.js b/src/main/resources/web/js/models/switchmodel.js
index 252b316e45c605e02477a57a167827cdd560865d..a2483a5a5cb5fb0ff78e245dc3aee542f0340d0a 100644
--- a/src/main/resources/web/js/models/switchmodel.js
+++ b/src/main/resources/web/js/models/switchmodel.js
@@ -185,8 +185,10 @@ window.SwitchCollection = Backbone.Collection.extend({
             dataType:"json",
             success:function (data) {
                 //console.log("fetched  switch list: " + data.length);
-                // console.log(data);
-                _.each(data, function(sw) {self.add({id: sw['dpid']})});
+                //console.log(data);
+                _.each(data, function(sw) {self.add({id: sw['dpid'],
+                                                     inetAddress: sw.inetAddress,
+                                                     connectedSince: new Date(sw.connectedSince).toLocaleString()})});
             }
         });
     },
diff --git a/src/main/resources/web/js/models/topologymodel.js b/src/main/resources/web/js/models/topologymodel.js
index be9fa302fa2b78ed0260e04118acaddd9823ade9..c5d8f9bff2cc9bbf13a7ee615faca1f173f23457 100644
--- a/src/main/resources/web/js/models/topologymodel.js
+++ b/src/main/resources/web/js/models/topologymodel.js
@@ -19,8 +19,8 @@ window.Topology = Backbone.Model.extend({
     url:"/wm/topology/links/json",
     
     defaults:{
-    	nodes: [],
-    	links: [],
+        nodes: [],
+        links: [],
     },
 
     initialize:function () {
@@ -34,19 +34,25 @@ window.Topology = Backbone.Model.extend({
                 // console.log(data);
                 self.nodes = {};
                 self.links = [];
+
                 // step 1: build unique array of switch IDs
+                /* this doesn't work if there's only one switch,
+                   because there are no switch-switch links
                 _.each(data, function (l) {
-                	self.nodes[l['src-switch']] = true;
-                	self.nodes[l['dst-switch']] = true;
+                    self.nodes[l['src-switch']] = true;
+                    self.nodes[l['dst-switch']] = true;
                 });
                 // console.log(self.nodes);
                 var nl = _.keys(self.nodes);
+                */
+                var nl = swl.pluck('id');
                 self.nodes = _.map(nl, function (n) {return {name:n}});
+
                 // step 2: build array of links in format D3 expects
                 _.each(data, function (l) {
-                	self.links.push({source:nl.indexOf(l['src-switch']),
-                					 target:nl.indexOf(l['dst-switch']),
-                					 value:10});
+                    self.links.push({source:nl.indexOf(l['src-switch']),
+                                     target:nl.indexOf(l['dst-switch']),
+                                     value:10});
                 });
                 // console.log(self.nodes);
                 // console.log(self.links);
diff --git a/src/main/resources/web/js/views/flow.js b/src/main/resources/web/js/views/flow.js
index 3d0609240edef0e4281d6b9741cea1d36e39d5d7..65e0b71d9e70a4522250e9c53f26499f68ad4c1e 100644
--- a/src/main/resources/web/js/views/flow.js
+++ b/src/main/resources/web/js/views/flow.js
@@ -48,7 +48,7 @@ window.FlowListItemView = Backbone.View.extend({
 // TODO throughput (bps) and pps sparklines would be nice here
 // TODO hovering over a MAC address could show a compact view of that host
 window.FlowListView = Backbone.View.extend({
-	
+
     initialize:function () {
         this.template = _.template(tpl.get('flow-list'));
         this.model.bind("change", this.render, this);
@@ -56,11 +56,11 @@ window.FlowListView = Backbone.View.extend({
     },
 
     render:function (eventName) {
-    	// console.log("rendering flow list view: " + this.model.models.length);
+        // console.log("rendering flow list view: " + this.model.models.length);
         $(this.el).html(this.template({nflows:this.model.length}));
         _.each(this.model.models, function (f) {
             $(this.el).find('table.flow-table > tbody')
-            	.append(new FlowListItemView({model:f}).render().el);
+                .append(new FlowListItemView({model:f}).render().el);
         }, this);
         return this;
     },
diff --git a/src/main/resources/web/js/views/port.js b/src/main/resources/web/js/views/port.js
index e6001e334df06e0d219a08a69af8f67dae2d7892..e9aadb9103a13b320e9131add8e0dfc68ca015fe 100644
--- a/src/main/resources/web/js/views/port.js
+++ b/src/main/resources/web/js/views/port.js
@@ -49,7 +49,7 @@ window.PortListItemView = Backbone.View.extend({
 
 // TODO throughput sparklines would be nice here
 window.PortListView = Backbone.View.extend({
-	
+
     initialize:function () {
         this.template = _.template(tpl.get('port-list'));
         this.model.bind("change", this.render, this);
@@ -57,11 +57,11 @@ window.PortListView = Backbone.View.extend({
     },
 
     render:function (eventName) {
-    	// console.log("rendering port list view");
+        // console.log("rendering port list view");
         $(this.el).html(this.template({nports:this.model.length}));
         _.each(this.model.models, function (p) {
             $(this.el).find('table.port-table > tbody')
-            	.append(new PortListItemView({model:p}).render().el);
+                .append(new PortListItemView({model:p}).render().el);
         }, this);
         return this;
     },
diff --git a/src/main/resources/web/js/views/status.js b/src/main/resources/web/js/views/status.js
index d56507e29e142be3993f0d708fbd1fe5ed1d5c64..52c6c1cbaa3e5a3279983979f625086ebe742f67 100644
--- a/src/main/resources/web/js/views/status.js
+++ b/src/main/resources/web/js/views/status.js
@@ -22,7 +22,7 @@ window.StatusView = Backbone.View.extend({
     },
 
     render:function (eventName) {
-    	// console.log("rendering status");
+        // console.log("rendering status");
         $(this.el).html(this.template(this.model.toJSON()));
         //$(this.el).html(this.template());
         return this;
diff --git a/src/main/resources/web/js/views/switch.js b/src/main/resources/web/js/views/switch.js
index 9aa850a364ced8f85374fa1522268127da8c9590..178dd99bba9021ac1675a17a46af2e77dc90e7f3 100644
--- a/src/main/resources/web/js/views/switch.js
+++ b/src/main/resources/web/js/views/switch.js
@@ -42,7 +42,7 @@ window.SwitchListItemView = Backbone.View.extend({
     initialize:function () {
         this.template = _.template(tpl.get('switch-list-item'));
         this.model.bind("change", this.render, this);
-	//this.model.bind("destroy", this.close, this);
+    //this.model.bind("destroy", this.close, this);
     },
 
     render:function (eventName) {
@@ -53,7 +53,7 @@ window.SwitchListItemView = Backbone.View.extend({
 });
 
 window.SwitchListView = Backbone.View.extend({
-	
+
     initialize:function () {
         this.template = _.template(tpl.get('switch-list'));
         this.model.bind("change", this.render, this);
@@ -63,7 +63,7 @@ window.SwitchListView = Backbone.View.extend({
         $(this.el).html(this.template({nswitches:swl.length}));
         _.each(this.model.models, function (sw) {
             $(this.el).find('table.switch-table > tbody')
-            	.append(new SwitchListItemView({model:sw}).render().el);
+                .append(new SwitchListItemView({model:sw}).render().el);
         }, this);
         return this;
     },
diff --git a/src/main/resources/web/tpl/flow-list.html b/src/main/resources/web/tpl/flow-list.html
index 4b6e4065b97cbdd5fe3b98c4eeea92c270bb804c..4bd0a856c9e47138aa88af71404b4567f1a822dd 100644
--- a/src/main/resources/web/tpl/flow-list.html
+++ b/src/main/resources/web/tpl/flow-list.html
@@ -1,7 +1,7 @@
 <div class="page-header">
 	<h1>Flows (<%= nflows %>)</h1>
 </div>
-<table class="table striped-table flow-table">
+<table class="table table-striped flow-table">
 	<thead><tr><th>Cookie</th><th>Priority</th><th>Match</th><th>Action</th><th>Packets</th><th>Bytes</th><th>Age</th><th>Timeout</th></tr></thead>
 	<tbody>
 		<!-- flows will be inserted here by FlowListView:render -->
diff --git a/src/main/resources/web/tpl/host-list.html b/src/main/resources/web/tpl/host-list.html
index ec63b3a76cab06455e251644f4e61736b209e0f8..cc4a2c067835eee5e331747d284eb86a3de1e4f3 100644
--- a/src/main/resources/web/tpl/host-list.html
+++ b/src/main/resources/web/tpl/host-list.html
@@ -3,7 +3,7 @@
 <div class="page-header">
 	<h1>Hosts (<%= nhosts %>)</h1>
 </div>
-<table class="table striped-table host-table">
+<table class="table table-striped host-table">
 	<thead><tr><th>MAC Address</th><!-- <th>VLAN</th> --><th>IP Address</th><th>Switch Port</th><th>Last Seen</th></tr></thead>
 	<tbody>
 		<!-- hosts will be inserted here by HostListView.render -->
diff --git a/src/main/resources/web/tpl/port-list.html b/src/main/resources/web/tpl/port-list.html
index d4c30606af8270b512d537497c8c144e732e377d..044fffff406fb22ff7eaae25d7583a2524edd66d 100644
--- a/src/main/resources/web/tpl/port-list.html
+++ b/src/main/resources/web/tpl/port-list.html
@@ -1,7 +1,7 @@
 <div class="page-header">
 	<h1>Ports (<%= nports %>)</h1>
 </div>
-<table class="table striped-table port-table">
+<table class="table table-striped port-table">
 	<thead><tr><th>#</th><th>Link Status</th><th>TX Bytes</th><th>RX Bytes</th><th>TX Pkts</th><th>RX Pkts</th><th>Dropped</th><th>Errors</th></tr></thead>
 	<tbody>
 		<!-- ports will be inserted here by PortListView:render -->
diff --git a/src/main/resources/web/tpl/switch-list-item.html b/src/main/resources/web/tpl/switch-list-item.html
index 7a20a5a09ad02cb3123d38e4029ddb7c4c0e98c9..c6cd4ac58b52cb5994824e615301d8251404bc21 100644
--- a/src/main/resources/web/tpl/switch-list-item.html
+++ b/src/main/resources/web/tpl/switch-list-item.html
@@ -1 +1 @@
-<td><a href="/switch/<%= id %>"><%= id %></a></td><td><%= manufacturerDescription %><td><%= packetCount %></td><td><%= byteCount %></td><td><%= flowCount %></td>
+<td><a href="/switch/<%= id %>"><%= id %></a></td><td><%= inetAddress %></td><td><%= manufacturerDescription %><td><%= packetCount %></td><td><%= byteCount %></td><td><%= flowCount %></td><td><%= connectedSince %></td>
diff --git a/src/main/resources/web/tpl/switch-list.html b/src/main/resources/web/tpl/switch-list.html
index 45c02f55f13b1024d9882bb489cda6cce8f6c8f4..7e577aac84c0ed5fbb9a613fa4931a0ba6f9cdd1 100644
--- a/src/main/resources/web/tpl/switch-list.html
+++ b/src/main/resources/web/tpl/switch-list.html
@@ -3,8 +3,8 @@
 <div class="page-header">
 	<h1>Switches (<%= nswitches %>)</h1>
 </div>
-<table class="table striped-table switch-table">
-    <thead><tr><th>DPID</th><th>Vendor</th><th>Packets</th><th>Bytes</th><th>Flows</th></tr></thead>
+<table class="table table-striped switch-table">
+	<thead><tr><th>DPID</th><th>IP Address</th><th>Vendor</th><th>Packets</th><th>Bytes</th><th>Flows</th><th>Connected Since</th></tr></thead>
 	<tbody>
 		<!-- switches will be inserted here by SwitchListView:render -->
 	</tbody>
diff --git a/src/main/resources/web/tpl/switch.html b/src/main/resources/web/tpl/switch.html
index bfba96795031241c30500042d1331bd6ba5b400e..bc1169d383438f970a5444e8dbac679e015c0bbf 100644
--- a/src/main/resources/web/tpl/switch.html
+++ b/src/main/resources/web/tpl/switch.html
@@ -1,9 +1,10 @@
 <div class="row">
 <div class="span12">
 <div class="page-header">
-	<h1>Switch <%= id %></h1>
+	<h1>Switch <%= id %> <%= inetAddress %></h1>
 </div>
-<p><%= manufacturerDescription %><br>
+<p>Connected since <%= connectedSince %><br>
+<%= manufacturerDescription %><br>
 <%= hardwareDescription %><br>
 <%= softwareDescription %><br>
 S/N: <%= serialNumber %><br>