Skip to content

Commit

Permalink
Platform Driver Developement Framework (PDDF) (sonic-net#4756)
Browse files Browse the repository at this point in the history
This change introduces PDDF which is described here: sonic-net/SONiC#536

Most of the platform bring up effort goes in developing the platform device drivers, SONiC platform APIs and validating them. Typically each platform vendor writes their own drivers and platform APIs which is very tailor made to that platform. This involves writing code, building, installing it on the target platform devices and testing. Many of the details of the platform are hard coded into these drivers, from the HW spec. They go through this cycle repetitively till everything works fine, and is validated before upstreaming the code.
PDDF aims to make this platform driver and platform APIs development process much simpler by providing a data driven development framework. This is enabled by:

JSON descriptor files for platform data
Generic data-driven drivers for various devices
Generic SONiC platform APIs
Vendor specific extensions for customisation and extensibility

Signed-off-by: Fuzail Khan <fuzail.khan@broadcom.com>
  • Loading branch information
FuzailBrcm authored and santhosh-kt committed Feb 25, 2021
1 parent a1de279 commit c94265d
Show file tree
Hide file tree
Showing 112 changed files with 18,064 additions and 1 deletion.
1 change: 1 addition & 0 deletions build_debian.sh
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
python \
python-setuptools \
python3-setuptools \
python-jsonschema \
python-apt \
traceroute \
iputils-ping \
Expand Down
27 changes: 27 additions & 0 deletions device/common/pddf/plugins/eeprom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python

try:
import os
import sys
import json
sys.path.append('/usr/share/sonic/platform/plugins')
import pddfparse
#from sonic_eeprom import eeprom_base
from sonic_eeprom import eeprom_tlvinfo
except ImportError, e:
raise ImportError (str(e) + "- required module not found")


class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
global pddf_obj
global plugin_data
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
plugin_data = json.load(pd)

pddf_obj = pddfparse.PddfParse()
# system EEPROM always has device name EEPROM1
self.eeprom_path = pddf_obj.get_path("EEPROM1", "eeprom")
super(board, self).__init__(self.eeprom_path, 0, '', True)

202 changes: 202 additions & 0 deletions device/common/pddf/plugins/fanutil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
#!/usr/bin/env python


# Sample pddf_fanutil file
# All the supported FAN SysFS aattributes are
#- fan<idx>_present
#- fan<idx>_direction
#- fan<idx>_input
#- fan<idx>_pwm
#- fan<idx>_fault
# where idx is in the range [1-12]
#


import os.path
import sys
sys.path.append('/usr/share/sonic/platform/plugins')
import pddfparse
import json

try:
from sonic_fan.fan_base import FanBase
except ImportError as e:
raise ImportError (str(e) + "- required module not found")

class FanUtil(FanBase):
"""PDDF generic FAN util class"""

def __init__(self):
FanBase.__init__(self)
global pddf_obj
global plugin_data
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
plugin_data = json.load(pd)

pddf_obj = pddfparse.PddfParse()
self.platform = pddf_obj.get_platform()

self.num_fans = (self.platform['num_fantrays'] * self.platform['num_fans_pertray'] )

def get_num_fans(self):
return self.num_fans

def get_presence(self, idx):
# 1 based fan index
if idx<1 or idx>self.num_fans:
print "Invalid fan index %d\n"%idx
return False

attr_name = "fan"+ str(idx) +"_present"
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr_name)
if not output:
return False

mode = output['mode']
presence = output['status'].rstrip()

vmap = plugin_data['FAN']['present'][mode]['valmap']

if presence in vmap:
status = vmap[presence]
else:
status = False

return status

def get_status(self, idx):
# 1 based fan index
if idx<1 or idx>self.num_fans:
print "Invalid fan index %d\n"%idx
return False

speed = self.get_speed(idx)
status = True if (speed != 0) else False
return status

def get_direction(self, idx):
# 1 based fan index
if idx<1 or idx>self.num_fans:
print "Invalid fan index %d\n"%idx
return None

attr = "fan" + str(idx) + "_direction"
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
if not output:
return None

mode = output['mode']
val = output['status']

val = val.rstrip()
vmap = plugin_data['FAN']['direction'][mode]['valmap']


if val in vmap:
direction = vmap[val]
else:
direction = val

return direction

def get_directions(self):
num_fan = self.get_num_fan();

for i in range(1, num_fan+1):
attr = "fan" + str(i) + "_direction"
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
if not output:
return None

