This commit consists of some miscellaneous small changes and some
exception tracking to help packet-out debugging in the adapter.

Change-Id: I1d6b50f60c800768acb5a132c1d630416ac9811f
diff --git a/python/adapters/iadapter.py b/python/adapters/iadapter.py
index 78cf42a..abe1bbc 100644
--- a/python/adapters/iadapter.py
+++ b/python/adapters/iadapter.py
@@ -200,12 +200,13 @@
         log.info("adapter-update-pm-config", device=device,
                  pm_config=pm_config)
         handler = self.devices_handlers[device.id]
-        handler.update_pm_config(device, pm_config)
+        if handler:
+            reactor.callLater(0, handler.update_pm_config, device, pm_config)
 
     def process_inter_adapter_message(self, msg):
         raise NotImplementedError()
 
-    def receive_packet_out(self, logical_device_id, egress_port_no, msg):
+    def receive_packet_out(self, device_id, egress_port_no, msg):
         raise NotImplementedError()
 
     def suppress_alarm(self, filter):
@@ -288,10 +289,14 @@
             reactor.callLater(0, handler.process_inter_adapter_message, msg)
 
     def receive_packet_out(self, device_id, egress_port_no, msg):
-        log.info('receive_packet_out', device_id=device_id,
-                 egress_port=egress_port_no, msg=msg)
-        handler = self.devices_handlers[device_id]
-        handler.packet_out(egress_port_no, msg.data)
+        try:
+            log.info('receive_packet_out', device_id=device_id,
+                     egress_port=egress_port_no, msg=msg)
+            handler = self.devices_handlers[device_id]
+            if handler:
+                reactor.callLater(0, handler.packet_out, egress_port_no, msg.data)
+        except Exception, e:
+            log.exception('packet-out-failure', e=e)
 
 
 """
diff --git a/python/adapters/kafka/adapter_request_facade.py b/python/adapters/kafka/adapter_request_facade.py
index e104cbc..fccb049 100644
--- a/python/adapters/kafka/adapter_request_facade.py
+++ b/python/adapters/kafka/adapter_request_facade.py
@@ -309,26 +309,29 @@
 
 
     def receive_packet_out(self, deviceId, outPort, packet):
-        d_id = StrType()
-        if deviceId:
-            deviceId.Unpack(d_id)
-        else:
-            return False, Error(code=ErrorCode.INVALID_PARAMETERS,
-                                reason="deviceid-invalid")
+        try:
+            d_id = StrType()
+            if deviceId:
+                deviceId.Unpack(d_id)
+            else:
+                return False, Error(code=ErrorCode.INVALID_PARAMETERS,
+                                    reason="deviceid-invalid")
 
-        op = IntType()
-        if outPort:
-            outPort.Unpack(op)
-        else:
-            return False, Error(code=ErrorCode.INVALID_PARAMETERS,
-                                reason="outport-invalid")
+            op = IntType()
+            if outPort:
+                outPort.Unpack(op)
+            else:
+                return False, Error(code=ErrorCode.INVALID_PARAMETERS,
+                                    reason="outport-invalid")
 
-        p = ofp_packet_out()
-        if packet:
-            packet.Unpack(p)
-        else:
-            return False, Error(code=ErrorCode.INVALID_PARAMETERS,
-                                reason="packet-invalid")
+            p = ofp_packet_out()
+            if packet:
+                packet.Unpack(p)
+            else:
+                return False, Error(code=ErrorCode.INVALID_PARAMETERS,
+                                    reason="packet-invalid")
 
-        return (True, self.adapter.receive_packet_out(d_id, op, p))
+            return (True, self.adapter.receive_packet_out(d_id.val, op.val, p))
+        except Exception as e:
+            log.exception("error-processing-receive_packet_out", e=e)
 
diff --git a/python/adapters/ponsim_olt/ponsim_olt.py b/python/adapters/ponsim_olt/ponsim_olt.py
index e3157e7..06c1235 100644
--- a/python/adapters/ponsim_olt/ponsim_olt.py
+++ b/python/adapters/ponsim_olt/ponsim_olt.py
@@ -340,7 +340,7 @@
             port=LogicalPort(
                 ofp_port=ofp_port(
                     hw_addr=mac_str_to_tuple(
-                        '00:00:00:00:00:%02x' % port_no),
+                        'AA:BB:CC:DD:EE:%02x' % port_no),
                     config=0,
                     state=OFPPS_LIVE,
                     curr=cap,
@@ -491,24 +491,28 @@
     def packet_out(self, egress_port, msg):
         self.log.info('sending-packet-out', egress_port=egress_port,
                       msg=hexify(msg))
-        pkt = Ether(msg)
-        out_pkt = pkt
-        if egress_port != self.nni_port.port_no:
-            # don't do the vlan manipulation for the NNI port, vlans are already correct
-            out_pkt = (
-                    Ether(src=pkt.src, dst=pkt.dst) /
-                    Dot1Q(vlan=egress_port, type=pkt.type) /
-                    pkt.payload
-            )
+        try:
+            pkt = Ether(msg)
+            out_pkt = pkt
+            if egress_port != self.nni_port.port_no:
+                # don't do the vlan manipulation for the NNI port, vlans are already correct
+                out_pkt = (
+                        Ether(src=pkt.src, dst=pkt.dst) /
+                        Dot1Q(vlan=egress_port, type=pkt.type) /
+                        pkt.payload
+                )
 
-        # TODO need better way of mapping logical ports to PON ports
-        out_port = self.nni_port.port_no if egress_port == self.nni_port.port_no else 1
+            # TODO need better way of mapping logical ports to PON ports
+            out_port = self.nni_port.port_no if egress_port == self.nni_port.port_no else 1
 
-        # send over grpc stream
-        stub = ponsim_pb2.PonSimStub(self.channel)
-        frame = PonSimFrame(id=self.device_id, payload=str(out_pkt),
-                            out_port=out_port)
-        stub.SendFrame(frame)
+            # send over grpc stream
+            stub = ponsim_pb2.PonSimStub(self.channel)
+            frame = PonSimFrame(id=self.device_id, payload=str(out_pkt),
+                                out_port=out_port)
+            stub.SendFrame(frame)
+        except Exception as e:
+            self.log.exception("error-processing-packet-out", e=e)
+
 
     @inlineCallbacks
     def reboot(self):
diff --git a/python/adapters/ponsim_onu/ponsim_onu.py b/python/adapters/ponsim_onu/ponsim_onu.py
index 9ad0799..22d9ca4 100644
--- a/python/adapters/ponsim_onu/ponsim_onu.py
+++ b/python/adapters/ponsim_onu/ponsim_onu.py
@@ -199,6 +199,8 @@
         device.root = False
         device.vendor = 'ponsim'
         device.model = 'n/a'
+        device.serial_number = device.id
+        device.mac_address = "AA:BB:CC:DD:E0:00"
         yield self.core_proxy.device_update(device)
 
         # Now set the initial PM configuration for this device
@@ -250,7 +252,7 @@
         return PortCapability(
             port=LogicalPort(
                 ofp_port=ofp_port(
-                    hw_addr=mac_str_to_tuple('00:00:00:00:00:%02x' % port_no),
+                    hw_addr=mac_str_to_tuple('AA:BB:CC:DD:E0:%02x' % port_no),
                     config=0,
                     state=OFPPS_LIVE,
                     curr=cap,
diff --git a/rw_core/core/logical_device_agent.go b/rw_core/core/logical_device_agent.go
index ee3d82a..7875da7 100644
--- a/rw_core/core/logical_device_agent.go
+++ b/rw_core/core/logical_device_agent.go
@@ -110,12 +110,12 @@
 		lp.DeviceId = agent.rootDeviceId
 		lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
 		lp.OfpPort.PortNo = port.PortNo
-		lp.OfpPort.Name = portCap.Port.Id
+		lp.OfpPort.Name = lp.Id
 		lp.DevicePortNo = port.PortNo
 		ld.Ports = append(ld.Ports, lp)
 	}
 	agent.lockLogicalDevice.Lock()
-	defer agent.lockLogicalDevice.Unlock()
+	//defer agent.lockLogicalDevice.Unlock()
 	// Save the logical device
 	if added := agent.clusterDataProxy.AddWithID("/logical_devices", ld.Id, ld, ""); added == nil {
 		log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
@@ -133,6 +133,11 @@
 	agent.flowProxy.RegisterCallback(model.POST_UPDATE, agent.flowTableUpdated)
 	agent.groupProxy.RegisterCallback(model.POST_UPDATE, agent.groupTableUpdated)
 
+	agent.lockLogicalDevice.Unlock()
+
+	// Setup the device graph
+	go agent.setupDeviceGraph()
+
 	return nil
 }
 
@@ -255,7 +260,7 @@
 	if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
 		return status.Error(codes.NotFound, agent.logicalDeviceId)
 	} else {
-		log.Infow("!!!!!!!!!!!ADDING-UNI", log.Fields{"deviceId": childDevice.Id})
+		log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
 		portCap.Port.RootPort = false
 		//TODO: For now use the channel id assigned by the OLT as logical port number
 		lPortNo := childDevice.ProxyAddress.ChannelId
@@ -265,6 +270,7 @@
 		portCap.Port.DeviceId = childDevice.Id
 		portCap.Port.DevicePortNo = uniPort
 		portCap.Port.DeviceId = childDevice.Id
+
 		ldevice.Ports = append(ldevice.Ports, portCap.Port)
 		return agent.updateLogicalDeviceWithoutLock(ldevice)
 	}
@@ -959,9 +965,6 @@
 		return nil
 	}
 
-	// Ensure the device graph has been setup
-	agent.setupDeviceGraph()
-
 	var groups *ofp.FlowGroups
 	lDevice, _ := agent.getLogicalDeviceWithoutLock()
 	groups = lDevice.FlowGroups
@@ -1001,9 +1004,6 @@
 		return nil
 	}
 
-	// Ensure the device graph has been setup
-	agent.setupDeviceGraph()
-
 	var flows *ofp.Flows
 	lDevice, _ := agent.getLogicalDeviceWithoutLock()
 	flows = lDevice.Flows
diff --git a/rw_core/core/logical_device_manager.go b/rw_core/core/logical_device_manager.go
index f49e52a..19eb6a4 100644
--- a/rw_core/core/logical_device_manager.go
+++ b/rw_core/core/logical_device_manager.go
@@ -285,7 +285,11 @@
 	log.Debugw("AddUNILogicalPort", log.Fields{"logDeviceId": logDeviceId, "parentId": parentId})
 
 	if agent := ldMgr.getLogicalDeviceAgent(*logDeviceId); agent != nil {
-		return agent.addUNILogicalPort(ctx, childDevice)
+		if err := agent.addUNILogicalPort(ctx, childDevice); err != nil {
+			return err
+		}
+		// Update the device routes - let it run in its own go routine as it can take time
+		go agent.updateRoutes()
 	}
 	return status.Errorf(codes.NotFound, "%s", childDevice.Id)
 }