VOL-1793: Set device mac address/dpid to unique value
Use openolt.proto provided DeviceId if available, otherwise
derive from IP address/hostname similar to voltha 1.x
Change-Id: Ieb5322b9087554b2466696c701a8a0a7acd2437f
diff --git a/adaptercore/device_handler.go b/adaptercore/device_handler.go
index 20701ab..b085177 100644
--- a/adaptercore/device_handler.go
+++ b/adaptercore/device_handler.go
@@ -23,6 +23,7 @@
"fmt"
"google.golang.org/grpc/codes"
"io"
+ "net"
"strconv"
"strings"
"sync"
@@ -131,6 +132,47 @@
log.Debug("device-agent-stopped")
}
+func macifyIP(ip net.IP) string {
+ if len(ip) > 0 {
+ oct1 := strconv.FormatInt(int64(ip[12]), 16)
+ oct2 := strconv.FormatInt(int64(ip[13]), 16)
+ oct3 := strconv.FormatInt(int64(ip[14]), 16)
+ oct4 := strconv.FormatInt(int64(ip[15]), 16)
+ return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
+ }
+ return ""
+}
+
+func generateMacFromHost(host string) (string, error) {
+ var genmac string
+ var addr net.IP
+ var ips []string
+ var err error
+
+ log.Debugw("generating-mac-from-host", log.Fields{"host": host})
+
+ if addr = net.ParseIP(host); addr == nil {
+ log.Debugw("looking-up-hostname", log.Fields{"host": host})
+
+ if ips, err = net.LookupHost(host); err == nil {
+ log.Debugw("dns-result-ips", log.Fields{"ips": ips})
+ if addr = net.ParseIP(ips[0]); addr == nil {
+ log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
+ return "", errors.New("unable-to-parse-ip")
+ }
+ genmac = macifyIP(addr)
+ log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
+ return genmac, nil
+ }
+ log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
+ return "", err
+ }
+
+ genmac = macifyIP(addr)
+ log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
+ return genmac, nil
+}
+
func macAddressToUint32Array(mac string) []uint32 {
slist := strings.Split(mac, ":")
result := make([]uint32, len(slist))
@@ -419,29 +461,11 @@
return nil
}
- deviceInfo, err := dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
+ deviceInfo, err := dh.populateDeviceInfo()
if err != nil {
- log.Errorw("Failed to fetch device info", log.Fields{"err": err})
+ log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
return err
}
- if deviceInfo == nil {
- log.Errorw("Device info is nil", log.Fields{})
- return errors.New("failed to get device info from OLT")
- }
- log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
- dh.device.Root = true
- dh.device.Vendor = deviceInfo.Vendor
- dh.device.Model = deviceInfo.Model
- dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
- dh.device.HardwareVersion = deviceInfo.HardwareVersion
- dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
- // FIXME: Remove Hardcodings
- dh.device.MacAddress = "0a:0b:0c:0d:0e:0f"
-
- // Synchronous call to update device - this method is run in its own go routine
- if er := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); er != nil {
- log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": er})
- }
device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
if err != nil || device == nil {
@@ -477,6 +501,51 @@
return nil
}
+func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
+ var err error
+ var deviceInfo *oop.DeviceInfo
+
+ deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
+
+ if err != nil {
+ log.Errorw("Failed to fetch device info", log.Fields{"err": err})
+ return nil, err
+ }
+ if deviceInfo == nil {
+ log.Errorw("Device info is nil", log.Fields{})
+ return nil, errors.New("failed to get device info from OLT")
+ }
+
+ log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
+ dh.device.Root = true
+ dh.device.Vendor = deviceInfo.Vendor
+ dh.device.Model = deviceInfo.Model
+ dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
+ dh.device.HardwareVersion = deviceInfo.HardwareVersion
+ dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
+
+ if deviceInfo.DeviceId == "" {
+ log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
+ host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
+ genmac, err := generateMacFromHost(host)
+ if err != nil {
+ return nil, err
+ }
+ log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
+ dh.device.MacAddress = genmac
+ } else {
+ dh.device.MacAddress = deviceInfo.DeviceId
+ }
+
+ // Synchronous call to update device - this method is run in its own go routine
+ if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
+ log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
+ return nil, err
+ }
+
+ return deviceInfo, nil
+}
+
//AdoptDevice adopts the OLT device
func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
dh.transitionMap = NewTransitionMap(dh)