mode = output['mode']
val = output['status']

val = val.rstrip()
vmap = plugin_data['FAN']['direction'][mode]['valmap']

direction = vmap[str(val)]

print "FAN-%d direction is %s"%(i, direction)

return 0

def get_speed(self, idx):
# 1 based fan index
if idx<1 or idx>self.num_fans:
print "Invalid fan index %d\n"%idx
return 0

attr = "fan" + str(idx) + "_input"
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
if not output:
return 0

#mode = output['mode']
val = output['status'].rstrip()

if val.isalpha():
return 0
else:
rpm_speed = int(float(val))

return rpm_speed

def get_speeds(self):
num_fan = self.get_num_fan();
ret = "FAN_INDEX\t\tRPM\n"

for i in range(1, num_fan+1):
attr1 = "fan" + str(i) + "_input"
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr1)
if not output:
return ""

#mode = output['mode']
val = output['status'].rstrip()

if val.isalpha():
frpm = 0
else:
frpm = int(val)

ret += "FAN-%d\t\t\t%d\n"%(i, frpm)

return ret

def set_speed(self, val):
if val<0 or val>100:
print "Error: Invalid speed %d. Please provide a valid speed percentage"%val
return False

num_fan = self.num_fans
if 'duty_cycle_to_pwm' not in plugin_data['FAN']:
print "Setting fan speed is not allowed !"
return False
else:
duty_cycle_to_pwm = eval(plugin_data['FAN']['duty_cycle_to_pwm'])
pwm = duty_cycle_to_pwm(val)
print "New Speed: %d%% - PWM value to be set is %d\n"%(val,pwm)

for i in range(1, num_fan+1):
attr = "fan" + str(i) + "_pwm"
node = pddf_obj.get_path("FAN-CTRL", attr)
if node is None:
return False
try:
with open(node, 'w') as f:
f.write(str(pwm))
except IOError:
return False

return True

def dump_sysfs(self):
return pddf_obj.cli_dump_dsysfs('fan')

def get_change_event(self):
"""
TODO: This function need to be implemented
when decide to support monitoring FAN(fand)
on this platform.
"""
raise NotImplementedError
58 changes: 58 additions & 0 deletions device/common/pddf/plugins/ledutil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python

import sys
sys.path.append('/usr/share/sonic/platform/plugins')
import pddfparse

class LedUtil:
color_map = {
"STATUS_LED_COLOR_GREEN" : "on",
"STATUS_LED_COLOR_RED" : "faulty",
"STATUS_LED_COLOR_OFF" : "off"
}

def __init__(self):
global pddf_obj
pddf_obj = pddfparse.PddfParse()
self.path="pddf/devices/led"
self.cur_state_path="pddf/devices/led/cur_state"

def set_status_led(self, led_device_name, color, color_state="SOLID"):
if (not led_device_name in pddf_obj.data.keys()):
status="ERROR: " + led_device_name + " is not configured"
return (status)

if (not color in self.color_map.keys()):
status="ERROR: Invalid color"
return (status)

index=pddf_obj.data[led_device_name]['dev_attr']['index']
pddf_obj.create_attr('device_name', led_device_name, self.path)
pddf_obj.create_attr('index', index, self.path)
pddf_obj.create_attr('color', self.color_map[color], self.cur_state_path)
pddf_obj.create_attr('color_state', color_state, self.cur_state_path)
pddf_obj.create_attr('dev_ops', 'set_status', self.path)
return ("Executed")

def get_status_led(self, led_device_name):
if (not led_device_name in pddf_obj.data.keys()):
status="ERROR: " + led_device_name + " is not configured"
return (status)

index=pddf_obj.data[led_device_name]['dev_attr']['index']
pddf_obj.create_attr('device_name', led_device_name, self.path)
pddf_obj.create_attr('index', index, self.path)
pddf_obj.create_attr('dev_ops', 'get_status', self.path)
color_f="/sys/kernel/" + self.cur_state_path +"/color"
color_state_f="/sys/kernel/" + self.cur_state_path +"/color_state"

try:
with open(color_f, 'r') as f:
color = f.read().strip("\r\n")
with open(color_state_f, 'r') as f:
color_state = f.read().strip("\r\n")
except IOError:
status="ERROR :" + color_f + " open failed"
return (status)
status = "%s-%s:\t%s %s\n"%(led_device_name, index, color, color_state)
return (status)
Loading

0 comments on commit c94265d

Please sign in to comment.