From 30a1500d9fcbe99fc2e587aa2df0dd60fb80dc24 Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Fri, 25 Jan 2019 18:26:48 +0530 Subject: [PATCH 1/9] Create Media-based-Port-settings.md Rename Media-based-Port-settings.md to doc/Media-based-Port-settings.md Update Media-based-Port-settings.md Update Media-based-Port-settings.md Update Media-based-Port-settings.md Update Media-based-Port-settings.md Update Media-based-Port-settings.md Update Media-based-Port-settings.md Image files Rename doc/Media-based-Port-settings.md to doc/media-settings/Media-based-Port-settings.md Delete event_flow.png Delete key_selection_flow.png Add files via upload Update Media-based-Port-settings.md Update Media-based-Port-settings.md Addressing the global range option Adding a global range block where the common values for multiple ports can be specified as a range. Changing indentation Update Media-based-Port-settings.md Update Media-based-Port-settings.md Update Media-based-Port-settings.md Update Media-based-Port-settings.md --- .../Media-based-Port-settings.md | 357 ++++++++++++++++++ doc/media-settings/event_flow.png | Bin 0 -> 18057 bytes doc/media-settings/key_selection_flow.png | Bin 0 -> 48991 bytes 3 files changed, 357 insertions(+) create mode 100644 doc/media-settings/Media-based-Port-settings.md create mode 100644 doc/media-settings/event_flow.png create mode 100644 doc/media-settings/key_selection_flow.png diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md new file mode 100644 index 0000000000..3c9fd35251 --- /dev/null +++ b/doc/media-settings/Media-based-Port-settings.md @@ -0,0 +1,357 @@ +Media based port settings in SONIC + +# 1 Document History + +| Version | Date | Author | Description | +|---------|------------|------------------------|--------------------------------------------------| +| v.01 | 01/30/2019 |Sudharsan | Initial version from Dell | + +Overview: +========= + +              Networking devices such as switches or routers use different kind of optics as well as DAC cables to connect with peer devices such as servers, storage or other networking devices. There are different types of networking cables available and based on the cable type the networking ASIC might require additional settings for a cable to work properly on a port. As an example, a 40G-QSFP-CR4 2M DAC might require a different pre-emphasis setting on a device based on Broadcom ASIC than 40G-QSFP-CR4 1M DAC on a port. If the pre-emphasis is not set properly the traffic flowing through the port might encounter CRC errors and even in some cases the port might not even become operationally up. + +              To solve the above problem, few SAI attributes required for serdes programming are listed in section below. These SAI attributes will be programmed during media insert event. + +Media settings file: +==================== + +              Each vendor need to define the media settings file under device// / /media_settings.json. This file contains the list of optics and DAC media-based settings for each port in the device. Each media setting for a media type comprises of key-value pairs per lane that is expected to be programmed when an optics or DAC is used. Examples of key value pairs include pre-emphasis, idriver and ipredriver. + +              Below example shows the media-based settings for a device on a Broadcom based platform.  For each port the list of supported optics and DAC types are defined (uniquely identified by media type key). For each media type the list of supported vendors (uniquely identified by vendor key) is defined. Each vendor key which will in turn contain the key value pairs per lane that needs to be programmed. + + The media type key defined in the file will be comprised of compliance code and length string or simply compliance code if length does not apply (e.g. 40GBASE-CR4-3M or 40GBASE-SR4). + + The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. + + When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the media key (compliance + length) is constructed and looked up at the next level. If there is an exact match then those values are fetched and returned. Unlike individual port level block below where a default value is specified, there will be no default value specified for the media-key. A no-match will make the search fall back to individual port based block from global block. + + In the port based settings block, the port on which it is detected is identified at the first level. At the second level, the media type key is constructed based on compliance code and length. If compliance code -- length key is not found in the media types listed for the port, then the key is reduced to include only compliance code. For instance, if the initial media type key constructed from the EEPROM fields is '40GBASE-CR4-2M' and the specific port does not list such an entry then key is reduced to '40GBASE-CR4' and the port entry is searched if the reduced key exists. If there is still no match, then the 'Default' value listed under the port is selected. + + At the third level, the Vendor key is derived by concatenating vendor name and vendor part number (e.g. DELL-00-11-22).  If there is no exact match for vendor name -- vendor part number key, then the vendor key is reduced to vendor name alone (e.g. DELL) and the media type entry is looked up for such a key. If there is no match, then the default value listed under the media type is chosen. Below is an example for json file for a specific port. For the port Ethernet20 two specific media types (40GBASE-SR4 and 40GBASE-CR4-3M) and a 'Default' media type is defined. For 40GBASE-SR4 a DELL vendor name- vendor PN specific setting is listed along with a 'Default' value which is chosen for all other 40GBASE-SR4 optics apart from the listed key (DELL-00-11-22). For 40GBASE-CR4-3M media key a DELL vendor name alone key word is listed along with a 'Default' key word. This would imply that any 40GBASE-CR4-3M DAC manufactured by DELL will pick the values listed in the vendor name key whereas everything else will pick the default values. + +{ + +    "PORT_MEDIA_SETTINGS": { + +        "Ethernet20": { + +            "Default": { + +                "Default": { + +                    "preemphasis": [ + +                         "0x1201", + +                          "0x1234" + +                    ], + +                    "idriver": [ + +                        "0x1", + +                        "0x1" + +                     ], + +                     "ipredriver": [ + +                        "0x1", + +                        "0x1" + +                     ] + +                }, + +                "DELL": { + +                    "preemphasis": [ + +                        "0x1205", + +                        "0x5055" + +                    ], + +                    "idriver": [ + +                        "0x2", + +                        "0x2" + +                    ], + +                    "ipredriver": [ + +                        "0x2", + +                        "0x2" + +                    ] + +                } + +            }, + +            "40GBASE-SR4": { + +                "Default": { + +                    "preemphasis": [ + +                        "0x4321", + +                        "0x4321" + +                    ], + +                    "idriver": [ + +                        "0x2", + +                        "0x3" + +                    ], + +                    "ipredriver": [ + +                         "0x3", + +                         "0x1" + +                    ] + +                }, + +                "DELL-00-11-22": { + +                    "preemphasis": [ + +                        "0x1311", + +                        "0x321c", + +                    ], + +                    "idriver": [ + +                        "0x1", + +                        "0x2", + +                    ], + +                    "ipredriver": [ + +                        "0x2", + +                        "0x1", + +                    ] + +                } + +            }, + +            "40GBASE-CR4-3M": { + +                "Default": { + +                    "preemphasis": [ + +                        "0x1021", + +                        "0x3021", + +                    ], + +                    "idriver": [ + +                        "0x4", + +                        "0x4" + +                    ], + +                    "ipredriver": [ + +                        "0x4", + +                        "0x4" + +                    ] + +                }, + +                "DELL": { + +                    "preemphasis": [ + +                        "0x1311", + +                        "0x1312 + +                    ], + +                    "idriver": [ + +                        "0x2", + +                        "0x2" + +                    ], + +                    "ipredriver": [ + +                        "0x2", + +                        "0x2" + +                    ] + +                } + +            } + +        } + +    } + +    "GLOBAL_MEDIA_SETTINGS": { + +        "Ethernet0-Ethernet120": { + +            "40GBASE-CR4-1M": { + +                "Default": { + +                    "preemphasis": [ + +                         "0x1111", + +                          "0x1274" + +                    ], + +                    "idriver": [ + +                        "0x1", + +                        "0x1" + +                     ], + +                     "ipredriver": [ + +                        "0x1", + +                        "0x1" + +                     ] + +                } + +            } + +        } + +    } + +} + +![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/event_flow.png) + +Flow: +===== + +              When a media is detected in xcvrd daemon, it constructs the media key identifier string as discussed above and searches the media_settings.json file. On finding a matching media key entry the vendor key is constructed and if found the key value pairs are fetched. The xcvrd daemon notifies these key value pairs along with the alias port to portsorch. The portsorch task will convert the alias to SAI object Id and notifies the syncd by doing port attribute set of corresponding settings. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware. + +              The notification of hardware profile from xcvrd to portsorch task will be done during initialization and during media detect event. This is not required during media removal event. Since the media settings are required only for the proper functioning of the optics or DAC, the handling can be restricted to media insert event alone and no action needs to be taken during media removal. + +              This mechanism is also very helpful in supporting new media types without upgrading the Operating system. If a new media type need to be supported the only change that needs to be done is modify media_settings.json to add the new media type. + +![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/key_selection_flow.png) + +SAI Attributes: +=============== + +              To define attributes for SAI pre-emphasis attribute as below. Some attributes like IDRIVER and IPREDRIVER are specific to Broadcom but required to be programmed for different cables similar to pre-emphasis. If an asic vendor does not support these attributes, then SAI implementation can return SAI_STATUS_NOT_SUPPORTED during set attribute call + +/** + +     * @brief Port serdes control pre-emphasis + +     * + +     * List of port serdes pre-emphasis values. The values are of type sai_u32_list_t + +     * where the count is number lanes in a port and the list specifies list of values + +     * to be applied to each lane. + +     * + +     * @type sai_u32_list_t + +     * @flags CREATE_AND_SET + +     * @default internal + +     */ + +    SAI_PORT_ATTR_SERDES_PREEMPHASIS, + +    /** + +     * @brief Port serdes control idriver + +     * + +     * List of port serdes idriver values. The values are of type sai_u32_list_t + +     * where the count is number lanes in a port and the list specifies list of values + +     * to be applied to each lane. + +     * + +     * @type sai_u32_list_t + +     * @flags CREATE_AND_SET + +     * @default internal + +     */ + +    SAI_PORT_ATTR_SERDES_IDRIVER, + +    /** + +     * @brief Port serdes control ipredriver + +     * + +     * List of port serdes ipredriver values. The values are of type sai_u32_list_t + +     * where the count is number lanes in a port and the list specifies list of values + +     * to be applied to each lane. + +     * + +     * @type sai_u32_list_t + +     * @flags CREATE_AND_SET + +     * @default internal + +     */ + +    SAI_PORT_ATTR_SERDES_IPREDRIVER, + +Below is the pull request + + diff --git a/doc/media-settings/event_flow.png b/doc/media-settings/event_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..fce43d0740a9987eeedc1d2545a357cf88480171 GIT binary patch literal 18057 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 WeRlFW0sQ$GIZJc9T}3+&{{A0QZ8O{e literal 0 HcmV?d00001 diff --git a/doc/media-settings/key_selection_flow.png b/doc/media-settings/key_selection_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..2cf73eabd770670b1b23dab1aa38d1b3e3e62c95 GIT binary patch literal 48991 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 Date: Mon, 4 Feb 2019 14:24:39 +0530 Subject: [PATCH 2/9] Added section on breakout scenario --- .../Media-based-Port-settings.md | 182 ++++++++++-------- 1 file changed, 98 insertions(+), 84 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index 3c9fd35251..77ab676d25 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -36,61 +36,61 @@ Media settings file:         "Ethernet20": { -            "Default": { +            "Default": {                 "Default": { -                    "preemphasis": [ +                    "preemphasis": { -                         "0x1201", +                         "Lane0": "0x1201", -                          "0x1234" +                          "Lane1": "0x1234" -                    ], +                    }, -                    "idriver": [ +                    "idriver": { -                        "0x1", +                        "Lane0": "0x1", -                        "0x1" +                        "Lane1": "0x1" -                     ], +                     }, -                     "ipredriver": [ +                     "ipredriver": { -                        "0x1", +                        "Lane0": "0x1", -                        "0x1" +                        "Lane1": "0x1" -                     ] +                     }                 },                 "DELL": { -                    "preemphasis": [ +                    "preemphasis": { -                        "0x1205", +                        "Lane0": "0x1205", -                        "0x5055" +                        "Lane1": "0x5055" -                    ], +                    }, -                    "idriver": [ +                    "idriver": {                         "0x2",                         "0x2" -                    ], +                    }, -                    "ipredriver": [ +                    "ipredriver": { -                        "0x2", +                        "Lane0": "0x2", -                        "0x2" +                        "Lane1": "0x2" -                    ] +                    }                 } @@ -100,57 +100,57 @@ Media settings file:                 "Default": { -                    "preemphasis": [ +                    "preemphasis": { -                        "0x4321", +                        "Lane0": "0x4321", -                        "0x4321" +                        "Lane1": "0x4321" -                    ], +                    }, -                    "idriver": [ +                    "idriver": { -                        "0x2", +                        "Lane0": "0x2", -                        "0x3" +                        "Lane1": "0x3" -                    ], +                    }, -                    "ipredriver": [ +                    "ipredriver": { -                         "0x3", +                         "Lane0": "0x3", -                         "0x1" +                         "Lane1": "0x1" -                    ] +                    }                 },                 "DELL-00-11-22": { -                    "preemphasis": [ +                    "preemphasis": { -                        "0x1311", +                        "Lane0": "0x1311", -                        "0x321c", +                        "Lane1": "0x321c", -                    ], +                    }, -                    "idriver": [ +                    "idriver": { -                        "0x1", +                        "Lane0": "0x1", -                        "0x2", +                        "Lane1": "0x2", -                    ], +                    }, -                    "ipredriver": [ +                    "ipredriver": { -                        "0x2", +                        "Lane0": "0x2", -                        "0x1", +                        "Lane1": "0x1", -                    ] +                    }                 } @@ -160,57 +160,57 @@ Media settings file:                 "Default": { -                    "preemphasis": [ +                    "preemphasis": { -                        "0x1021", +                        "Lane0": "0x1021", -                        "0x3021", +                        "Lane1": "0x3021", -                    ], +                    }, -                    "idriver": [ +                    "idriver": { -                        "0x4", +                        "Lane0": "0x4", -                        "0x4" +                        "Lane1": "0x4" -                    ], +                    }, -                    "ipredriver": [ +                    "ipredriver": { -                        "0x4", +                        "Lane0": "0x4", -                        "0x4" +                        "Lane1": "0x4" -                    ] +                    }                 },                 "DELL": { -                    "preemphasis": [ +                    "preemphasis": { -                        "0x1311", +                        "Lane0": "0x1311", -                        "0x1312 +                        "Lane1": "0x1312 -                    ], +                    }, -                    "idriver": [ +                    "idriver": { -                        "0x2", +                        "Lane0": "0x2", -                        "0x2" +                        "Lane1": "0x2" -                    ], +                    }, -                    "ipredriver": [ +                    "ipredriver": { -                        "0x2", +                        "Lane0": "0x2", -                        "0x2" +                        "Lane1": "0x2" -                    ] +                    }                 } @@ -224,33 +224,33 @@ Media settings file:         "Ethernet0-Ethernet120": { -            "40GBASE-CR4-1M": { +            "40GBASE-CR4-1M": {                 "Default": { -                    "preemphasis": [ +                    "preemphasis": { -                         "0x1111", +                         "Lane0": "0x1111", -                          "0x1274" +                         "Lane1": "0x1274" -                    ], +                    }, -                    "idriver": [ +                    "idriver": { -                        "0x1", +                         "Lane0": "0x1", -                        "0x1" +                         "Lane1": "0x1" -                     ], +                     }, -                     "ipredriver": [ +                     "ipredriver": { -                        "0x1", +                         "Lane0": "0x1", -                        "0x1" +                         "Lane1": "0x1" -                     ] +                     }                 } @@ -275,6 +275,20 @@ Flow: ![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/key_selection_flow.png) +Breakout Scenario: +================== + +              The media_settings.json file is defined based on logical ports and for each logical ports, the settings are defined per lane. When a port is breakout, it is split into multiple logical ports. For example let us assume the port before breakout is Ethernet0 and has four lanes, after breakout the logical ports would be Ethernet0, Ethernet1, Ethernet2, Ethernet3 with each one lane. When a media is detected, the xcvrd daemon will read media_settings.json file for the first logical port (Ethernet0) and will fetch the values for all four lanes and notify portsorch. Portsorch on receiving the message with four lanes will figure out that Ethernet0 is now in one lane mode and thus invoke the SAI API for the first port (Ethernet0) and additional three ports(Ethernet1,Ethernet2,Ethernet3) each with one lane. The data from xcvrd will be cached in a new table as below so that when breakout command is executed dynamically, the settings can be reapplied without any re-notification from xcvrd. + +PHY_MEDIA:LOGICAL_PORT_NAME:LANE_NUM: + +1)PRE-EMPHASIS: + +2)I_DRIVER: + +3)IPRE-DRIVER + + SAI Attributes: =============== From 64b036b8af90b770383838465b8712a14acf7b75 Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Wed, 27 Mar 2019 20:01:44 -0700 Subject: [PATCH 3/9] Update Media-based-Port-settings.md Updating the document based on latest design --- .../Media-based-Port-settings.md | 246 ++++++------------ 1 file changed, 78 insertions(+), 168 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index 77ab676d25..986adb2276 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -24,241 +24,159 @@ Media settings file: The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. - When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the media key (compliance + length) is constructed and looked up at the next level. If there is an exact match then those values are fetched and returned. Unlike individual port level block below where a default value is specified, there will be no default value specified for the media-key. A no-match will make the search fall back to individual port based block from global block. + When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) is constructed and looked up at the next level. If there is an exact match then those values are fetched and returned. Unlike individual port level block below where a default value is specified, there will be no default value specified. A no-match will make the search fall back to individual port based block from global block. - In the port based settings block, the port on which it is detected is identified at the first level. At the second level, the media type key is constructed based on compliance code and length. If compliance code -- length key is not found in the media types listed for the port, then the key is reduced to include only compliance code. For instance, if the initial media type key constructed from the EEPROM fields is '40GBASE-CR4-2M' and the specific port does not list such an entry then key is reduced to '40GBASE-CR4' and the port entry is searched if the reduced key exists. If there is still no match, then the 'Default' value listed under the port is selected. - - At the third level, the Vendor key is derived by concatenating vendor name and vendor part number (e.g. DELL-00-11-22).  If there is no exact match for vendor name -- vendor part number key, then the vendor key is reduced to vendor name alone (e.g. DELL) and the media type entry is looked up for such a key. If there is no match, then the default value listed under the media type is chosen. Below is an example for json file for a specific port. For the port Ethernet20 two specific media types (40GBASE-SR4 and 40GBASE-CR4-3M) and a 'Default' media type is defined. For 40GBASE-SR4 a DELL vendor name- vendor PN specific setting is listed along with a 'Default' value which is chosen for all other 40GBASE-SR4 optics apart from the listed key (DELL-00-11-22). For 40GBASE-CR4-3M media key a DELL vendor name alone key word is listed along with a 'Default' key word. This would imply that any 40GBASE-CR4-3M DAC manufactured by DELL will pick the values listed in the vendor name key whereas everything else will pick the default values. + In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is derived by concatenating vendor name and vendor part number (e.g. DELL-0123).  If there is no exact match for vendor name -- vendor part number key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port Ethernet0 a Vendor specific media type and a 'Default' media type is defined. { -    "PORT_MEDIA_SETTINGS": { - -        "Ethernet20": { - -            "Default": { - -                "Default": { - -                    "preemphasis": { - -                         "Lane0": "0x1201", - -                          "Lane1": "0x1234" - -                    }, - -                    "idriver": { - -                        "Lane0": "0x1", - -                        "Lane1": "0x1" - -                     }, - -                     "ipredriver": { - -                        "Lane0": "0x1", - -                        "Lane1": "0x1" - -                     } - -                }, - -                "DELL": { - -                    "preemphasis": { - -                        "Lane0": "0x1205", - -                        "Lane1": "0x5055" - -                    }, - -                    "idriver": { +    "GLOBAL_MEDIA_SETTINGS": { -                        "0x2", +        "Ethernet0-Ethernet124": { -                        "0x2" +            "AMPHENOL-1234": { -                    }, +                "preemphasis": { -                    "ipredriver": { +                    "lane0":"0x001234", -                        "Lane0": "0x2", +                    "lane1":"0x001234", -                        "Lane1": "0x2" +                    "lane2":"0x001234", -                    } +                    "lane3":"0x001234" -                } +                }, -            }, +                "idriver": { -            "40GBASE-SR4": { +                    "lane0":"0x2", -                "Default": { +                    "lane1":"0x2", -                    "preemphasis": { +                    "lane2":"0x2", -                        "Lane0": "0x4321", +                    "lane3":"0x2" -                        "Lane1": "0x4321" +                } -                    }, +            }, -                    "idriver": { +            "MOLEX-5678": { -                        "Lane0": "0x2", +                "preemphasis": { -                        "Lane1": "0x3" +                    "lane0":"0x005678", -                    }, +                    "lane1":"0x005678", -                    "ipredriver": { +                    "lane2":"0x005678", -                         "Lane0": "0x3", +                    "lane3":"0x005678" -                         "Lane1": "0x1" +                }, -                    } +                "idriver": { -                }, +                    "lane0":"0x1", -                "DELL-00-11-22": { +                    "lane1":"0x1", -                    "preemphasis": { +                    "lane2":"0x1", -                        "Lane0": "0x1311", +                    "lane3":"0x1" -                        "Lane1": "0x321c", +                } -                    }, +            }, -                    "idriver": { +            "DELL-1111": { -                        "Lane0": "0x1", +                "preemphasis": { -                        "Lane1": "0x2", +                    "lane0":"0x005678", -                    }, +                    "lane1":"0x005678" -                    "ipredriver": { +                }, -                        "Lane0": "0x2", +                "idriver": { -                        "Lane1": "0x1", +                    "lane0":"0x1", -                    } +                    "lane1":"0x1" -                } +                } -            }, +            } -            "40GBASE-CR4-3M": { +        } -                "Default": { +    }, -                    "preemphasis": { +    "PORT_MEDIA_SETTINGS": { -                        "Lane0": "0x1021", +        "Ethernet0": { -                        "Lane1": "0x3021", +            "Default": { -                    }, +                "preemphasis": { -                    "idriver": { +                    "lane0":"0x112233", -                        "Lane0": "0x4", +                    "lane1":"0x112233", -                        "Lane1": "0x4" +                    "lane2":"0x112244", -                    }, +                    "lane3":"0x443322" -                    "ipredriver": { +                }, -                        "Lane0": "0x4", +                "idriver": { -                        "Lane1": "0x4" +                    "lane0":"0xb", -                    } +                    "lane1":"0xc", -                }, +                    "lane2":"0xd", -                "DELL": { +                    "lane3":"0xa" -                    "preemphasis": { +                } -                        "Lane0": "0x1311", +            }, -                        "Lane1": "0x1312 +            "DELL-5678": { -                    }, +                "preemphasis": { -                    "idriver": { +                    "lane0":"0x102233", -                        "Lane0": "0x2", +                    "lane1":"0x132233", -                        "Lane1": "0x2" +                    "lane2":"0x152244", -                    }, +                    "lane3":"0x413322" -                    "ipredriver": { +                }, -                        "Lane0": "0x2", +                "idriver": { -                        "Lane1": "0x2" +                    "lane0":"0xc", -                    } +                    "lane1":"0xc", -                } +                    "lane2":"0xd", -            } +                    "lane3":"0xb" -        } +                } -    } +            } -    "GLOBAL_MEDIA_SETTINGS": { +        } -        "Ethernet0-Ethernet120": { - -            "40GBASE-CR4-1M": { - -                "Default": { - -                    "preemphasis": { - -                         "Lane0": "0x1111", - -                         "Lane1": "0x1274" - -                    }, - -                    "idriver": { - -                         "Lane0": "0x1", - -                         "Lane1": "0x1" - -                     }, - -                     "ipredriver": { - -                         "Lane0": "0x1", - -                         "Lane1": "0x1" - -                     } - -                } - -            } - -        } - -    } +    } } @@ -267,7 +185,7 @@ Media settings file: Flow: ===== -              When a media is detected in xcvrd daemon, it constructs the media key identifier string as discussed above and searches the media_settings.json file. On finding a matching media key entry the vendor key is constructed and if found the key value pairs are fetched. The xcvrd daemon notifies these key value pairs along with the alias port to portsorch. The portsorch task will convert the alias to SAI object Id and notifies the syncd by doing port attribute set of corresponding settings. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware. +              When a media is detected in xcvrd daemon, it constructs the key identifier string as discussed above and searches the media_settings.json file. If found the key value pairs are fetched. The xcvrd daemon notifies these key value pairs along with the alias port to portsorch. The portsorch task will convert the alias to SAI object Id and notifies the syncd by doing port attribute set of corresponding settings. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware.               The notification of hardware profile from xcvrd to portsorch task will be done during initialization and during media detect event. This is not required during media removal event. Since the media settings are required only for the proper functioning of the optics or DAC, the handling can be restricted to media insert event alone and no action needs to be taken during media removal. @@ -278,15 +196,7 @@ Flow: Breakout Scenario: ================== -              The media_settings.json file is defined based on logical ports and for each logical ports, the settings are defined per lane. When a port is breakout, it is split into multiple logical ports. For example let us assume the port before breakout is Ethernet0 and has four lanes, after breakout the logical ports would be Ethernet0, Ethernet1, Ethernet2, Ethernet3 with each one lane. When a media is detected, the xcvrd daemon will read media_settings.json file for the first logical port (Ethernet0) and will fetch the values for all four lanes and notify portsorch. Portsorch on receiving the message with four lanes will figure out that Ethernet0 is now in one lane mode and thus invoke the SAI API for the first port (Ethernet0) and additional three ports(Ethernet1,Ethernet2,Ethernet3) each with one lane. The data from xcvrd will be cached in a new table as below so that when breakout command is executed dynamically, the settings can be reapplied without any re-notification from xcvrd. - -PHY_MEDIA:LOGICAL_PORT_NAME:LANE_NUM: - -1)PRE-EMPHASIS: - -2)I_DRIVER: - -3)IPRE-DRIVER +              For breakout the particular media, if it has a global value is listed in the media_settings.json with appropriate lane values. If the values are specific to a port, then the entry is listed under the port. If the logical port is going to be created after breakout (E.g Ethernet0 is modified to Ethernet0,Ethernet1,Ethernet2,Ethernet3) those corresponding ports are listed in the ports section in media_settings.json. In the current breakout scenario, when port_config.ini is modified and a config reload is done, the flow will be similar to bootup sequence and thus all the media settings will be pushed from xcvrd to portsorch on restart during config apply. SAI Attributes: From 328f5117e9526e85d9bb26267a34d3ac7fc44feb Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Wed, 27 Mar 2019 23:54:15 -0700 Subject: [PATCH 4/9] Update Media-based-Port-settings.md --- doc/media-settings/Media-based-Port-settings.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index 986adb2276..0ae0caa00b 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -24,9 +24,9 @@ Media settings file: The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. - When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) is constructed and looked up at the next level. If there is an exact match then those values are fetched and returned. Unlike individual port level block below where a default value is specified, there will be no default value specified. A no-match will make the search fall back to individual port based block from global block. + When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. - In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is derived by concatenating vendor name and vendor part number (e.g. DELL-0123).  If there is no exact match for vendor name -- vendor part number key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port Ethernet0 a Vendor specific media type and a 'Default' media type is defined. + In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port Ethernet0 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key { @@ -90,7 +90,7 @@ Media settings file:             }, -            "DELL-1111": { +            "QSFP28-40GBASE-CR4-1M":{                 "preemphasis": { From 6e63fe9d7bc006b57b96609c261c8cc15ce0d4ee Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Thu, 28 Mar 2019 15:02:44 -0700 Subject: [PATCH 5/9] Update Media-based-Port-settings.md Formatting the document --- .../Media-based-Port-settings.md | 171 ++++-------------- 1 file changed, 32 insertions(+), 139 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index 0ae0caa00b..24c4acc872 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -1,189 +1,114 @@ -Media based port settings in SONIC +# Media based port settings in SONIC -# 1 Document History +## 1 Document History | Version | Date | Author | Description | |---------|------------|------------------------|--------------------------------------------------| | v.01 | 01/30/2019 |Sudharsan | Initial version from Dell | -Overview: -========= +## Overview: +               Networking devices such as switches or routers use different kind of optics as well as DAC cables to connect with peer devices such as servers, storage or other networking devices. There are different types of networking cables available and based on the cable type the networking ASIC might require additional settings for a cable to work properly on a port. As an example, a 40G-QSFP-CR4 2M DAC might require a different pre-emphasis setting on a device based on Broadcom ASIC than 40G-QSFP-CR4 1M DAC on a port. If the pre-emphasis is not set properly the traffic flowing through the port might encounter CRC errors and even in some cases the port might not even become operationally up.               To solve the above problem, few SAI attributes required for serdes programming are listed in section below. These SAI attributes will be programmed during media insert event. -Media settings file: -==================== - -              Each vendor need to define the media settings file under device// / /media_settings.json. This file contains the list of optics and DAC media-based settings for each port in the device. Each media setting for a media type comprises of key-value pairs per lane that is expected to be programmed when an optics or DAC is used. Examples of key value pairs include pre-emphasis, idriver and ipredriver. +## Media settings file: -              Below example shows the media-based settings for a device on a Broadcom based platform.  For each port the list of supported optics and DAC types are defined (uniquely identified by media type key). For each media type the list of supported vendors (uniquely identified by vendor key) is defined. Each vendor key which will in turn contain the key value pairs per lane that needs to be programmed. + Each vendor need to define the media settings file under device// / /media_settings.json. This file contains the list of optics and DAC media-based settings for each port in the device. Each media setting for a media type comprises of key-value pairs per lane that is expected to be programmed when an optics or DAC is used. Examples of key value pairs include pre-emphasis, idriver and ipredriver. - The media type key defined in the file will be comprised of compliance code and length string or simply compliance code if length does not apply (e.g. 40GBASE-CR4-3M or 40GBASE-SR4). + Below example shows the media-based settings for a device on a Broadcom based platform.  For each port the list of supported optics and DAC types are defined (uniquely identified by media type key). For each media type the list of supported vendors (uniquely identified by vendor key) is defined. Each vendor key which will in turn contain the key value pairs per lane that needs to be programmed. - The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. + The media type key defined in the file will be comprised of compliance code and length string or simply compliance code if length does not apply (e.g. 40GBASE-CR4-3M or 40GBASE-SR4). - When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. + The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. + + When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port Ethernet0 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key +``` { -     "GLOBAL_MEDIA_SETTINGS": { -         "Ethernet0-Ethernet124": { -             "AMPHENOL-1234": { -                 "preemphasis": { -                     "lane0":"0x001234", -                     "lane1":"0x001234", -                     "lane2":"0x001234", -                     "lane3":"0x001234" -                 }, -                 "idriver": { -                     "lane0":"0x2", -                     "lane1":"0x2", -                     "lane2":"0x2", -                     "lane3":"0x2" -                 } -             }, -             "MOLEX-5678": { -                 "preemphasis": { -                     "lane0":"0x005678", -                     "lane1":"0x005678", -                     "lane2":"0x005678", -                     "lane3":"0x005678" -                 }, -                 "idriver": { -                     "lane0":"0x1", -                     "lane1":"0x1", -                     "lane2":"0x1", -                     "lane3":"0x1" -                 } -             }, -             "QSFP28-40GBASE-CR4-1M":{ -                 "preemphasis": { -                     "lane0":"0x005678", -                     "lane1":"0x005678" -                 }, -                 "idriver": { -                     "lane0":"0x1", -                     "lane1":"0x1" -                 } -             } -         } -     }, -     "PORT_MEDIA_SETTINGS": { -         "Ethernet0": { -             "Default": { -                 "preemphasis": { -                     "lane0":"0x112233", -                     "lane1":"0x112233", -                     "lane2":"0x112244", -                     "lane3":"0x443322" -                 }, -                 "idriver": { -                     "lane0":"0xb", -                     "lane1":"0xc", -                     "lane2":"0xd", -                     "lane3":"0xa" -                 } -             }, -             "DELL-5678": { -                 "preemphasis": { -                     "lane0":"0x102233", -                     "lane1":"0x132233", -                     "lane2":"0x152244", -                     "lane3":"0x413322" -                 }, - -                "idriver": { - -                    "lane0":"0xc", - -                    "lane1":"0xc", - -                    "lane2":"0xd", - -                    "lane3":"0xb" - -                } - +               "idriver": { +                   "lane0":"0xc", +                   "lane1":"0xc", +                   "lane2":"0xd", +                   "lane3":"0xb" +               }             } -         } -     } - } - +``` ![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/event_flow.png) -Flow: -===== +## Flow: +               When a media is detected in xcvrd daemon, it constructs the key identifier string as discussed above and searches the media_settings.json file. If found the key value pairs are fetched. The xcvrd daemon notifies these key value pairs along with the alias port to portsorch. The portsorch task will convert the alias to SAI object Id and notifies the syncd by doing port attribute set of corresponding settings. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware. @@ -193,89 +118,57 @@ Flow: ![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/key_selection_flow.png) -Breakout Scenario: -================== +## Breakout Scenario: +               For breakout the particular media, if it has a global value is listed in the media_settings.json with appropriate lane values. If the values are specific to a port, then the entry is listed under the port. If the logical port is going to be created after breakout (E.g Ethernet0 is modified to Ethernet0,Ethernet1,Ethernet2,Ethernet3) those corresponding ports are listed in the ports section in media_settings.json. In the current breakout scenario, when port_config.ini is modified and a config reload is done, the flow will be similar to bootup sequence and thus all the media settings will be pushed from xcvrd to portsorch on restart during config apply. -SAI Attributes: -=============== +## SAI Attributes: +               To define attributes for SAI pre-emphasis attribute as below. Some attributes like IDRIVER and IPREDRIVER are specific to Broadcom but required to be programmed for different cables similar to pre-emphasis. If an asic vendor does not support these attributes, then SAI implementation can return SAI_STATUS_NOT_SUPPORTED during set attribute call +``` /** -      * @brief Port serdes control pre-emphasis -      * -      * List of port serdes pre-emphasis values. The values are of type sai_u32_list_t -      * where the count is number lanes in a port and the list specifies list of values -      * to be applied to each lane. -      * -      * @type sai_u32_list_t -      * @flags CREATE_AND_SET -      * @default internal -      */ -     SAI_PORT_ATTR_SERDES_PREEMPHASIS, - +     /** -      * @brief Port serdes control idriver -      * -      * List of port serdes idriver values. The values are of type sai_u32_list_t -      * where the count is number lanes in a port and the list specifies list of values -      * to be applied to each lane. -      * -      * @type sai_u32_list_t -      * @flags CREATE_AND_SET -      * @default internal -      */ -     SAI_PORT_ATTR_SERDES_IDRIVER, - -    /** - +  + /**      * @brief Port serdes control ipredriver - -     * - +     *      * List of port serdes ipredriver values. The values are of type sai_u32_list_t -      * where the count is number lanes in a port and the list specifies list of values -      * to be applied to each lane. - -     * - +     *      * @type sai_u32_list_t -      * @flags CREATE_AND_SET -      * @default internal -      */ -     SAI_PORT_ATTR_SERDES_IPREDRIVER, - +``` Below is the pull request From 3397bb0f25ffa67bfd7d0564a2024573fd91fa07 Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Thu, 28 Mar 2019 15:50:57 -0700 Subject: [PATCH 6/9] Update Media-based-Port-settings.md Editing file for proper indentation --- .../Media-based-Port-settings.md | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index 24c4acc872..e5d4dcf57a 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -15,18 +15,21 @@ ## Media settings file: - Each vendor need to define the media settings file under device// / /media_settings.json. This file contains the list of optics and DAC media-based settings for each port in the device. Each media setting for a media type comprises of key-value pairs per lane that is expected to be programmed when an optics or DAC is used. Examples of key value pairs include pre-emphasis, idriver and ipredriver. - Below example shows the media-based settings for a device on a Broadcom based platform.  For each port the list of supported optics and DAC types are defined (uniquely identified by media type key). For each media type the list of supported vendors (uniquely identified by vendor key) is defined. Each vendor key which will in turn contain the key value pairs per lane that needs to be programmed. - - The media type key defined in the file will be comprised of compliance code and length string or simply compliance code if length does not apply (e.g. 40GBASE-CR4-3M or 40GBASE-SR4). - - The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. +              Each vendor need to define the media settings file under device/vendor-name/ONIE_PLATFORM_STRING/media_settings.json. This file contains the list of optics and DAC media-based settings for each port in the device. Each media setting for a media type comprises of key-value pairs per lane that is expected to be programmed when an optics or DAC is used. Examples of key value pairs include pre-emphasis, idriver and ipredriver. + +              Below example shows the media-based settings for a device on a Broadcom based platform.  For each port the list of supported optics and DAC types are defined (uniquely identified by media type key). For each media type the list of supported vendors (uniquely identified by vendor key) is defined. Each vendor key which will in turn contain the key value pairs per lane that needs to be programmed. + +              The media type key defined in the file will be comprised of compliance code and length string or simply compliance code if length does not apply (e.g. 40GBASE-CR4-3M or 40GBASE-SR4). + +              The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. - When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. +              When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. - In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port Ethernet0 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key +              In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port Ethernet0 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key + +### Sample Media settings file: ``` {     "GLOBAL_MEDIA_SETTINGS": { @@ -105,7 +108,6 @@     } } ``` -![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/event_flow.png) ## Flow: @@ -115,6 +117,8 @@               The notification of hardware profile from xcvrd to portsorch task will be done during initialization and during media detect event. This is not required during media removal event. Since the media settings are required only for the proper functioning of the optics or DAC, the handling can be restricted to media insert event alone and no action needs to be taken during media removal.               This mechanism is also very helpful in supporting new media types without upgrading the Operating system. If a new media type need to be supported the only change that needs to be done is modify media_settings.json to add the new media type. + +![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/event_flow.png) ![](https://github.com/dgsudharsan/SONiC/blob/hld_media/doc/media-settings/key_selection_flow.png) @@ -169,6 +173,4 @@      */     SAI_PORT_ATTR_SERDES_IPREDRIVER, ``` -Below is the pull request - - +[This the pull request](https://github.com/opencomputeproject/SAI/pull/907) From 9c656a09213acf00f8a003f5bc5dbff95c0bd829 Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Thu, 28 Mar 2019 20:47:39 -0700 Subject: [PATCH 7/9] Update Media-based-Port-settings.md Explaining the breakout scenario with examples --- .../Media-based-Port-settings.md | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index e5d4dcf57a..b10d239dbc 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -16,24 +16,26 @@ ## Media settings file: -              Each vendor need to define the media settings file under device/vendor-name/ONIE_PLATFORM_STRING/media_settings.json. This file contains the list of optics and DAC media-based settings for each port in the device. Each media setting for a media type comprises of key-value pairs per lane that is expected to be programmed when an optics or DAC is used. Examples of key value pairs include pre-emphasis, idriver and ipredriver. +              The media settings file device/vendor-name/ONIE_PLATFORM_STRING/media_settings.json needs to be defined by each vendor who want to use this mechanism. All the SKUs of the platform share this media_settings.json file. If there is no such file, then this mechanism will not be used. Thus if some vendors want to disable this mechanism, not defining a media_settings.json file should be sufficient. + +              This file contains the list of optics and DAC media-based settings for each port in the device. Each media setting for a media type comprises of key-value pairs per lane that is expected to be programmed when an optics or DAC is used. Examples of key value pairs include pre-emphasis, idriver and ipredriver.               Below example shows the media-based settings for a device on a Broadcom based platform.  For each port the list of supported optics and DAC types are defined (uniquely identified by media type key). For each media type the list of supported vendors (uniquely identified by vendor key) is defined. Each vendor key which will in turn contain the key value pairs per lane that needs to be programmed.               The media type key defined in the file will be comprised of compliance code and length string or simply compliance code if length does not apply (e.g. 40GBASE-CR4-3M or 40GBASE-SR4). -              The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (Ethernet0-Ethern120) or a list(Ethernet0,Ethernet4,Ethernet8) or a list of ranges(Ethernet0-Ethernet20,Ethernet40-Ethernet60) of logical ports. The second block is port level settings where the key comprises of a single logical port. +              The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (1-32) or a list(1,2,3) or a list of ranges(1-10,20-30) of front panel port number. The second block is port level settings where the key comprises of a single port number. -              When a media is detected, the logical port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. +              When a media is detected, the front panel port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. -              In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port Ethernet0 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key +              In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port 1 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key ### Sample Media settings file: ``` {     "GLOBAL_MEDIA_SETTINGS": { -        "Ethernet0-Ethernet124": { +        "1-32": {             "AMPHENOL-1234": {                 "preemphasis": {                     "lane0":"0x001234", @@ -75,7 +77,7 @@         }     },     "PORT_MEDIA_SETTINGS": { -        "Ethernet0": { +        "1": {             "Default": {                 "preemphasis": {                     "lane0":"0x112233", @@ -112,7 +114,7 @@ ## Flow: -              When a media is detected in xcvrd daemon, it constructs the key identifier string as discussed above and searches the media_settings.json file. If found the key value pairs are fetched. The xcvrd daemon notifies these key value pairs along with the alias port to portsorch. The portsorch task will convert the alias to SAI object Id and notifies the syncd by doing port attribute set of corresponding settings. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware. +              When a media is detected in xcvrd daemon, it constructs the key identifier string as discussed above and searches the media_settings.json file. If found the key value pairs are fetched. The xcvrd daemon notifies these key value pairs along with the logical port to portsorch. The logical ports are derived from the physical port in the xcvrd daemon. The portsorch task will convert the logical port to SAI object Id and notifies the syncd by doing port attribute set of corresponding settings. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware.               The notification of hardware profile from xcvrd to portsorch task will be done during initialization and during media detect event. This is not required during media removal event. Since the media settings are required only for the proper functioning of the optics or DAC, the handling can be restricted to media insert event alone and no action needs to be taken during media removal. @@ -124,10 +126,50 @@ ## Breakout Scenario: +              For breakout scenario, there is no special handling or modification that needs to be done to media_settings.json. Currently breakout in SONiC is done by modifying port_config.ini and platform related files and doing a config reload. This config reload will stop and restart most of the daemons. Thus this sequence will be similar to the normal reboot sequence. When xcvrd is stopped and restarted it notifies portsorch about all media just as in normal reboot scenario. + +              The breakout media is listed either in global or port level section with appropriate number of lanes corresponding to the type. On media detection, the number of lanes per logical port and number of lanes listed in the media_settings.json file would match and thus this will be a normal scenario. For example if a 2X50G DAC media is detected on a port, each logical port would have two lanes and the media settings file would have two lanes defined as below and those those would be fetched and communicated to portsorch task. -              For breakout the particular media, if it has a global value is listed in the media_settings.json with appropriate lane values. If the values are specific to a port, then the entry is listed under the port. If the logical port is going to be created after breakout (E.g Ethernet0 is modified to Ethernet0,Ethernet1,Ethernet2,Ethernet3) those corresponding ports are listed in the ports section in media_settings.json. In the current breakout scenario, when port_config.ini is modified and a config reload is done, the flow will be similar to bootup sequence and thus all the media settings will be pushed from xcvrd to portsorch on restart during config apply. +``` +{ +    "GLOBAL_MEDIA_SETTINGS": { +        "1-32": { +            "AMPHENOL-2250": { +                "preemphasis": { +                    "lane0":"0x001234", +                    "lane1":"0x001234" +                }, +                "idriver": { +                    "lane0":"0x2", +                    "lane1":"0x2" +                } +            } + } + } +} +``` + +              If there is no match for the media type or vendor PN detected, the media will be programmed with the default values listed in the port section for the particular physical port. However the values listed in media_settings.json for the physical port will be in four lane format. Thus for 2X50 breakout mode where there are two logical ports, the first two lanes in the key value pairs are associated with the first logical port and the next two lanes are associated with the next logical port. xcvrd will take care of these mapping and communicate the final logical ports with key value pairs and appropriate number of lanes to portsorch +``` +{ +    "PORT_MEDIA_SETTINGS": { +        "1": { +            "Default": { +                "preemphasis": { +                    "lane0":"0x001231", +                    "lane1":"0x001232", + "lane2":"0x001233", + "lane3":"0x001234", +                } +            } + } + } +} +``` +              In the above case if the port 1 is in 2X50 mode with the logical ports Ethernet0 and Ethernet2 and the detected media type is unknown, xcvrd assigns pre-emphasis values 0x001231, 0x001232 to Ethernet0 and 0x001233, 0x001234 to Ethernet4 and communicates to portsorch + ## SAI Attributes: From 688514df4958fba70d7f6ff997b9f13fb5ec3a71 Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Tue, 14 May 2019 18:55:11 -0700 Subject: [PATCH 8/9] Update Media-based-Port-settings.md Modified few places according to latest design. --- doc/media-settings/Media-based-Port-settings.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index b10d239dbc..92d09ff957 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -24,11 +24,11 @@               The media type key defined in the file will be comprised of compliance code and length string or simply compliance code if length does not apply (e.g. 40GBASE-CR4-3M or 40GBASE-SR4). -              The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (1-32) or a list(1,2,3) or a list of ranges(1-10,20-30) of front panel port number. The second block is port level settings where the key comprises of a single port number. +              The file comprises of two blocks. The first block is for global level settings, where all or multiple ports can be presented as keys. The multiple ports can be represented as a range (1-32) or a list(1,2,3) or a list of ranges(1-10,20-30) of index number in port_config.ini. The second block is port level settings where the key comprises of a single port number. -              When a media is detected, the front panel port is identified. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. +              When a media is detected, the front panel port is identified and index number is derived. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. -              In the port based settings block, the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port 1 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key +              In the port based settings block, the index number of the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port 1 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key. ### Sample Media settings file: @@ -114,9 +114,9 @@ ## Flow: -              When a media is detected in xcvrd daemon, it constructs the key identifier string as discussed above and searches the media_settings.json file. If found the key value pairs are fetched. The xcvrd daemon notifies these key value pairs along with the logical port to portsorch. The logical ports are derived from the physical port in the xcvrd daemon. The portsorch task will convert the logical port to SAI object Id and notifies the syncd by doing port attribute set of corresponding settings. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware. +              When a media is detected in xcvrd daemon, it constructs the key identifier string as discussed above and searches the media_settings.json file. If found the key value pairs are fetched. The xcvrd daemon then sets the keys with values on appl_db PORT_TABLE. The logical ports are derived from the index number in the xcvrd daemon. The portsorch task will convert the logical port to SAI object Id and notifies the syncd by doing port attribute set of corresponding keys obtained from xcvrd. Syncd invokes the SAI port set those attribute with specified values. The SAI implementation then programs the attribute into the hardware. -              The notification of hardware profile from xcvrd to portsorch task will be done during initialization and during media detect event. This is not required during media removal event. Since the media settings are required only for the proper functioning of the optics or DAC, the handling can be restricted to media insert event alone and no action needs to be taken during media removal. +              The notification of hardware profile from xcvrd to portsorch task will be done during initialization and during media detect event. However this notification will not happen during warm-reboot. This notification is also not required during media removal event. Since the media settings are required only for the proper functioning of the optics or DAC, the handling can be restricted to media insert event alone and no action needs to be taken during media removal.               This mechanism is also very helpful in supporting new media types without upgrading the Operating system. If a new media type need to be supported the only change that needs to be done is modify media_settings.json to add the new media type. From 0e2ad60f3026d1db4520a9d339f5457a417481ef Mon Sep 17 00:00:00 2001 From: "Sudharsan D.G" Date: Tue, 4 Jun 2019 08:35:45 -0700 Subject: [PATCH 9/9] Update Media-based-Port-settings.md Updated with latest design. Included default at global level, supporting multiple ranges at global level. --- .../Media-based-Port-settings.md | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/doc/media-settings/Media-based-Port-settings.md b/doc/media-settings/Media-based-Port-settings.md index 92d09ff957..8e71f1dad4 100644 --- a/doc/media-settings/Media-based-Port-settings.md +++ b/doc/media-settings/Media-based-Port-settings.md @@ -28,7 +28,7 @@               When a media is detected, the front panel port is identified and index number is derived. First the global level is looked up and if there is a range or list that the port false within is found, then the vendor key (vendor name + vendor PN) as well as media_key (media type + specification compliance + length) is constructed and looked up at the next level. First Vendor key (eg. AMPHENOL-1234) is looked and If there is an exact match then those values are fetched and returned. If vendor key doesn't match, then media key (eg. QSFP28-40GBASE-CR4-1M) is looked and if there is a match then those values are fetched and returned. The purpose of having a media key is to have default values for a media type across vendors. A no-match on vendor and media keys will make the search fall back to individual port based block from global block. -              In the port based settings block, the index number of the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port 1 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key. +              In the port based settings block, the index number of the port on which it is detected is identified at the first level. At second level, the Vendor key is and media key are derived as earlier (e.g. DELL-0123, QSFP28-40GBASE-SR4).  If there is no exact match for vendor key or media key, then the default value listed is chosen. Below is an example for json file for a specific port. For the port 1 a Vendor specific media type and a 'Default' media type is defined apart from global section containing vendor key as well as media key. The 'Default' media type can also be defined at a global section for a range of ports, if multiple ports have same default values. ### Sample Media settings file: @@ -74,7 +74,23 @@                     "lane1":"0x1"                 }             } -        } +        }, + "2,4,6,8": { + "Default": { +                "preemphasis": { +                    "lane0":"0x612233", +                    "lane1":"0x512233", +                    "lane2":"0x412244", +                    "lane3":"0x343322" +                }, +                "idriver": { +                    "lane0":"0x1", +                    "lane1":"0x2", +                    "lane2":"0xd", +                    "lane3":"0x1" +                } + } + }     },     "PORT_MEDIA_SETTINGS": {         "1": {