From 1c34a6289060f312f806c81dc74bee056ee32573 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Fri, 12 Mar 2021 02:30:45 +0000 Subject: [PATCH 01/14] initial draft for Y cable Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 225 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 doc/y_cable/design_doc.md diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md new file mode 100644 index 0000000000..eace290345 --- /dev/null +++ b/doc/y_cable/design_doc.md @@ -0,0 +1,225 @@ +## Multiple y cable vendor API design + +### Overview + +This document summarizes the approach taken to accommodate multiple +Y cable vendors in Gemini Project. All the design choices are presented +such that vendors can implement the Y cable interface with ease and effeciency +and all the feature requirements are met. + + +Challenge: to provide an interface for Y cable to interact with PMON docker and HOST + which can be uniform across all vendors. + +### Directory Structure + +#### Background + +- We need to have an appropriate place where vendors can implement their modules/packages and provide Sonic with an abstraction layer where pmon and host can access the Y cable packages of all the vendors with ease + + - Currently the assumption is Y cable package implementation would be in python itself + - If a vendor provides shared library, that scenario would be considered accordingly + - Since sonic_y_cable (sonic-platform-common/sonic_y_cable) is already built as a package today (only for a single Y cable vendor with sonic-buildimage) vendors can also build packages along similar lines. + +#### Proposed Solution + +- Vendors can place their implementations in this format + +``` + Sonic_platform_common/sonic_y_cable//y_cable.py +``` +- For sxample + +``` + Sonic_platform_common/sonic_y_cable/credo/y_cable.py +``` +#### Rationale +- The requirement here would be that the vendors must create their packages such that It can easily be accessed/imported and the packages also adhere to a uniform convention + + - Vendor name should be derivable from the vendor name field inside the register spec of transceiver type. + - This is essential so that host/pmon can determine the vendor name from eeprom and import the module of the transceiver appropriately + +### Vendor to Module mapping + +#### Background + +- We need to have a vendor to Y cable module mappings defined and accessible somewhere for pmon/cli to import + + - Before calling any Y cable API, how do we know which type/vendor does the Y cable belong to ? + - Also lets suppose once the type/vendor of the cable is known from where does pmon or cli import the module ? + - Since there can be many specs which vendors follow (8636, 8624 etc.) for transceivers it is important to have a solution which meets all requirements so that the API access is available to whoever wants to invoke it. + - another issue is how do we support the multiple vendors modules/packages which could be used by both sonic pmon docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. +#### Proposed Solution + +- We define a file which would contain vendor to module mapping and put it in a place which is accessible to both pmon and host +- The vendor to module mapping can be present in a file which could be present in + +``` + /usr/share/sonic/y_cable/y_cable_vendor_mapping.csv +``` +or + +``` + /usr/share/sonic/y_cable/y_cable_vendor_mapping.yaml +``` +- Mapping could be such that +``` + ,, +``` +- For example +``` + Credo,credo,y_cable +``` + +#### Rationale + + - This is because both the container and host can easily access this path. And it would be easy to mount this on container (pmon) as applicable. + - Also since python has built in support for both csv and yaml parsing, it would be convenient to retrieve the mappings. + +#### Implementation details +- Once the xcvrd will start (daemon launched) it will know the Vendor name from the register specification and then it can appropriately read and parse the vendor name from the spec. Once it has this information it can then using this file Load/import the appropriate module. + +### Port to module mapping +- Another thing that is required is once we do have a vendor to module mapping, we need to map appropriate port to a module as well + +#### Background + + - Basically, the key idea is once we have a port identified as being of a certain vendor and it has been identified to load a certain module which we can gather from the mapping described above we still need to call the correct module on each port each time we call the API on the port + - want to maintain this mapping in memory since xcvrd does not want to read/parse this y_cable_vendor_mapping.csv file again and again each time we call the y cable API + - Also note that the module loaded might change during xcvrd running lifetime since cable can be changed from one vendor to another. So we need to take this into consideration as well + +#### Proposed Solution + + - Each module of the Y cable vendor can be a class (of each transceiver type) and all we need to do is instantiate the objects of these classes as class instances and these objects will provide the interface of calling the API's for the appropriate vendor Y cable. + - This instantiation will be done inside xcvrd, when xcvrd starts + - These objects basically emulate Y cable instances and whatever action/interaction needs to be done with the Ycable the methods of these objects would provide that + - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the y cable. + - If the vendor does not support or implement the utility, it will just raise a not implemented error from the base class itself + +For example a typical module of the vendor can be like this +``` + + class Ycable(Ycablebase): + #all vendor modules inherit from Ycablebase + def __init__(self): + + def toggle_mux_to_torA(self, port): + #implement or raise exception if not implemented + raise NotImplementedError + def toggle_mux_to_torB(self, port): + #implement or raise exception if not implemented + raise NotImplementedError + + def check_prbs(self, port): + #implement or raise exception if not implemented + raise NotImplementedError + + def only_credo(self, port): + raise NotImplementedError + + def only_amphenol(self, port): + raise NotImplementedError + +``` +the base class would be like this + +``` + class Ycablebase(object): + def __init__(self, port): + self.port = port + + def toggle_mux_to_torA(self, port): + raise NotImplementedError + def toggle_mux_to_torB(self, port): + raise NotImplementedError + + def check_prbs(self, port): + raise NotImplementedError + + def only_credo(self, port): + raise NotImplementedError + + def only_amphenol(self, port): + raise NotImplementedError + +``` + +#### Implementation details +- Now for xcvrd to use this solution, all it has to do is instantiate the class objects defined by importing the appropriate module. This should happen when xcvrd starts or if there is a change event (xcvrd inserted/removed) + +``` + from credo import y_cable + y_cable_port_Ethernet0 = Ycable(port) + + + + # and to use the Y cable APIS + try: + y_cable_port_etherne0.toggle_mux_to_torA() + except: + helper_logger.log(not able to toggle_mux_to_torA) +``` +#### Rationale + + - xcvrd can maintain a dict of these objects an whenever it needs to call the API for the correct port (in this case physical port) it can easily achieve so by indexing into the instance of the physical port and calling the class object. + +``` + + Y_cable_ports_instances = {} + + # appending instances in the dictionary + Y_cable_ports_instances[physical_port] = Ycable(port) + + # and to use the Y cable APIS + try: + Y_cable_ports_instances[physical_port].toggle_mux_to_torA() + except: + helper_logger.log(not able to toggle_mux_to_torA) +``` + + +### How does cli interact with Y cable api's +- Another thing that is required is once we do have a vendor to module mapping, we need to map appropriate port to a module as well + +#### Background + + - Another requirement we have is Cli also requires to interact with the Ycable directly. This basically implies that all Ycable vendor packages needs to be imported inside sonic-utilities/host as well + - This would come in the form of commands like setting PRBS, enabling disabling loopback and also get the BER info and EYE info etc + - Also commands such as config/show hwmode is important which gives the cli ability to toggle the mux without going into sonic modules like mux-mgr or orchagent. + - All these require access to Y cable APIs to be directly called by the cli. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc + +#### Proposed Solution(s) + + - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into vendor to module mapping file and then load the module and execute the API + - Another way is cli can interact with pmon thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the y cable. + +``` + HW_MUX_OPERATION_TABLE|Ethernet0 + state active/standby + enable_prbs true/false + check_mux_direction true/false +``` + - In xcvrd we can have a thread running and listening to these events and execute the APIs since all the ports already have the correct mapping of the module (maintained in the form of a dictionary). The response of the API can be again written back to the redis table and absorbed by the CLI + +### Concurrency for Y cables API + +#### Background + + - Since some vendors need to execute two or three transactions in a single API it is imperative to have a solution where we can protect the Y cable APIs for concurrent behavior + +#### Proposed Solution(s) + + - We might need to pass a semaphore or lock to the API to protect reexecuting or executing some other API in the meantime. + - For now we insist on vendors to acquire/release locks in the API/implementation itself. So that if there is any possibility of concurrency the locking mechanism inside the the API prevents that from happening + + +### Storing the state within a Y cable Module + +#### Background + + - Another requirement in future that could arise is what if we need a feature which requires vendors to store a state with the Y cable. In this regard it is important to address this requirement in the initial design itself. (example port to bus mapping) + +#### Proposed Solution(s) + + - Since the vendor has class definitions associated with Y cable module, it can have attributes which store the information. However, it still needs to be decided how these attributes will be instantiated/configured. Whether this onus will be on xcvrd/daemon or whether it can be done within the module itself. + From 230e793dbc88fe2238fc0f05f5e8fde46c2ae0e6 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Fri, 12 Mar 2021 04:58:34 +0000 Subject: [PATCH 02/14] fixing with suggestion Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index eace290345..89e75dc3a1 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -3,7 +3,8 @@ ### Overview This document summarizes the approach taken to accommodate multiple -Y cable vendors in Gemini Project. All the design choices are presented +Y cable vendors for supporting dual-ToR configurations in SONiC. +All the design choices are presented such that vendors can implement the Y cable interface with ease and effeciency and all the feature requirements are met. From 5b19c157f4a498f6e6cf12c474c0c602a04fdb9b Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Tue, 23 Mar 2021 13:27:22 +0000 Subject: [PATCH 03/14] fix comments Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 142 +++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 64 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index 89e75dc3a1..e34c8de65f 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -1,5 +1,13 @@ ## Multiple y cable vendor API design +## Revision + +| Rev | Date | Author | Change Description | +|:---:|:--------:|:---------------:|--------------------| +| 0.1 | 03/22/21 | Vaibhav Dahiya | Initial version | + +## Scope + ### Overview This document summarizes the approach taken to accommodate multiple @@ -12,81 +20,87 @@ and all the feature requirements are met. Challenge: to provide an interface for Y cable to interact with PMON docker and HOST which can be uniform across all vendors. -### Directory Structure + +### Vendor to Module mapping #### Background -- We need to have an appropriate place where vendors can implement their modules/packages and provide Sonic with an abstraction layer where pmon and host can access the Y cable packages of all the vendors with ease - - - Currently the assumption is Y cable package implementation would be in python itself - - If a vendor provides shared library, that scenario would be considered accordingly - - Since sonic_y_cable (sonic-platform-common/sonic_y_cable) is already built as a package today (only for a single Y cable vendor with sonic-buildimage) vendors can also build packages along similar lines. +- We need to have a vendor to Y cable module mappings defined and accessible somewhere for PMon container/cli to import + - Before calling any Y cable API, how do we know which type/vendor does the Y cable belong to ? + - Also lets suppose once the type/vendor of the cable is known from where does PMon container or cli import the module ? + - Since there can be many specs which vendors follow (8636, 8624 etc.) for transceivers it is important to have a solution which meets all requirements so that the API access is available to whoever wants to invoke it. + - another issue is how do we support the multiple vendors modules/packages which could be used by both SONiC PMon container docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. #### Proposed Solution -- Vendors can place their implementations in this format +- We define a file which would contain vendor to module mapping and put it in a place which is accessible to both PMon container and host +- The vendor to module mapping can be present in a file which could be present in sonic_platform_common +- It makes sense to keep the mapping file in the sonic_y_cable package so that it can be updated in the same pull request when a vendor adds a new cable implementation. However, we cannot install data files outside of the Python directory via a wheel. Considering this we propose to make this a Python file which simply contains a 2D dictionary which can be used to look up the module path. If the file is part of the sonic_y_cable package, it will be installed in both the PMon container and the host +For example ``` - Sonic_platform_common/sonic_y_cable//y_cable.py + /sonic_platform_common/sonic_y_cable/y_cable_vendor_mapping.py ``` -- For sxample +Vendors can have several implementations/ways to use this concept +- Vendor has a 1:1 mapping between model and Python file +- Vendor has one Python file which supports all models +- A combination of the above + +- Mapping could be such that its a dictionary in 2D ``` - Sonic_platform_common/sonic_y_cable/credo/y_cable.py + , + ,, +``` +- For example ``` + Credo,credo_model1,y_cable.py + Credo,y_cable.py +``` + #### Rationale -- The requirement here would be that the vendors must create their packages such that It can easily be accessed/imported and the packages also adhere to a uniform convention - - Vendor name should be derivable from the vendor name field inside the register spec of transceiver type. - - This is essential so that host/pmon can determine the vendor name from eeprom and import the module of the transceiver appropriately + - This is because both the container and host can easily access this path. And it would be easy to mount this on container (PMon container) as applicable. -### Vendor to Module mapping +#### Implementation details +- Once the xcvrd will start (daemon launched) it will know the Vendor name from the register specification and then it can appropriately read and parse the vendor name from the spec. Once it has this information it can then using this file Load/import the appropriate module. + +### Directory Structure #### Background -- We need to have a vendor to Y cable module mappings defined and accessible somewhere for pmon/cli to import - - - Before calling any Y cable API, how do we know which type/vendor does the Y cable belong to ? - - Also lets suppose once the type/vendor of the cable is known from where does pmon or cli import the module ? - - Since there can be many specs which vendors follow (8636, 8624 etc.) for transceivers it is important to have a solution which meets all requirements so that the API access is available to whoever wants to invoke it. - - another issue is how do we support the multiple vendors modules/packages which could be used by both sonic pmon docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. -#### Proposed Solution +- We need to have an appropriate place where vendors can implement their modules and provide SONiC with an abstraction layer where PMon container and host can access the Y cable packages of all the vendors with ease -- We define a file which would contain vendor to module mapping and put it in a place which is accessible to both pmon and host -- The vendor to module mapping can be present in a file which could be present in + - Currently the assumption is Y-cable API will be written in the Python language + - If a vendor has an existing library in a different language, they will need to either find a way to wrap/bind it in Python to align with the description below or (preferrably) provide a pure Python implementation + - Since sonic_y_cable (sonic-platform-common/sonic_y_cable) is already built as a package today (only for a single Y cable vendor with sonic-buildimage) vendors can also place their implementation in this directory itself. -``` - /usr/share/sonic/y_cable/y_cable_vendor_mapping.csv -``` -or +#### Proposed Solution + +- Vendors can place their implementations in this format ``` - /usr/share/sonic/y_cable/y_cable_vendor_mapping.yaml -``` -- Mapping could be such that -``` - ,, + sonic_platform_common/sonic_y_cable//y_cable.py ``` - For example + ``` - Credo,credo,y_cable + sonic_platform_common/sonic_y_cable/credo/y_cable.py ``` - #### Rationale +- The requirement here would be that the vendors must create their modules such that It can easily be accessed/imported and the modules also adhere to a uniform convention - - This is because both the container and host can easily access this path. And it would be easy to mount this on container (pmon) as applicable. - - Also since python has built in support for both csv and yaml parsing, it would be convenient to retrieve the mappings. + - Vendor name should be derivable from the vendor name field inside the register spec of transceiver type. + - This is essential so that host/PMon container can determine the vendor name from eeprom and import the module of the transceiver appropriately -#### Implementation details -- Once the xcvrd will start (daemon launched) it will know the Vendor name from the register specification and then it can appropriately read and parse the vendor name from the spec. Once it has this information it can then using this file Load/import the appropriate module. ### Port to module mapping - Another thing that is required is once we do have a vendor to module mapping, we need to map appropriate port to a module as well #### Background - - Basically, the key idea is once we have a port identified as being of a certain vendor and it has been identified to load a certain module which we can gather from the mapping described above we still need to call the correct module on each port each time we call the API on the port - - want to maintain this mapping in memory since xcvrd does not want to read/parse this y_cable_vendor_mapping.csv file again and again each time we call the y cable API + - Basically, the key idea is once we have a port identified as being of a certain vendor and it has been identified to load a certain module which we can gather from the mapping described above we still need to call the correct module on each port each time we call the API on the port + - want to maintain this mapping in memory since xcvrd does not want to read/parse this y_cable_vendor_mapping.csv file again and again each time we call the y cable API - Also note that the module loaded might change during xcvrd running lifetime since cable can be changed from one vendor to another. So we need to take this into consideration as well #### Proposed Solution @@ -99,11 +113,11 @@ or For example a typical module of the vendor can be like this ``` - + class Ycable(Ycablebase): #all vendor modules inherit from Ycablebase def __init__(self): - + def toggle_mux_to_torA(self, port): #implement or raise exception if not implemented raise NotImplementedError @@ -120,15 +134,15 @@ For example a typical module of the vendor can be like this def only_amphenol(self, port): raise NotImplementedError - + ``` -the base class would be like this +the base class would be like this -``` +``` class Ycablebase(object): def __init__(self, port): self.port = port - + def toggle_mux_to_torA(self, port): raise NotImplementedError def toggle_mux_to_torB(self, port): @@ -154,7 +168,7 @@ the base class would be like this - # and to use the Y cable APIS + # and to use the Y cable APIS try: y_cable_port_etherne0.toggle_mux_to_torA() except: @@ -162,16 +176,16 @@ the base class would be like this ``` #### Rationale - - xcvrd can maintain a dict of these objects an whenever it needs to call the API for the correct port (in this case physical port) it can easily achieve so by indexing into the instance of the physical port and calling the class object. + - xcvrd can maintain a dict of these objects an whenever it needs to call the API for the correct port (in this case physical port) it can easily achieve so by indexing into the instance of the physical port and calling the class object. ``` - Y_cable_ports_instances = {} - - # appending instances in the dictionary + Y_cable_ports_instances = {} + + # appending instances in the dictionary Y_cable_ports_instances[physical_port] = Ycable(port) - # and to use the Y cable APIS + # and to use the Y cable APIS try: Y_cable_ports_instances[physical_port].toggle_mux_to_torA() except: @@ -184,15 +198,15 @@ the base class would be like this #### Background - - Another requirement we have is Cli also requires to interact with the Ycable directly. This basically implies that all Ycable vendor packages needs to be imported inside sonic-utilities/host as well - - This would come in the form of commands like setting PRBS, enabling disabling loopback and also get the BER info and EYE info etc - - Also commands such as config/show hwmode is important which gives the cli ability to toggle the mux without going into sonic modules like mux-mgr or orchagent. - - All these require access to Y cable APIs to be directly called by the cli. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc + - Another requirement we have is Cli also requires to interact with the Ycable directly. This basically implies that all Ycable vendor packages needs to be imported inside SONiC-utilities/host as well + - This would come in the form of commands like setting PRBS, enabling disabling loopback and also get the BER info and EYE info etc + - Also commands such as config/show hwmode is important which gives the cli ability to toggle the mux without going into SONiC modules like mux-mgr or orchagent. + - All these require access to Y cable APIs to be directly called by the cli. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc #### Proposed Solution(s) - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into vendor to module mapping file and then load the module and execute the API - - Another way is cli can interact with pmon thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the y cable. + - Another way is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the y cable. ``` HW_MUX_OPERATION_TABLE|Ethernet0 @@ -201,26 +215,26 @@ the base class would be like this check_mux_direction true/false ``` - In xcvrd we can have a thread running and listening to these events and execute the APIs since all the ports already have the correct mapping of the module (maintained in the form of a dictionary). The response of the API can be again written back to the redis table and absorbed by the CLI - -### Concurrency for Y cables API + +### Concurrency for Y cables API #### Background - - Since some vendors need to execute two or three transactions in a single API it is imperative to have a solution where we can protect the Y cable APIs for concurrent behavior + - Since some vendors need to execute two or three transactions in a single API it is imperative to have a solution where we can protect the Y cable APIs for concurrent behavior #### Proposed Solution(s) - We might need to pass a semaphore or lock to the API to protect reexecuting or executing some other API in the meantime. - For now we insist on vendors to acquire/release locks in the API/implementation itself. So that if there is any possibility of concurrency the locking mechanism inside the the API prevents that from happening - -### Storing the state within a Y cable Module + +### Storing the state within a Y cable Module #### Background - - Another requirement in future that could arise is what if we need a feature which requires vendors to store a state with the Y cable. In this regard it is important to address this requirement in the initial design itself. (example port to bus mapping) + - Another requirement in future that could arise is what if we need a feature which requires vendors to store a state with the Y cable. In this regard it is important to address this requirement in the initial design itself. (example port to bus mapping) #### Proposed Solution(s) - - Since the vendor has class definitions associated with Y cable module, it can have attributes which store the information. However, it still needs to be decided how these attributes will be instantiated/configured. Whether this onus will be on xcvrd/daemon or whether it can be done within the module itself. + - Since the vendor has class definitions associated with Y cable module, it can have attributes which store the information. However, it still needs to be decided how these attributes will be instantiated/configured. Whether this onus will be on xcvrd/daemon or whether it can be done within the module itself. From 92870a6fb4adba82290b50033bc4d23d63814c54 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Tue, 23 Mar 2021 22:08:17 +0000 Subject: [PATCH 04/14] fix comments Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index e34c8de65f..b65011b229 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -1,4 +1,4 @@ -## Multiple y cable vendor API design +## Multiple Y-cable vendor API design ## Revision @@ -31,6 +31,7 @@ Challenge: to provide an interface for Y cable to interact with PMON docker and - Also lets suppose once the type/vendor of the cable is known from where does PMon container or cli import the module ? - Since there can be many specs which vendors follow (8636, 8624 etc.) for transceivers it is important to have a solution which meets all requirements so that the API access is available to whoever wants to invoke it. - another issue is how do we support the multiple vendors modules/packages which could be used by both SONiC PMon container docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. + #### Proposed Solution - We define a file which would contain vendor to module mapping and put it in a place which is accessible to both PMon container and host @@ -48,6 +49,9 @@ Vendors can have several implementations/ways to use this concept - A combination of the above - Mapping could be such that its a dictionary in 2D + +For example + ``` , ,, @@ -100,7 +104,7 @@ Vendors can have several implementations/ways to use this concept #### Background - Basically, the key idea is once we have a port identified as being of a certain vendor and it has been identified to load a certain module which we can gather from the mapping described above we still need to call the correct module on each port each time we call the API on the port - - want to maintain this mapping in memory since xcvrd does not want to read/parse this y_cable_vendor_mapping.csv file again and again each time we call the y cable API + - want to maintain this mapping in memory since xcvrd does not want to read/parse this y_cable_vendor_mapping.csv file again and again each time we call the Y-cable API - Also note that the module loaded might change during xcvrd running lifetime since cable can be changed from one vendor to another. So we need to take this into consideration as well #### Proposed Solution @@ -108,7 +112,7 @@ Vendors can have several implementations/ways to use this concept - Each module of the Y cable vendor can be a class (of each transceiver type) and all we need to do is instantiate the objects of these classes as class instances and these objects will provide the interface of calling the API's for the appropriate vendor Y cable. - This instantiation will be done inside xcvrd, when xcvrd starts - These objects basically emulate Y cable instances and whatever action/interaction needs to be done with the Ycable the methods of these objects would provide that - - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the y cable. + - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the Y-cable. - If the vendor does not support or implement the utility, it will just raise a not implemented error from the base class itself For example a typical module of the vendor can be like this @@ -206,7 +210,7 @@ the base class would be like this #### Proposed Solution(s) - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into vendor to module mapping file and then load the module and execute the API - - Another way is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the y cable. + - Another way is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-cable. ``` HW_MUX_OPERATION_TABLE|Ethernet0 From 4bf24b6ecd461359b9b9bf0ee98baaa75f951a79 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Wed, 24 Mar 2021 12:46:06 +0000 Subject: [PATCH 05/14] fixing suggestions Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index b65011b229..b3534d3d20 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -18,19 +18,21 @@ and all the feature requirements are met. Challenge: to provide an interface for Y cable to interact with PMON docker and HOST - which can be uniform across all vendors. + which can be uniform across all vendors. As part of this refactor, we will + be moving towards a model where only xcvrd interacts with the cables/transceivers, + and host-side processes will communicate with xcvrd rather than with the devices directly ### Vendor to Module mapping #### Background -- We need to have a vendor to Y cable module mappings defined and accessible somewhere for PMon container/cli to import +- We need to have a vendor to corresponding Y cable module mappings defined and accessible somewhere for PMon container to import - Before calling any Y cable API, how do we know which type/vendor does the Y cable belong to ? - Also lets suppose once the type/vendor of the cable is known from where does PMon container or cli import the module ? - Since there can be many specs which vendors follow (8636, 8624 etc.) for transceivers it is important to have a solution which meets all requirements so that the API access is available to whoever wants to invoke it. - - another issue is how do we support the multiple vendors modules/packages which could be used by both SONiC PMon container docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. + - another issue is how do we support the multiple vendors modules/packages which could be used by both SONiC PMon container docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. Although we are moving towards a model where cli should not need to import Y cable modules but it is still preferred have it accessible #### Proposed Solution @@ -50,24 +52,24 @@ Vendors can have several implementations/ways to use this concept - Mapping could be such that its a dictionary in 2D -For example ``` - , - ,, + {: {}, + : {:}} ``` - For example ``` - Credo,credo_model1,y_cable.py - Credo,y_cable.py + {"Credo" : {"model1": "y_cable.py"}, + "Amphenol" : {"model_a": "y_cable_a.py", "model_b":"y_cable_b.py"}} ``` #### Rationale - This is because both the container and host can easily access this path. And it would be easy to mount this on container (PMon container) as applicable. + - The sonic_y_cable package is installed in both host and pmon #### Implementation details -- Once the xcvrd will start (daemon launched) it will know the Vendor name from the register specification and then it can appropriately read and parse the vendor name from the spec. Once it has this information it can then using this file Load/import the appropriate module. +- Once the xcvrd will start (daemon launched) it will know the Vendor name from the register specification and then it can appropriately read and parse the vendor name from the spec. Once it has this information it can then using this file to Load/import the appropriate module. ### Directory Structure @@ -210,8 +212,9 @@ the base class would be like this #### Proposed Solution(s) - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into vendor to module mapping file and then load the module and execute the API - - Another way is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-cable. + - The more preferred approach here is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-cable. +Exanple table and operations ``` HW_MUX_OPERATION_TABLE|Ethernet0 state active/standby From 935b8603bfbbd8fcf713e4eebe9bd88600392810 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Wed, 24 Mar 2021 23:28:39 +0000 Subject: [PATCH 06/14] fix comment Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index b3534d3d20..ac9af3f5e3 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -69,7 +69,7 @@ Vendors can have several implementations/ways to use this concept - The sonic_y_cable package is installed in both host and pmon #### Implementation details -- Once the xcvrd will start (daemon launched) it will know the Vendor name from the register specification and then it can appropriately read and parse the vendor name from the spec. Once it has this information it can then using this file to Load/import the appropriate module. +- Once the xcvrd will start (daemon launched) or tranceiver is connected (plugged in), in both cases xcvrd can determine the Vendor name and part number from the register specification and then it can appropriately read and parse the vendor name and part number from the spec using eeprom. Once it has this information it can then use this file to Load/import the appropriate module. ### Directory Structure From 469a49cad9af9ed1c3cd3a129e463aef5a89c89b Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Wed, 24 Mar 2021 23:31:59 +0000 Subject: [PATCH 07/14] fix spellings Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index ac9af3f5e3..5823da3ef6 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -69,7 +69,7 @@ Vendors can have several implementations/ways to use this concept - The sonic_y_cable package is installed in both host and pmon #### Implementation details -- Once the xcvrd will start (daemon launched) or tranceiver is connected (plugged in), in both cases xcvrd can determine the Vendor name and part number from the register specification and then it can appropriately read and parse the vendor name and part number from the spec using eeprom. Once it has this information it can then use this file to Load/import the appropriate module. +- Once the xcvrd will start (daemon launched) or transceiver is connected (plugged in), in both cases xcvrd can determine the Vendor name and part number from the register specification and then it can appropriately read and parse the vendor name and part number from the spec using eeprom. Once it has this information it can then use this file to Load/import the appropriate module. ### Directory Structure From 16697045bb02266da4b0526cd13e40059bf77c1f Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Thu, 25 Mar 2021 15:00:48 +0000 Subject: [PATCH 08/14] fixing comments Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 139 ++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 49 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index 5823da3ef6..bed5af7585 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -30,14 +30,13 @@ Challenge: to provide an interface for Y cable to interact with PMON docker and - We need to have a vendor to corresponding Y cable module mappings defined and accessible somewhere for PMon container to import - Before calling any Y cable API, how do we know which type/vendor does the Y cable belong to ? - - Also lets suppose once the type/vendor of the cable is known from where does PMon container or cli import the module ? + - Also lets suppose once the type/vendor of the cable is known from where does interested application import the module ? - Since there can be many specs which vendors follow (8636, 8624 etc.) for transceivers it is important to have a solution which meets all requirements so that the API access is available to whoever wants to invoke it. - another issue is how do we support the multiple vendors modules/packages which could be used by both SONiC PMon container docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. Although we are moving towards a model where cli should not need to import Y cable modules but it is still preferred have it accessible #### Proposed Solution -- We define a file which would contain vendor to module mapping and put it in a place which is accessible to both PMon container and host -- The vendor to module mapping can be present in a file which could be present in sonic_platform_common +- We define a file which would contain a mapping from vendor/part number to the appropriate Y-cable module to load and put it in a place which is accessible to both PMon container and host which can be present in sonic_platform_common - It makes sense to keep the mapping file in the sonic_y_cable package so that it can be updated in the same pull request when a vendor adds a new cable implementation. However, we cannot install data files outside of the Python directory via a wheel. Considering this we propose to make this a Python file which simply contains a 2D dictionary which can be used to look up the module path. If the file is part of the sonic_y_cable package, it will be installed in both the PMon container and the host For example @@ -53,14 +52,30 @@ Vendors can have several implementations/ways to use this concept - Mapping could be such that its a dictionary in 2D -``` - {: {}, - : {:}} -``` + ```python + { + : { + + }, + : { + : + } + } + ``` + - For example -``` - {"Credo" : {"model1": "y_cable.py"}, - "Amphenol" : {"model_a": "y_cable_a.py", "model_b":"y_cable_b.py"}} +```python + + { + "Credo": { + "model1": "y_cable.py" + }, + + "Amphenol" : { + "model_a": "y_cable_a.py", + "model_b": "y_cable_b.py" + } + } ``` #### Rationale @@ -80,19 +95,31 @@ Vendors can have several implementations/ways to use this concept - Currently the assumption is Y-cable API will be written in the Python language - If a vendor has an existing library in a different language, they will need to either find a way to wrap/bind it in Python to align with the description below or (preferrably) provide a pure Python implementation - Since sonic_y_cable (sonic-platform-common/sonic_y_cable) is already built as a package today (only for a single Y cable vendor with sonic-buildimage) vendors can also place their implementation in this directory itself. + - Also, a vendor can provide multiple files to support multiple cables/groups of cables. Importing the module from the mappng should import all the necessary implementation for the cable #### Proposed Solution - Vendors can place their implementations in this format +```python + sonic_platform_common/sonic_y_cable// ``` - sonic_platform_common/sonic_y_cable//y_cable.py -``` -- For example +```python + sonic_platform_common/sonic_y_cable/// + sonic_platform_common/sonic_y_cable/// ``` +- Few examples + +```python sonic_platform_common/sonic_y_cable/credo/y_cable.py ``` + +```python + sonic_platform_common/sonic_y_cable/credo/PART_XYZ/y_cable_xyz.py + sonic_platform_common/sonic_y_cable/credo/PART_ABC/y_cable_abc.py + sonic_platform_common/sonic_y_cable/credo/PART_ABC/abc_helper.py +``` #### Rationale - The requirement here would be that the vendors must create their modules such that It can easily be accessed/imported and the modules also adhere to a uniform convention @@ -101,7 +128,7 @@ Vendors can have several implementations/ways to use this concept ### Port to module mapping -- Another thing that is required is once we do have a vendor to module mapping, we need to map appropriate port to a module as well +- Another thing that is required is once we do have a mapping from vendor/part number to the appropriate Y-cable module to load, we need to map appropriate port to a module as well #### Background @@ -113,70 +140,84 @@ Vendors can have several implementations/ways to use this concept - Each module of the Y cable vendor can be a class (of each transceiver type) and all we need to do is instantiate the objects of these classes as class instances and these objects will provide the interface of calling the API's for the appropriate vendor Y cable. - This instantiation will be done inside xcvrd, when xcvrd starts - - These objects basically emulate Y cable instances and whatever action/interaction needs to be done with the Ycable the methods of these objects would provide that + - These objects basically emulate Y cable instances and whatever action/interaction needs to be done with the YCable the methods of these objects would provide that - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the Y-cable. - - If the vendor does not support or implement the utility, it will just raise a not implemented error from the base class itself + - for vendors the recommneded approach in case their subclass implementation does not support a method, it should set the method equal to None. This differentiates it from a method they forgot to implement. Then, the calling code should first check if the method is None before attempting to call it. -For example a typical module of the vendor can be like this -``` +For example the base class would be like this - class Ycable(Ycablebase): - #all vendor modules inherit from Ycablebase - def __init__(self): +```python + class YCableBase(object): + def __init__(self, port): + self.port = port + def toggle_mux_to_torA(self, port): - #implement or raise exception if not implemented - raise NotImplementedError + + def toggle_mux_to_torB(self, port): - #implement or raise exception if not implemented - raise NotImplementedError + def check_prbs(self, port): - #implement or raise exception if not implemented - raise NotImplementedError + def only_credo(self, port): - raise NotImplementedError + def only_amphenol(self, port): - raise NotImplementedError + -``` -the base class would be like this ``` - class Ycablebase(object): - def __init__(self, port): - self.port = port + +For example a typical module of the vendor can be like this +```python + + class YCable(YCableBase): + #All vendor modules inherit from YCableBase + + def __init__(self): + def toggle_mux_to_torA(self, port): - raise NotImplementedError + + def toggle_mux_to_torB(self, port): - raise NotImplementedError + def check_prbs(self, port): - raise NotImplementedError + def only_credo(self, port): - raise NotImplementedError + def only_amphenol(self, port): - raise NotImplementedError + ``` - #### Implementation details - Now for xcvrd to use this solution, all it has to do is instantiate the class objects defined by importing the appropriate module. This should happen when xcvrd starts or if there is a change event (xcvrd inserted/removed) -``` - from credo import y_cable - y_cable_port_Ethernet0 = Ycable(port) +```python + # import the vendor to module mapping + from sonic_y_cable import y_cable_vendor_mapping + + # This vendor/part_name determination subroutines will either read through eeprom + # or else read from the TRANSCEIVER_INFO_TABLE inside state db + vendor_name = get_vendor_name(port) + part_name = get_part_name(port) + + module = y_cable_vendor_mapping.mapping[vendor_name][part_name] + + from sonic_y_cable import vendor_name.part_name.module.YCable as YCable + + y_cable_port_Ethernet0 = YCable(port) # and to use the Y cable APIS try: - y_cable_port_etherne0.toggle_mux_to_torA() + y_cable_port_Etherne0.toggle_mux_to_torA() except: helper_logger.log(not able to toggle_mux_to_torA) ``` @@ -184,12 +225,12 @@ the base class would be like this - xcvrd can maintain a dict of these objects an whenever it needs to call the API for the correct port (in this case physical port) it can easily achieve so by indexing into the instance of the physical port and calling the class object. -``` +```python Y_cable_ports_instances = {} # appending instances in the dictionary - Y_cable_ports_instances[physical_port] = Ycable(port) + Y_cable_ports_instances[physical_port] = YCable(port) # and to use the Y cable APIS try: @@ -200,18 +241,18 @@ the base class would be like this ### How does cli interact with Y cable api's -- Another thing that is required is once we do have a vendor to module mapping, we need to map appropriate port to a module as well +- Another thing that is required is once we do have a a mapping from vendor/part number to the appropriate Y-cable module to load, we need to map appropriate port to a module as well #### Background - - Another requirement we have is Cli also requires to interact with the Ycable directly. This basically implies that all Ycable vendor packages needs to be imported inside SONiC-utilities/host as well + - Another requirement we have is Cli also requires to interact with the YCable directly. This basically implies that all Ycable vendor packages needs to be imported inside SONiC-utilities/host as well - This would come in the form of commands like setting PRBS, enabling disabling loopback and also get the BER info and EYE info etc - Also commands such as config/show hwmode is important which gives the cli ability to toggle the mux without going into SONiC modules like mux-mgr or orchagent. - All these require access to Y cable APIs to be directly called by the cli. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc #### Proposed Solution(s) - - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into vendor to module mapping file and then load the module and execute the API + - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into a mapping from vendor/part number to the appropriate Y-cable module to load file and then load the module and execute the API - The more preferred approach here is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-cable. Exanple table and operations From c810b4da3ed1dc51613989c14775a5966a7fb6ce Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Thu, 25 Mar 2021 15:12:05 +0000 Subject: [PATCH 09/14] formatting Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 47 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index bed5af7585..1f5d63ff2f 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -40,8 +40,9 @@ Challenge: to provide an interface for Y cable to interact with PMON docker and - It makes sense to keep the mapping file in the sonic_y_cable package so that it can be updated in the same pull request when a vendor adds a new cable implementation. However, we cannot install data files outside of the Python directory via a wheel. Considering this we propose to make this a Python file which simply contains a 2D dictionary which can be used to look up the module path. If the file is part of the sonic_y_cable package, it will be installed in both the PMon container and the host For example -``` - /sonic_platform_common/sonic_y_cable/y_cable_vendor_mapping.py +```python + + /sonic_platform_common/sonic_y_cable/y_cable_vendor_mapping.py ``` Vendors can have several implementations/ways to use this concept @@ -52,7 +53,8 @@ Vendors can have several implementations/ways to use this concept - Mapping could be such that its a dictionary in 2D - ```python +```python + { : { @@ -61,9 +63,10 @@ Vendors can have several implementations/ways to use this concept : } } - ``` +``` + +For example -- For example ```python { @@ -210,33 +213,33 @@ For example a typical module of the vendor can be like this part_name = get_part_name(port) module = y_cable_vendor_mapping.mapping[vendor_name][part_name] - - from sonic_y_cable import vendor_name.part_name.module.YCable as YCable - y_cable_port_Ethernet0 = YCable(port) + from sonic_y_cable import vendor_name.part_name.module.YCable as YCable + + y_cable_port_Ethernet0 = YCable(port) + + # and to use the Y cable APIS + try: + y_cable_port_Etherne0.toggle_mux_to_torA() + except: + helper_logger.log(not able to toggle_mux_to_torA) - # and to use the Y cable APIS - try: - y_cable_port_Etherne0.toggle_mux_to_torA() - except: - helper_logger.log(not able to toggle_mux_to_torA) ``` #### Rationale - xcvrd can maintain a dict of these objects an whenever it needs to call the API for the correct port (in this case physical port) it can easily achieve so by indexing into the instance of the physical port and calling the class object. ```python + Y_cable_ports_instances = {} - Y_cable_ports_instances = {} - - # appending instances in the dictionary - Y_cable_ports_instances[physical_port] = YCable(port) + # appending instances in the dictionary + Y_cable_ports_instances[physical_port] = YCable(port) - # and to use the Y cable APIS - try: - Y_cable_ports_instances[physical_port].toggle_mux_to_torA() - except: - helper_logger.log(not able to toggle_mux_to_torA) + # and to use the Y cable APIS + try: + Y_cable_ports_instances[physical_port].toggle_mux_to_torA() + except: + helper_logger.log(not able to toggle_mux_to_torA) ``` From 31186c7022a848bea5c291d19eb30f979b331917 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Thu, 25 Mar 2021 21:41:23 +0000 Subject: [PATCH 10/14] fix suggestions Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 49 ++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index 1f5d63ff2f..02aeac2b0c 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -40,7 +40,7 @@ Challenge: to provide an interface for Y cable to interact with PMON docker and - It makes sense to keep the mapping file in the sonic_y_cable package so that it can be updated in the same pull request when a vendor adds a new cable implementation. However, we cannot install data files outside of the Python directory via a wheel. Considering this we propose to make this a Python file which simply contains a 2D dictionary which can be used to look up the module path. If the file is part of the sonic_y_cable package, it will be installed in both the PMon container and the host For example -```python +``` /sonic_platform_common/sonic_y_cable/y_cable_vendor_mapping.py ``` @@ -54,7 +54,6 @@ Vendors can have several implementations/ways to use this concept ```python - { : { @@ -68,15 +67,14 @@ Vendors can have several implementations/ways to use this concept For example ```python - { - "Credo": { - "model1": "y_cable.py" + "Vendor1": { + "model1": "vendor1/y_cable.py" }, - "Amphenol" : { - "model_a": "y_cable_a.py", - "model_b": "y_cable_b.py" + "Vendor2" : { + "model_a": "vendor2/y_cable_a.py", + "model_b": "vendor2/y_cable_b.py" } } ``` @@ -104,24 +102,24 @@ For example - Vendors can place their implementations in this format -```python +``` sonic_platform_common/sonic_y_cable// ``` -```python - sonic_platform_common/sonic_y_cable/// - sonic_platform_common/sonic_y_cable/// +``` + sonic_platform_common/sonic_y_cable// + sonic_platform_common/sonic_y_cable// ``` - Few examples -```python - sonic_platform_common/sonic_y_cable/credo/y_cable.py +``` + sonic_platform_common/sonic_y_cable/vendor1/y_cable.py ``` -```python - sonic_platform_common/sonic_y_cable/credo/PART_XYZ/y_cable_xyz.py - sonic_platform_common/sonic_y_cable/credo/PART_ABC/y_cable_abc.py - sonic_platform_common/sonic_y_cable/credo/PART_ABC/abc_helper.py +``` + sonic_platform_common/sonic_y_cable/vendor2/y_cable_xyz.py + sonic_platform_common/sonic_y_cable/vendor2/y_cable_abc.py + sonic_platform_common/sonic_y_cable/vendor2/abc_helper.py ``` #### Rationale - The requirement here would be that the vendors must create their modules such that It can easily be accessed/imported and the modules also adhere to a uniform convention @@ -143,9 +141,9 @@ For example - Each module of the Y cable vendor can be a class (of each transceiver type) and all we need to do is instantiate the objects of these classes as class instances and these objects will provide the interface of calling the API's for the appropriate vendor Y cable. - This instantiation will be done inside xcvrd, when xcvrd starts - - These objects basically emulate Y cable instances and whatever action/interaction needs to be done with the YCable the methods of these objects would provide that + - These objects basically emulate Y cable instances and whatever action/interaction needs to be done with the Y-Cable the methods of these objects would provide that - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the Y-cable. - - for vendors the recommneded approach in case their subclass implementation does not support a method, it should set the method equal to None. This differentiates it from a method they forgot to implement. Then, the calling code should first check if the method is None before attempting to call it. + - for vendors the recommended approach in case their subclass implementation does not support a method, is to set the method equal to None. This differentiates it from a method they forgot to implement. Then, the calling code should first check if the method is None before attempting to call it. For example the base class would be like this @@ -175,9 +173,7 @@ For example the base class would be like this For example a typical module of the vendor can be like this ```python - class YCable(YCableBase): - #All vendor modules inherit from YCableBase def __init__(self): @@ -202,6 +198,7 @@ For example a typical module of the vendor can be like this - Now for xcvrd to use this solution, all it has to do is instantiate the class objects defined by importing the appropriate module. This should happen when xcvrd starts or if there is a change event (xcvrd inserted/removed) ```python + import importlib # import the vendor to module mapping from sonic_y_cable import y_cable_vendor_mapping @@ -214,7 +211,11 @@ For example a typical module of the vendor can be like this module = y_cable_vendor_mapping.mapping[vendor_name][part_name] - from sonic_y_cable import vendor_name.part_name.module.YCable as YCable + from sonic_y_cable import module + + importlib.reload(module) + + from module import YCable y_cable_port_Ethernet0 = YCable(port) @@ -248,7 +249,7 @@ For example a typical module of the vendor can be like this #### Background - - Another requirement we have is Cli also requires to interact with the YCable directly. This basically implies that all Ycable vendor packages needs to be imported inside SONiC-utilities/host as well + - Another requirement we have is Cli also requires to interact with the Y-Cable directly. This basically implies that all Ycable vendor packages needs to be imported inside SONiC-utilities/host as well - This would come in the form of commands like setting PRBS, enabling disabling loopback and also get the BER info and EYE info etc - Also commands such as config/show hwmode is important which gives the cli ability to toggle the mux without going into SONiC modules like mux-mgr or orchagent. - All these require access to Y cable APIs to be directly called by the cli. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc From e5fe47419fa1948ea6998c733ae9d13bcab68c29 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Fri, 26 Mar 2021 06:21:51 +0000 Subject: [PATCH 11/14] fix formattting Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 146 +++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 74 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index 02aeac2b0c..7178b179cd 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -39,11 +39,11 @@ Challenge: to provide an interface for Y cable to interact with PMON docker and - We define a file which would contain a mapping from vendor/part number to the appropriate Y-cable module to load and put it in a place which is accessible to both PMon container and host which can be present in sonic_platform_common - It makes sense to keep the mapping file in the sonic_y_cable package so that it can be updated in the same pull request when a vendor adds a new cable implementation. However, we cannot install data files outside of the Python directory via a wheel. Considering this we propose to make this a Python file which simply contains a 2D dictionary which can be used to look up the module path. If the file is part of the sonic_y_cable package, it will be installed in both the PMon container and the host -For example -``` +###For example - /sonic_platform_common/sonic_y_cable/y_cable_vendor_mapping.py -``` + ``` + /sonic_platform_common/sonic_y_cable/y_cable_vendor_mapping.py + ``` Vendors can have several implementations/ways to use this concept - Vendor has a 1:1 mapping between model and Python file @@ -52,32 +52,31 @@ Vendors can have several implementations/ways to use this concept - Mapping could be such that its a dictionary in 2D - -```python + ```python { - : { - + "": { + "": "" }, - : { - : + "" : { + "": "" } } -``` + ``` -For example +###For example -```python - { - "Vendor1": { + ```python + { + "Vendor1": { "model1": "vendor1/y_cable.py" - }, + }, - "Vendor2" : { + "Vendor2" : { "model_a": "vendor2/y_cable_a.py", "model_b": "vendor2/y_cable_b.py" - } - } -``` + } + } + ``` #### Rationale @@ -96,31 +95,32 @@ For example - Currently the assumption is Y-cable API will be written in the Python language - If a vendor has an existing library in a different language, they will need to either find a way to wrap/bind it in Python to align with the description below or (preferrably) provide a pure Python implementation - Since sonic_y_cable (sonic-platform-common/sonic_y_cable) is already built as a package today (only for a single Y cable vendor with sonic-buildimage) vendors can also place their implementation in this directory itself. - - Also, a vendor can provide multiple files to support multiple cables/groups of cables. Importing the module from the mappng should import all the necessary implementation for the cable + - Also, a vendor can provide multiple files to support multiple cables/groups of cables. Importing the module from the mapping should import all the necessary implementation for the cable + - Vendors can put their common implementation across multiple modules in helper files which can be present in the vendor directory or inside another subdirectory. The second example below shows this approach. #### Proposed Solution - Vendors can place their implementations in this format -``` - sonic_platform_common/sonic_y_cable// -``` + ``` + sonic_platform_common/sonic_y_cable// + ``` -``` - sonic_platform_common/sonic_y_cable// - sonic_platform_common/sonic_y_cable// -``` + ``` + sonic_platform_common/sonic_y_cable// + sonic_platform_common/sonic_y_cable// + ``` - Few examples -``` - sonic_platform_common/sonic_y_cable/vendor1/y_cable.py -``` + ``` + sonic_platform_common/sonic_y_cable/vendor1/y_cable.py + ``` -``` - sonic_platform_common/sonic_y_cable/vendor2/y_cable_xyz.py - sonic_platform_common/sonic_y_cable/vendor2/y_cable_abc.py - sonic_platform_common/sonic_y_cable/vendor2/abc_helper.py -``` + ``` + sonic_platform_common/sonic_y_cable/vendor2/y_cable_xyz.py + sonic_platform_common/sonic_y_cable/vendor2/y_cable_abc.py + sonic_platform_common/sonic_y_cable/vendor2/abc_helper.py + ``` #### Rationale - The requirement here would be that the vendors must create their modules such that It can easily be accessed/imported and the modules also adhere to a uniform convention @@ -145,63 +145,63 @@ For example - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the Y-cable. - for vendors the recommended approach in case their subclass implementation does not support a method, is to set the method equal to None. This differentiates it from a method they forgot to implement. Then, the calling code should first check if the method is None before attempting to call it. -For example the base class would be like this +###For example the base class would be like this -```python - class YCableBase(object): - def __init__(self, port): - self.port = port + ```python + class YCableBase(object): + def __init__(self, port): + self.port = port - def toggle_mux_to_torA(self, port): + def toggle_mux_to_torA(self, port): - def toggle_mux_to_torB(self, port): + def toggle_mux_to_torB(self, port): - def check_prbs(self, port): + def check_prbs(self, port): - def only_credo(self, port): + def only_credo(self, port): - def only_amphenol(self, port): + def only_amphenol(self, port): + ``` -``` +###For example a typical module of the vendor can be like this -For example a typical module of the vendor can be like this -```python - class YCable(YCableBase): + ```python + class YCable(YCableBase): - def __init__(self): + def __init__(self): - def toggle_mux_to_torA(self, port): + def toggle_mux_to_torA(self, port): - def toggle_mux_to_torB(self, port): + def toggle_mux_to_torB(self, port): - def check_prbs(self, port): + def check_prbs(self, port): - def only_credo(self, port): + def only_credo(self, port): - def only_amphenol(self, port): + def only_amphenol(self, port): -``` + ``` #### Implementation details - Now for xcvrd to use this solution, all it has to do is instantiate the class objects defined by importing the appropriate module. This should happen when xcvrd starts or if there is a change event (xcvrd inserted/removed) -```python - import importlib + ```python # import the vendor to module mapping from sonic_y_cable import y_cable_vendor_mapping - + from sonic_py_common.general import load_module_from_source + # This vendor/part_name determination subroutines will either read through eeprom # or else read from the TRANSCEIVER_INFO_TABLE inside state db @@ -209,11 +209,9 @@ For example a typical module of the vendor can be like this part_name = get_part_name(port) - module = y_cable_vendor_mapping.mapping[vendor_name][part_name] - - from sonic_y_cable import module + path_to_module_obtained_from_mapping = y_cable_vendor_mapping.mapping[vendor_name][part_name] - importlib.reload(module) + module = load_module_from_source("y_cable", "path_to_module_obtained_from_mapping") from module import YCable @@ -225,12 +223,12 @@ For example a typical module of the vendor can be like this except: helper_logger.log(not able to toggle_mux_to_torA) -``` + ``` #### Rationale - xcvrd can maintain a dict of these objects an whenever it needs to call the API for the correct port (in this case physical port) it can easily achieve so by indexing into the instance of the physical port and calling the class object. -```python + ```python Y_cable_ports_instances = {} # appending instances in the dictionary @@ -241,7 +239,7 @@ For example a typical module of the vendor can be like this Y_cable_ports_instances[physical_port].toggle_mux_to_torA() except: helper_logger.log(not able to toggle_mux_to_torA) -``` + ``` ### How does cli interact with Y cable api's @@ -249,7 +247,7 @@ For example a typical module of the vendor can be like this #### Background - - Another requirement we have is Cli also requires to interact with the Y-Cable directly. This basically implies that all Ycable vendor packages needs to be imported inside SONiC-utilities/host as well + - Another requirement we have is Cli also requires to interact with the Y-Cable directly. This basically implies that all Y-Cable vendor packages needs to be imported inside SONiC-utilities/host as well - This would come in the form of commands like setting PRBS, enabling disabling loopback and also get the BER info and EYE info etc - Also commands such as config/show hwmode is important which gives the cli ability to toggle the mux without going into SONiC modules like mux-mgr or orchagent. - All these require access to Y cable APIs to be directly called by the cli. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc @@ -260,12 +258,12 @@ For example a typical module of the vendor can be like this - The more preferred approach here is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-cable. Exanple table and operations -``` - HW_MUX_OPERATION_TABLE|Ethernet0 - state active/standby - enable_prbs true/false - check_mux_direction true/false -``` + ``` + HW_MUX_OPERATION_TABLE|Ethernet0 + state active/standby + enable_prbs true/false + check_mux_direction true/false + ``` - In xcvrd we can have a thread running and listening to these events and execute the APIs since all the ports already have the correct mapping of the module (maintained in the form of a dictionary). The response of the API can be again written back to the redis table and absorbed by the CLI ### Concurrency for Y cables API From e02ccd982698e39c693d62dd8abff0494e577007 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Mon, 29 Mar 2021 10:07:08 +0000 Subject: [PATCH 12/14] correct formatting Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index 7178b179cd..c4a476d4a3 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -39,8 +39,7 @@ Challenge: to provide an interface for Y cable to interact with PMON docker and - We define a file which would contain a mapping from vendor/part number to the appropriate Y-cable module to load and put it in a place which is accessible to both PMon container and host which can be present in sonic_platform_common - It makes sense to keep the mapping file in the sonic_y_cable package so that it can be updated in the same pull request when a vendor adds a new cable implementation. However, we cannot install data files outside of the Python directory via a wheel. Considering this we propose to make this a Python file which simply contains a 2D dictionary which can be used to look up the module path. If the file is part of the sonic_y_cable package, it will be installed in both the PMon container and the host -###For example - +- For example ``` /sonic_platform_common/sonic_y_cable/y_cable_vendor_mapping.py ``` @@ -63,7 +62,7 @@ Vendors can have several implementations/ways to use this concept } ``` -###For example +- For example ```python { @@ -145,7 +144,7 @@ Vendors can have several implementations/ways to use this concept - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the Y-cable. - for vendors the recommended approach in case their subclass implementation does not support a method, is to set the method equal to None. This differentiates it from a method they forgot to implement. Then, the calling code should first check if the method is None before attempting to call it. -###For example the base class would be like this + - For example the base class would be like this ```python class YCableBase(object): @@ -170,7 +169,7 @@ Vendors can have several implementations/ways to use this concept ``` -###For example a typical module of the vendor can be like this + - For example a typical module of the vendor can be like this ```python class YCable(YCableBase): @@ -257,7 +256,7 @@ Vendors can have several implementations/ways to use this concept - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into a mapping from vendor/part number to the appropriate Y-cable module to load file and then load the module and execute the API - The more preferred approach here is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-cable. -Exanple table and operations + - Exanple table and operations ``` HW_MUX_OPERATION_TABLE|Ethernet0 state active/standby From e48841d6d8976294d7df65228d6db4b7c6fe06ad Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Mon, 29 Mar 2021 22:42:46 +0000 Subject: [PATCH 13/14] formatting Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 62 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index c4a476d4a3..e5ec2612e4 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -1,4 +1,4 @@ -## Multiple Y-cable vendor API design +## Multiple Y-Cable vendor API design ## Revision @@ -11,13 +11,13 @@ ### Overview This document summarizes the approach taken to accommodate multiple -Y cable vendors for supporting dual-ToR configurations in SONiC. +Y-Cable vendors for supporting dual-ToR configurations in SONiC. All the design choices are presented -such that vendors can implement the Y cable interface with ease and effeciency +such that vendors can implement the Y-Cable interface with ease and effeciency and all the feature requirements are met. -Challenge: to provide an interface for Y cable to interact with PMON docker and HOST +Challenge: to provide an interface for Y-Cable to interact with PMON docker and HOST which can be uniform across all vendors. As part of this refactor, we will be moving towards a model where only xcvrd interacts with the cables/transceivers, and host-side processes will communicate with xcvrd rather than with the devices directly @@ -27,16 +27,16 @@ Challenge: to provide an interface for Y cable to interact with PMON docker and #### Background -- We need to have a vendor to corresponding Y cable module mappings defined and accessible somewhere for PMon container to import +- We need to have a vendor to corresponding Y-Cable module mappings defined and accessible somewhere for PMon container to import - - Before calling any Y cable API, how do we know which type/vendor does the Y cable belong to ? - - Also lets suppose once the type/vendor of the cable is known from where does interested application import the module ? + - Before calling any Y-Cable API, how do we know which type/vendor does the Y-Cable belong to? + - Also lets suppose once the type/vendor of the cable is known from where does interested application import the module? - Since there can be many specs which vendors follow (8636, 8624 etc.) for transceivers it is important to have a solution which meets all requirements so that the API access is available to whoever wants to invoke it. - - another issue is how do we support the multiple vendors modules/packages which could be used by both SONiC PMon container docker as well as the sonic cli (sonic-utilities). Basically the package should be available both in host and container. Although we are moving towards a model where cli should not need to import Y cable modules but it is still preferred have it accessible + - another issue is how do we support the multiple vendors modules/packages which could be used by both SONiC PMon container docker as well as the SONiC CLI (sonic-utilities). Basically the package should be available both in host and container. Although we are moving towards a model where CLI should not need to import Y-Cable modules but it is still preferred have it accessible #### Proposed Solution -- We define a file which would contain a mapping from vendor/part number to the appropriate Y-cable module to load and put it in a place which is accessible to both PMon container and host which can be present in sonic_platform_common +- We define a file which would contain a mapping from vendor/part number to the appropriate Y-Cable module to load and put it in a place which is accessible to both PMon container and host which can be present in sonic_platform_common - It makes sense to keep the mapping file in the sonic_y_cable package so that it can be updated in the same pull request when a vendor adds a new cable implementation. However, we cannot install data files outside of the Python directory via a wheel. Considering this we propose to make this a Python file which simply contains a 2D dictionary which can be used to look up the module path. If the file is part of the sonic_y_cable package, it will be installed in both the PMon container and the host - For example @@ -89,11 +89,11 @@ Vendors can have several implementations/ways to use this concept #### Background -- We need to have an appropriate place where vendors can implement their modules and provide SONiC with an abstraction layer where PMon container and host can access the Y cable packages of all the vendors with ease +- We need to have an appropriate place where vendors can implement their modules and provide SONiC with an abstraction layer where PMon container and host can access the Y-Cable packages of all the vendors with ease - - Currently the assumption is Y-cable API will be written in the Python language + - Currently the assumption is Y-Cable API will be written in the Python language - If a vendor has an existing library in a different language, they will need to either find a way to wrap/bind it in Python to align with the description below or (preferrably) provide a pure Python implementation - - Since sonic_y_cable (sonic-platform-common/sonic_y_cable) is already built as a package today (only for a single Y cable vendor with sonic-buildimage) vendors can also place their implementation in this directory itself. + - Since sonic_y_cable (sonic-platform-common/sonic_y_cable) is already built as a package today (only for a single Y-Cable vendor with sonic-buildimage) vendors can also place their implementation in this directory itself. - Also, a vendor can provide multiple files to support multiple cables/groups of cables. Importing the module from the mapping should import all the necessary implementation for the cable - Vendors can put their common implementation across multiple modules in helper files which can be present in the vendor directory or inside another subdirectory. The second example below shows this approach. @@ -128,20 +128,20 @@ Vendors can have several implementations/ways to use this concept ### Port to module mapping -- Another thing that is required is once we do have a mapping from vendor/part number to the appropriate Y-cable module to load, we need to map appropriate port to a module as well +- Another thing that is required is once we do have a mapping from vendor/part number to the appropriate Y-Cable module to load, we need to map appropriate port to a module as well #### Background - Basically, the key idea is once we have a port identified as being of a certain vendor and it has been identified to load a certain module which we can gather from the mapping described above we still need to call the correct module on each port each time we call the API on the port - - want to maintain this mapping in memory since xcvrd does not want to read/parse this y_cable_vendor_mapping.csv file again and again each time we call the Y-cable API + - want to maintain this mapping in memory since xcvrd does not want to read/parse this y_cable_vendor_mapping.py file again and again each time we call the Y-Cable API - Also note that the module loaded might change during xcvrd running lifetime since cable can be changed from one vendor to another. So we need to take this into consideration as well #### Proposed Solution - - Each module of the Y cable vendor can be a class (of each transceiver type) and all we need to do is instantiate the objects of these classes as class instances and these objects will provide the interface of calling the API's for the appropriate vendor Y cable. + - Each module of the Y-Cable vendor can be a class (of each transceiver type) and all we need to do is instantiate the objects of these classes as class instances and these objects will provide the interface of calling the API's for the appropriate vendor Y-Cable. - This instantiation will be done inside xcvrd, when xcvrd starts - - These objects basically emulate Y cable instances and whatever action/interaction needs to be done with the Y-Cable the methods of these objects would provide that - - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the Y-cable. + - These objects basically emulate Y-Cable instances and whatever action/interaction needs to be done with the Y-Cable the methods of these objects would provide that + - each vendor in their implementation can inherit from a base class where there will be definitions for all the supported capabilities of the Y-Cable. - for vendors the recommended approach in case their subclass implementation does not support a method, is to set the method equal to None. This differentiates it from a method they forgot to implement. Then, the calling code should first check if the method is None before attempting to call it. - For example the base class would be like this @@ -216,7 +216,7 @@ Vendors can have several implementations/ways to use this concept y_cable_port_Ethernet0 = YCable(port) - # and to use the Y cable APIS + # and to use the Y-Cable APIS try: y_cable_port_Etherne0.toggle_mux_to_torA() except: @@ -233,7 +233,7 @@ Vendors can have several implementations/ways to use this concept # appending instances in the dictionary Y_cable_ports_instances[physical_port] = YCable(port) - # and to use the Y cable APIS + # and to use the Y-Cable APIS try: Y_cable_ports_instances[physical_port].toggle_mux_to_torA() except: @@ -241,20 +241,20 @@ Vendors can have several implementations/ways to use this concept ``` -### How does cli interact with Y cable api's -- Another thing that is required is once we do have a a mapping from vendor/part number to the appropriate Y-cable module to load, we need to map appropriate port to a module as well +### How does SONiC CLI interact with Y-Cable API's +- Another thing that is required is once we do have a a mapping from vendor/part number to the appropriate Y-Cable module to load, we need to map appropriate port to a module as well #### Background - - Another requirement we have is Cli also requires to interact with the Y-Cable directly. This basically implies that all Y-Cable vendor packages needs to be imported inside SONiC-utilities/host as well + - Another requirement we have is SONiC CLI also requires to interact with the Y-Cable directly. This basically implies that all Y-Cable vendor packages needs to be imported inside SONiC-utilities/host as well - This would come in the form of commands like setting PRBS, enabling disabling loopback and also get the BER info and EYE info etc - - Also commands such as config/show hwmode is important which gives the cli ability to toggle the mux without going into SONiC modules like mux-mgr or orchagent. - - All these require access to Y cable APIs to be directly called by the cli. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc + - Also commands such as config/show hwmode is important which gives the CLI ability to toggle the mux without going into SONiC modules like mux-mgr or orchagent. + - All these require access to Y-Cable APIs to be directly called by the CLI. But then again same problems arrive, how do we know which type/vendor does the cable/port belong to, how to load the appropriate module etc #### Proposed Solution(s) - - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into a mapping from vendor/part number to the appropriate Y-cable module to load file and then load the module and execute the API - - The more preferred approach here is cli can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-cable. + - One way is since CLI lives in the host, we can choose to do everything on xcvrd lines. Meaning once there is port number, convert to a physical port and look into a mapping from vendor/part number to the appropriate Y-Cable module to load file and then load the module and execute the API + - The more preferred approach here is CLI can interact with PMon container thorugh redis-db. Basically we can define a schema table for different operations which need to be performed on the Y-Cable. - Exanple table and operations ``` @@ -265,11 +265,11 @@ Vendors can have several implementations/ways to use this concept ``` - In xcvrd we can have a thread running and listening to these events and execute the APIs since all the ports already have the correct mapping of the module (maintained in the form of a dictionary). The response of the API can be again written back to the redis table and absorbed by the CLI -### Concurrency for Y cables API +### Concurrency for Y-Cables API #### Background - - Since some vendors need to execute two or three transactions in a single API it is imperative to have a solution where we can protect the Y cable APIs for concurrent behavior + - Since some vendors need to execute two or three transactions in a single API it is imperative to have a solution where we can protect the Y-Cable APIs for concurrent behavior #### Proposed Solution(s) @@ -277,13 +277,13 @@ Vendors can have several implementations/ways to use this concept - For now we insist on vendors to acquire/release locks in the API/implementation itself. So that if there is any possibility of concurrency the locking mechanism inside the the API prevents that from happening -### Storing the state within a Y cable Module +### Storing the state within a Y-Cable Module #### Background - - Another requirement in future that could arise is what if we need a feature which requires vendors to store a state with the Y cable. In this regard it is important to address this requirement in the initial design itself. (example port to bus mapping) + - Another requirement in future that could arise is what if we need a feature which requires vendors to store a state with the Y-Cable. In this regard it is important to address this requirement in the initial design itself. (example port to bus mapping) #### Proposed Solution(s) - - Since the vendor has class definitions associated with Y cable module, it can have attributes which store the information. However, it still needs to be decided how these attributes will be instantiated/configured. Whether this onus will be on xcvrd/daemon or whether it can be done within the module itself. + - Since the vendor has class definitions associated with Y-Cable module, it can have attributes which store the information. However, it still needs to be decided how these attributes will be instantiated/configured. Whether this onus will be on xcvrd/daemon or whether it can be done within the module itself. From a4331387388ad7dbb978bd3a00c989e5444ba3e9 Mon Sep 17 00:00:00 2001 From: vaibhav-dahiya Date: Tue, 30 Mar 2021 23:07:13 +0000 Subject: [PATCH 14/14] fix comments Signed-off-by: vaibhav-dahiya --- doc/y_cable/design_doc.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/y_cable/design_doc.md b/doc/y_cable/design_doc.md index e5ec2612e4..c1945612aa 100644 --- a/doc/y_cable/design_doc.md +++ b/doc/y_cable/design_doc.md @@ -161,10 +161,10 @@ Vendors can have several implementations/ways to use this concept def check_prbs(self, port): - def only_credo(self, port): + def enable_loopback(self, port): - def only_amphenol(self, port): + def get_eye_info(self, port): ``` @@ -186,10 +186,10 @@ Vendors can have several implementations/ways to use this concept def check_prbs(self, port): - def only_credo(self, port): + def enable_loopback(self, port): - def only_amphenol(self, port): + def get_eye_info(self, port): ```