Understanding gRPC

gRPC is a general open-source RPC software framework that runs over HTTP/2 and features high performance. Both communication parties perform secondary development based on the framework, so that they focus on services and do not need to pay attention to underlying communication implemented by the gRPC software framework.

Telemetry uses the gRPC protocol to report the data encapsulated in an encoding format to the collector. For details about the gRPC protocol stack structure, see Figure 1.

GRPC-based Interconnection Mode

To implement the telemetry function, the device supports the dial-in and dial-out modes based on gRPC.

  1. Dial-in mode: The device functions as a gRPC server, and the collector functions as a gRPC client. After the collector initiates a gRPC request and establishes a gRPC connection with the device, the device periodically returns the collected data to the collector along the original path. The dial-in mode applies to small-scale networks and scenarios where the collector needs to deliver configurations to devices.
    The following operations can be performed in dial-in mode:
    • Capabilities: obtains device capability data. Currently, only the Capabilities operation based on the gRPC Network Management Interface (gNMI) specification is supported.
    • Set: delivers configurations to a device. Currently, only the set operation based on the gNMI specification is supported.
    • Get: obtains the device running status and configuration. Currently, only the get operation based on the gNMI specification is supported.
    • Subscribe: collects data such as interface traffic statistics, CPU usage, and memory usage of the device at a high speed.
  2. Dial-out mode: The device functions as a gRPC client, and the collector functions as a gRPC server. After telemetry sampling is configured on a device, the device proactively establishes a gRPC connection with the target collector and pushes the subscribed data to the collector. This mode applies to large-scale networks

    and only allows the subscribe operation to be performed.

Proto file

The data model layer in the gRPC protocol stack consists of the RPC layer, telemetry layer, and service data layer, which are defined in different .proto files. To establish a gRPC connection between the collector and a device, use the .proto files for interconnection. The .proto files on the two ends must be the same, which facilitates decoding.
  • huawei-grpc-dialout.proto is the RPC header file. When a device functions as the client to push data, this file defines the RPC interface. The following table describes the file content and meaning.

    huawei-grpc-dialout.proto

    syntax = "proto3";                          //The .proto file version is defined as v3. 
    package huawei_dialout;                     //The package name is huawei_dialout. 
    service gRPCDataservice {                   //The service name is gRPCDataservice. 
        rpc dataPublish(stream serviceArgs) returns(stream serviceArgs) {};                 //The method name is dataPublish, providing the data push method. The working mode is bidirectional stream mode. The input parameter is the serviceArgs data flow. 
    }
    message serviceArgs {                       //Message format description. 
        int64 ReqId = 1;                        //Request ID.
        oneof MessageData {
            bytes data = 2;         //Sampled data in GPB encoding format is carried.
            string data_json = 4;   //Sampled data in JSON encoding format is carried.
        }
        string errors = 3;         //Error description.
    }
  • huawei-grpc-dialin.proto is the RPC header file. When a device functions as the server to push data, this file defines the RPC interface. The following table describes the file content and meaning.

    huawei-grpc-dialin.proto

    syntax = "proto3";                           //The .proto file version is defined as v3.
    package huawei_dialin;                     //The package name is huawei_dialin.
    service gRPCConfigOper {                   //The service name is gRPCConfigOper.
        rpc Subscribe (SubsArgs) returns (stream SubsReply) {}; //The method is Subscribe, and the server stream mode is used, providing the dynamic subscription method. The input parameter SubsArgs contains subscribing parameters.
        rpc Cancel (CancelArgs) returns (CancelReply) {}; //The method is Cancel, and the query and response mode is used, providing the method of canceling dynamic subscription. The input parameter CancelArgs contains unsubscribing parameters.
    }
    message Path {                //Path message structure.
        string path = 1;          //Subscribed sensor-path.
        uint32 depth = 2;         //Sampling depth of the subscribed sensor-path. The value 1 indicates the current level, and the value 2 indicates the current level and its sub-level, and so on.
    }
    message SubsArgs {            //Subscribing request parameter.
        uint64 request_id = 1;    //Request ID, which is transferred by the invoker.
        uint32 encoding = 2;      //Encoding type. 0: GPB encoding; 1: JSON encoding.
        repeated Path path = 5;   //Subscribed path structure.
        uint64 sample_interval = 6; //Sampling interval.
        uint64 heartbeat_interval = 7; //Redundancy suppression interval. This parameter is valid only when suppress_redundant is set to 1.
        oneof Suppress {
            bool suppress_redundant = 8;  //Redundancy suppression. The sampled data is not reported if the data content remains unchanged. 0: disabled; 1: enabled.
            uint64 delay_time = 9;        //Delay, which ranges from 100 ms to 60000 ms. When data change occurs, new data will be reported after this delay. The data changes that occur during the delay will be reported together. This prevents massive data generated due to service flapping from being reported.
        }
    }
    message SubsReply {            //Subscribing response parameter.
        uint32 subscription_id = 1; //If the subscribing is successful, the subscription ID is returned. If the subscribing fails, 0 is returned.
        uint64 request_id = 2;        //ID of the subscribing request.
        string response_code = 3; //Return code. The value 200 indicates a success.
        oneof MessageData {
            bytes message = 4;        //If an error occurs, the error description is returned. If no error occurs, the GPB encoding data is sent.
            string message_json = 5;  //If no error occurs, the JSON encoding data is sent. 
        }
    }
    message CancelArgs {            //Unsubscribing request parameter.
        uint64 request_id = 1;    //Request ID, which is transferred by the invoker.
        uint32 subscription_id = 2;   //ID of the subscription to be canceled.
    }
    message CancelReply {            //Unsubscribing response parameter.
        uint64 request_id = 1;    //Request ID, which is transferred by the invoker.
        string response_code = 2; //Return code. The value 200 indicates a success.
        string message = 3;            //Error description.
    }
  • huawei-telemetry.proto is the telemetry header definition file. It defines the data header when telemetry data sampled is sent, including key information, such as the sampling path and sampling timestamp. The following table describes the file content and meaning.

    huawei-telemetry.proto

    syntax = "proto3";         //The .proto file version is defined as v3. 
    package telemetry;                          //The package name is telemetry. 
    message Telemetry {                         //Telemetry message structure definition. 
       string node_id_str = 1;                     //Device name.
       string subscription_id_str = 2;   //Static subscription name.
       string sensor_path = 3;           //Subscription path.
       string proto_path = 13;          //Message path for the sampling path in the proto file.
       uint64 collection_id = 4;         //Sampling round.
       uint64 collection_start_time = 5;//Start time of a sampling round.
       uint64 msg_timestamp = 6;        //Timestamp when the message is generated.
       TelemetryGPBTable data_gpb = 7; //Carried data is defined by TelemetryGPBTable.
       uint64 collection_end_time = 8;  //End time of a sampling round.
       uint32 current_period = 9;       //Sampling precision, in milliseconds.
       string except_desc = 10;        //Exception description, which is reported when a sampling exception occurs.
       string product_name = 11;       //Product name.
       enum Encoding {
        Encoding_GPB = 0;        //GPB encoding format.
        Encoding_JSON = 1;       //JSON encoding format.
      };
      Encoding encoding = 12;    //Data encoding format. If the GPB encoding format is used, the data_gpb field is valid. Otherwise, the data_str field is valid.
      string data_str = 14;   //This field is valid only when a non-GPB encoding format is used.
      string ne_id = 15;               //Unique NE ID, which identifies the NE to which data belongs in the gateway scenario.
      string software_version = 16;    //Software version number.
    }
    message TelemetryGPBTable {                 //TelemetryGPBTable message structure definition. 
      repeated TelemetryRowGPB row = 1;     //Array definition. Its member is TelemetryRowGPB structure.
      repeated DataPath delete = 2;      //Deletes a data path.
      Generator generator = 3;           //Data source description, which applies to the OnChange+ service that requires high reliability.
    }
    message Generator {
       uint64 generator_id = 1;         //Data source ID. Multiple data sources can provide data concurrently and maintain their own reliability.
       uint32 generator_sn = 2;         //Message sequence number. The sequence numbers of messages sent by each data source must be consecutive. If the sequence numbers are not consecutive, data out-of-synchronization occurs. In this case, the collector must be automatically disconnected from the device and re-connected. The value ranges from 0 to 0xFFFFFFFF and can be reversed.
       bool generator_sync = 3;         //Data source synchronization. The value true indicates that full OnChange data is being synchronized. In addition, if the value is true and no data is contained, the synchronization is complete.
    }
    message TelemetryRowGPB {
    uint64 timestamp = 1;            //Timestamp of the current sampling instance.
       bytes content = 11;              //Sampling instance data carried. It is used with the sensor_path field to determine which .proto file is used for encoding.
    }
    message DataPath {
       uint64 timestamp = 1;            //Timestamp of the current sampling instance. 
       Path path = 2;                   //Data tree node, which contains only the data path and key field information.
    }
    message Path {
       repeated PathElem node = 1;      //   repeated PathElem node = 1;      //Data tree node, which contains only the data path and key field information. 
    }
    message PathElem {
      string name = 1;                  //Data tree node name.
      map<string, string> key = 2;      //Key field name and value mapping table of the data tree node.
    }
    message TelemetrySelfDefinedEvent {
      string path = 1;         //Sampling path that triggers the customized event, which describes the method of parsing the content.
      string proto_path = 13;  //Message path for the sampling path in the proto file.
      uint32 level = 2;        //Level of the user-defined event.
      string description = 3;  //Description of the user-defined event.
      string fieldName = 4; //Name of the field that triggers the customized event.
      uint32 fieldValue = 5;   //Value of the field that triggers the customized event.
      TelemetrySelfDefineThresTable data_threshold = 6; //Threshold filter criteria when the customized event is triggered.
      enum ThresholdRelation {
          ThresholdRelation_INVALID = 0; //The relationship between thresholds is not configured.
          ThresholdRelation_AND = 1; //The relationship between thresholds is And.
          ThresholdRelation_OR = 2; //The relationship between thresholds is Or.
      }
      ThresholdRelation thresholdRelation = 7; //Relationship between threshold filter criteria when the customized event is triggered.
      bytes content = 8; //Sampled data that triggers the customized event.
    }
    message TelemetrySelfDefineThresTable {
      repeated TelemetryThreshold row = 1; //Multiple thresholds are included.
    }
    message TelemetryThreshold {
      uint32 thresholdValue = 1; //Delivered threshold.
      enum ThresholdOpType {
          ThresholdOpType_EQ = 0; //The actual value in the data sent equals to the configured data threshold.
          ThresholdOpType_GT = 1; //The actual value in the data sent is greater than the configured data threshold.
          ThresholdOpType_GE = 2; //The actual value in the data sent is greater than or equals to the configured data threshold.
          ThresholdOpType_LT = 3; //The actual value in the data sent is less than the configured data threshold.
          ThresholdOpType_LE = 4; //The actual value in the data sent is less than or equals to the configured data threshold.
      }
      ThresholdOpType thresholdOpType = 2; //Threshold on the device.
    }
  • A service data file describes the detailed service data formats. For details, see NetEngine 8000 F V800R021C00SPC100 Telemetry Performance Indicator List.

gRPC Data Processing Based on gNMI

As shown in Figure 1, in dial-in mode, gRPC provides data configuration, query, and subscription functions using the Capabilities, Set, Get, and Subscribe methods defined in the gRPC Network Management Interface (gNMI) protocol.

Figure 1 gRPC Data Processing Based on gNMI
  • Capabilities

    The Capabilities method is used to obtain device model capabilities. Its process is as follows:

    1. The gRPC client sends an RPC request (Capabilities) defined in the gNMI protocol.
    2. The gRPC server parses the request packet and detects that a Capabilities method is used in the RPC request.
      • Operation authentication: All users who pass authentication can use the Capabilities method to obtain device capabilities.
      • Log recording: The gRPC server records logs.
    3. The gRPC server obtains the existing model capability set on the device. The model information includes:
      • Model name, for example, openconfig-interfaces.
      • Organization, for example, OpenConfig workinggroup.
      • Model version, such as 2018-11-23 and 1.0.0.
    4. The gRPC server returns the capability set to the client.
    • If the YANG model changes due to a patch installation, the gRPC detects the patch. It will uninstall and reload the XSMLIB resource file, load the new YANG mode, and make the model take effect.
    • If the Capabilities method contains unimplemented parameters, parameters fail verification, or an error occurs on the model obtaining interface, the gRPC server records a Capabilities method execution failure log and waits for the client to re-send a correct Capabilities request.
    • If the command queuing time reaches the time set on the client, gRPC proactively terminates the RPC request and waits for the command to be delivered again.

    The Capabilities packet format is as follows:

    # Response packet
    ++++++++ Recevied get response: ++++++++
     supported_models:{
    name:"openconfig-interfaces" 
    organization:"OpenConfig workinggroup" 
    version:"2.3.0"
    }
    supported_models:{
    name:"huawei-ifm"
    organization:"Huawei Technologies Co.,Ltd." 
    version:"2018-11-23"
    }
    supported_encodings:JSON
    gNMI_version:"0.7.0"
  • Set

    The Set method can be used to deliver configurations to the device. The process is as follows:

    1. The gRPC client sends an RPC request (Set) defined in the gNMI protocol.
      • gNMI defines the RPC method and packet structure in the gnmi.proto file. To obtain the gnmi.proto file, see Obtaining the gnmi.proto File.
      • The Set method is carried by service data and needs to be encoded using JSON_VAL. Each field can carry a namespace. If no namespace is carried, the namespace of the parent container node is inherited by default.
      • The Set method includes the following parameters.
        Table 1 Parameters in the Set method

        Parameter

        Description

        DELETE

        Corresponds to NETCONF <delete> and is used to delete configuration data.

        REPLACE

        Corresponds to NETCONF <replace> and is used to replace configuration data.

        UPDATE

        Corresponds to NETCONF <merge> and is used to update or create configuration data.

    2. The gRPC server delivers a request for modifying device data.
      • Operation authentication: During a Set operation, the system performs authentication to check whether the user has sufficient permission to access the specified path. If the authentication fails, the system returns an authentication failure error and terminates the operation.
      • Log recording: The gRPC server records operation logs that contain service data. Sensitive information in the service data will be shielded.
      • Transaction management: When a request packet carries multiple operations such as the delete, replace, and update operations, the gRPC server sequentially performs the operations in compliance with the gNMI protocol. Operations take effect when they are all successfully performed. If any operation fails, all operations do not take effect and a failure message is returned.
      • Object operation: The Set operation can be performed on a container and its sub-nodes, or on a leaf node.
      • Capacity: The maximum size of a request packet is 1 MB.
    3. The gRPC server returns data to the client.

    If some operations in a request fail, all operations in the request do not take effect.

    The Set packet format is as follows:

    • For the delete operation, the input path is huawei-ifm:ifm/interfaces/interface[ifName=Loopback1].
      # Request packet
      ++++++++ Sending set request: ++++++++
      path {
        elem {
          name: "huawei-ifm:ifm"
        }
        elem {
          name: "interfaces"
        }
        elem {
          name: "interface"
          key {
            key: " ifName"
            value: "Loopback1"
          }
        }
      }
      # Response packet
      ++++++++ Recevied set response: ++++++++
      response : {
        path {
          elem {
            name: "huawei-ifm:ifm"
          } 
          elem {
            name: "interfaces"
          }
          elem {
            name: "interface"
            key {
              key: "ifName"
              value: "Loopback1"
          }
        }
      }
      op: DELETE
      }
      timestamp: 159207901002054000
    • Replace operation (without a key)
      • The input path is huawei-ifm:ifm/interfaces/interface.
      • Input data in JSON format:
        {\n\t\"ifName\":\t\"LoopBack1\",
        \n\t\"ifPhyType\":\t\"LoopBack\",
        \n\t\"ifNumber\":\t\"1\",
        \n\t\"ifAdminStatus\":\t\"up\",
        \n\t\"ifLinkProtocol\":\t\"invalid\",
        \n\t\"ifRouterType\":\t\"PtoP\",
        \n\t\"ifDf\":\tfalse,
        \n\t\"ifTrapEnable\":\ttrue,
        \n\t\"ifMtu\":\t1500,
        \n\t\"l2SubIfFlag\":\tfalse,
        \n\t\"ifClass\":\t\"mainInterface\",
        \n\t\"ifNetworkLayerStatus\":\t\"ipv4andipv6up\",
        \n\t\"ifControlFlap\":\t{\n\t\t\"ifCtrlFlapEnbl\":\tfalse\n\t},
        \n\t\"ipv4Config\":\t{\n\t\t\"addrCfgType\":\t\"config\"\n\t},
        \n\t\"ipv6Config\":\t{\n\t\t\"enableFlag\":\tfalse,
        \n\t\t\"autoLinkLocal\":\tfalse\n\t}\n}
      # Request packet
      ++++++++ Sending set request: ++++++++
      path {
        elem {
          name: "huawei-ifm:ifm"
        }
        elem {
          name: "interfaces"
        }
        elem {
          name: "interface"
        }
        val {
          json_val: "{\n\t\"ifName\":\t\"LoopBack1\",
          \n\t\"ifPhyType\":\t\"LoopBack\",
          \n\t\"ifNumber\":\t\"1\",
          \n\t\"ifAdminStatus\":\t\"up\",
          \n\t\"ifLinkProtocol\":\t\"invalid\",
          \n\t\"ifRouterType\":\t\"PtoP\",
          \n\t\"ifDf\":\tfalse,
          \n\t\"ifTrapEnable\":\ttrue,
          \n\t\"ifMtu\":\t1500,
          \n\t\"l2SubIfFlag\":\tfalse,
          \n\t\"ifClass\":\t\"mainInterface\",
          \n\t\"ifNetworkLayerStatus\":\t\"ipv4andipv6up\",
          \n\t\"ifControlFlap\":\t{\n\t\t\"ifCtrlFlapEnbl\":\tfalse\n\t},
          \n\t\"ipv4Config\":\t{\n\t\t\"addrCfgType\":\t\"config\"\n\t},
          \n\t\"ipv6Config\":\t{\n\t\t\"enableFlag\":\tfalse,
          \n\t\t\"autoLinkLocal\":\tfalse\n\t}\n}"
        }
      }
      # Response packet
      ++++++++ Recevied set response: ++++++++
      response : {
        path {
          elem {
            name: "huawei-ifm:ifm"
          }
          elem {
            name: "interfaces"
          }
          elem {
            name: "interface"
          }
        }
        op: REPLACE
      }
      timestamp: 1592245848404176000
    • Replace operation (with a key)
      • The input path is huawei-ifm:ifm/interfaces/interface[ifName=Loopback1].
      • Input data in JSON format:
        {\n\t\"ifPhyType\":\t\"LoopBack\",
        \n\t\"ifNumber\":\t\"1\",
        \n\t\"ifAdminStatus\":\t\"up\",
        \n\t\"ifLinkProtocol\":\t\"invalid\",
        \n\t\"ifRouterType\":\t\"PtoP\",
        \n\t\"ifDf\":\tfalse,
        \n\t\"ifTrapEnable\":\ttrue,
        \n\t\"ifMtu\":\t1500,
        \n\t\"l2SubIfFlag\":\tfalse,
        \n\t\"ifClass\":\t\"mainInterface\",
        \n\t\"ifNetworkLayerStatus\":\t\"ipv4andipv6up\",
        \n\t\"ifControlFlap\":\t{\n\t\t\"ifCtrlFlapEnbl\":\tfalse\n\t},
        \n\t\"ipv4Config\":\t{\n\t\t\"addrCfgType\":\t\"config\"\n\t},
        \n\t\"ipv6Config\":\t{\n\t\t\"enableFlag\":\tfalse,
        \n\t\t\"autoLinkLocal\":\tfalse\n\t}\n}
      # Request packet
      ++++++++ Sending set request: ++++++++
      path {
        elem {
          name: "huawei-ifm:ifm"
        }
        elem {
          name: "interfaces"
        }
        elem {
          name: "interface"
          key {
            key: "ifName"
            value: "Loopback1"
          }
        }
        val {
          json_val: "{\n\t\"ifPhyType\":\t\"LoopBack\",
          \n\t\"ifNumber\":\t\"1\",
          \n\t\"ifAdminStatus\":\t\"up\",
          \n\t\"ifLinkProtocol\":\t\"invalid\",
          \n\t\"ifRouterType\":\t\"PtoP\",
          \n\t\"ifDf\":\tfalse,
          \n\t\"ifTrapEnable\":\ttrue,
          \n\t\"ifMtu\":\t1500,
          \n\t\"l2SubIfFlag\":\tfalse,
          \n\t\"ifClass\":\t\"mainInterface\",
          \n\t\"ifNetworkLayerStatus\":\t\"ipv4andipv6up\",
          \n\t\"ifControlFlap\":\t{\n\t\t\"ifCtrlFlapEnbl\":\tfalse\n\t},
          \n\t\"ipv4Config\":\t{\n\t\t\"addrCfgType\":\t\"config\"\n\t},
          \n\t\"ipv6Config\":\t{\n\t\t\"enableFlag\":\tfalse,
          \n\t\t\"autoLinkLocal\":\tfalse\n\t}\n}"
        }
      }
      # Response packet
      ++++++++ Recevied set response: ++++++++
      response : {
        path {
          elem {
            name: "huawei-ifm:ifm"
          }
          elem {
            name: "interfaces"
          }
          elem {
            name: "interface"
            key {
              key: "ifName"
              value: "Loopback1"
            }
          }
        }
        op: REPLACE
      }
      timestamp: 1592246188782490000
    • Update operation (without a key)
      • The input path is huawei-ifm:ifm/interfaces/interface.
      • The input data in JSON format is {\"ifName\":\"Loopback1\", \"ifDescr\":\"testForUpdate\"}.
      # Request packet
      ++++++++ Sending set request: ++++++++
      path {
        elem {
          name: "huawei-ifm:ifm"
        }
        elem {
          name: "interfaces"
        }
        elem {
          name: "interface"
        }
        val {
          json_val: "{\"ifName\":\"Loopback1\", \"ifDescr\":\"testForUpdate\"}"
        }
      }
      # Response packet
      ++++++++ Recevied set response: ++++++++
      response : {
        path {
          elem {
            name: "huawei-ifm:ifm"
          }
          elem {
            name: "interfaces"
          }
          elem {
            name: "interface"
          }
        }
        op: UPDATE
      }
      timestamp: 1592246353662332000
    • Update operation (with key)
      • The input path is huawei-ifm:ifm/interfaces/interface[ifName=Loopback1].
      • The input data in JSON format is {\"ifDescr\":\"testForUpdate\"}.
      # Request packet
      ++++++++ Sending set request: ++++++++
      path {
        elem {
          name: "huawei-ifm:ifm"
        }
        elem {
          name: "interfaces"
        }
        elem {
          name: "interface"
          key {
            key: "ifName"
            value: "Loopback1"
          }
        }
        val {
          json_val: "{\"ifDescr\":\"testForUpdate\"}"
        }
      }
      # Response packet
      ++++++++ Recevied set response: ++++++++
      response : {
        path {
          elem {
            name: "huawei-ifm:ifm"
          }
          elem {
            name: "interfaces"
          }
          elem {
            name: "interface"
            key {
              key: "ifName"
              value: "Loopback1"
            }
          }
        }
        op: UPDATE
      }
      timestamp: 1592220455502852000

    Restrictions on leafref: When a parent node is associated with a child node through leafref, these two nodes must be both in a path or defined in JSON_VAL. Otherwise, the operations on these two nodes will be different and will fail to be executed.

    Cause: The operation on nodes in a path is None, while the operation on nodes defined in JSON_VAL is REPLACE or UPDATE. If one of two nodes associated through leafref is in a path and the other is defined in JSON_VAL, operation consistency check will fail.

    For example, in the openconfig-telemetry.yang model, the key defined in the parent node list subscription is subscription-name, which is associated with subscription-name in child node config through leafref. The preceding restriction applies to data in config. If the path is set to:

    "openconfig-telemetry:telemetry-system/subscriptions/persistent/subscription[subscription-name=abc]

    Define JSON_VAL as:

    {"config": {"originated-qos-marking": "30","encoding":"openconfig-telemetry-types:ENC_PROTO3"}}

    The following error is returned:

    The target node of the leafref type and the source node have different operations.

    To rectify the error, set the path to:

    "openconfig-telemetry:telemetry-system/subscriptions/persistent/subscription[subscription-name=abc]/config"

    Define JSON_VAL as:

    {"originated-qos-marking": "30","encoding":"openconfig-telemetry-types:ENC_PROTO3"}

    In this case, the parent and child nodes associated through leafref are both in a path and can be correctly executed.

  • Get

    You can perform the Get operation to obtain the running status and configuration of a device. The procedure is as follows:

    1. The gRPC client sends an RPC request (Get) defined in the gNMI protocol.
      • gNMI defines the RPC method and packet structure in the gnmi.proto file. To obtain the gnmi.proto file, see Obtaining the gnmi.proto File.
      • The Get method uses JSON to encode service data. The gRPC server parses the request packet and detects that the RPC is a Get method to implement operation authentication.
      • The Get method includes the following parameters.
        Table 2 Parameters of the Get operation

        Parameter

        Description

        ALL

        Corresponds to NETCONF <get> and includes configuration data and status data.

        CONFIG

        Corresponds to NETCONF <get-config> and includes configuration data.

    2. The gRPC server queries data.
      • Operation authentication: During a Get operation, the system performs authentication to check whether the user has sufficient permission to access the specified path. If the authentication fails, the system returns an authentication failure error and terminates the operation.
      • Log recording: The gRPC server records operation logs that contain service data. Sensitive information in the service data will be shielded.
      • Transaction management: Query for multiple paths in a request packet is supported. All path query results are returned only after the query is complete. If an error occurs (for example, NotFound) during the query for multiple paths, the query is terminated, an error message is displayed, and all cached query results are discarded.
      • Object: The Get operation can be performed on a container and its sub-nodes, or on a leaf node.
      • Capacity: The maximum size of a response packet is 20 MB. If the maximum size is exceeded, an error is reported.

      If some commands fail to be executed, the query stops after the commands are returned. RPC returns an error and does not return the query result. It waits for the client issues the correct command again.

    The Get packet format is as follows:

    • For the container or list node, the input path is huawei-ifm:ifm/interfaces/interface[ifName=Loopback1].
      # Request packet
      ++++++++ Sending get request: ++++++++
      path {
        elem {
          name: "huawei-ifm:ifm"
        }
        elem {
          name: "interfaces"
        }
        elem {
          name: "interface"
          key {
            key: "ifName"
            value: "Loopback1"
          }
        }
      }
      type: CONFIG
      encoding: JSON
      # Response packet
      notification {
        timestamp: 1591901665078236000
        update {
          path {
            elem {
              name: "huawei-ifm:ifm"
            }
            elem {
              name: "interfaces"
            }
            elem {
              name: "interface"
              key {
                key: "ifName"
                value: "Loopback1"
              }
            }
          }
          val {
            json_val: "{\n\t\"ifPhyType\":\t\"LoopBack\",
            \n\t\"ifNumber\":\t\"1\",
            \n\t\"ifAdminStatus\":\t\"up\",
            \n\t\"ifLinkProtocol\":\t\"invalid\",
            \n\t\"ifRouterType\":\t\"PtoP\",
            \n\t\"ifDf\":\tfalse,
            \n\t\"ifTrapEnable\":\ttrue,
            \n\t\"ifMtu\":\t1500,
            \n\t\"l2SubIfFlag\":\tfalse,
            \n\t\"ifClass\":\t\"mainInterface\",
            \n\t\"ifNetworkLayerStatus\":\t\"ipv4andipv6up\",
            \n\t\"ifControlFlap\":\t{\n\t\t\"ifCtrlFlapEnbl\":\tfalse\n\t},
            \n\t\"ipv4Config\":\t{\n\t\t\"addrCfgType\":\t\"config\"\n\t},
            \n\t\"ipv6Config\":\t{\n\t\t\"enableFlag\":\tfalse,
            \n\t\t\"autoLinkLocal\":\tfalse\n\t}\n}"
          }
        }
      }
    • For the leaf node, the input path is huawei-ifm:ifm/interfaces/interface[ifName=Loopback1]/ifDescr.
      # Request packet
      ++++++++ Sending get request: ++++++++
      path {
        elem {
          name: "huawei-ifm:ifm"
        }
        elem {
          name: "interfaces"
        }
        elem {
          name: "interface"
          key {
            key: "ifName"
            value: "Loopback1"
          }
        }
        elem {
            name: "ifDescr"
        }
      }
      encoding: JSON
      # Response packet
      notification {
        timestamp: 1591901665078236000
        update {
          path {
            elem {
              name: "huawei-ifm:ifm"
            }
            elem {
              name: "interfaces"
            }
            elem {
              name: "interface"
              key {
                key: "ifName"
                value: "Loopback1"
              }
            }
            elem {
              name: "ifDescr"
            }
          }
          val {
            json_val: "\"test\""
          }
        }
      }
  • Subscribe

    The Subscribe method is used to collect device status and configurations periodically or in event-driven mode. Its process is as follows:

    1. The gRPC client sends an RPC request (Subscribe) defined in the gNMI protocol.
      • gNMI defines the RPC method and packet structure in the gnmi.proto file. To obtain the gnmi.proto file, see Obtaining the gnmi.proto File.
      • The Subscribe method uses JSON/PROTO/JSON_IETF to encode service data.
      • The Subscribe method includes the following parameters.
        Table 3 Parameters in a Subscribe request

        Layer 1 Parameter

        Layer 1 Parameter Description

        Layer 2 Parameter

        Layer 2 Parameter Description

        Prefix

        Prefix.

        path

        Sampling path prefix.

        target

        When the target parameter is set on the client, the response message from the server needs to carry the parameter.

        Subscription

        There can be one or more subscription parameters of this level in a Subscribe request.

        path

        Sampling path.

        mode

        Sampling mode. Currently, the following modes are supported:

        • ON_CHANGE
        • SAMPLE

        sample_interval

        Sampling interval, corresponding to the sampling mode:

        • The sampling interval takes effect only when the sampling mode is SAMPLE.
        • When the sampling mode is ON_CHANGE, the sampling interval must be set to 0.

        SubscriptionListData

        There can be only one subscription parameter of this level in a Subscribe request.

        marking

        Configured DSCP value. The value ranges from 0 to 63.

        mode

        Subscription mode. Currently, STREAM is supported.

        allow_aggregation

        Whether the client allows elements with the aggregation flag to be combined in a Telemetry transmission message. This parameter is valid only in PROTO encoding mode.

        encoding

        Encoding mode. Currently, the following modes are supported:
        • JSON
        • PROTO
        • JSON_IETF

        updates_only

        Only incremental data is sent. This parameter is valid when the device sampling mode is ON_CHANGE+.

        NOTE:

        The device implements ON_CHANGE in either of the following modes:

        • Mode 1: Only incremental data is sent.
        • Mode 2: Full data is sent for the first time, and only incremental data is sent subsequently.
    2. The server parses the request packet, detects that the RPC method is Subscribe, collects data based on the parameters set in the packet, and sends the data to the client.

    The Subscribe packet format is as follows:

    # Subscribe request packet

    ++++++++ Sending subscribe request: ++++++++
    prefix {
    	elem {
    		name: "huawei-debug:debug"
    	}
    	target: "TARGET"
    }
    Subscription {
    	path {
    	  elem {
    		name: "cpu-infos"
    	  }
    	  elem {
    		name: "cpu-info"
    	  }
    	}
    	mode: SAMPLE
    	sample_interval: 1000
    }
    SubscriptionListData {
    	marking: 63
    	mode: STREAM
    	allow_aggregation: false
    	encoding: JSON
    	updates_only: false
    }

    # JSON response packet

    ++++++++ Recevied subscribe response: ++++++++
    <subscibegNMI>: update {
      timestamp: 1626429829051000000
      update {
        path {
          elem {
            name: "huawei-debug:debug"
          }
          elem {
            name: "cpu-infos"
          }
          elem {
            name: "cpu-info"
          }
        }
        val {
          json_val: "[{\"position\":\"17\",\"overload-threshold\":90,\"unoverload-threshold\":75,\"interval\":8,\"index\":17891329,\"system-cpu-usage\":6,\"monitor-number\":48,\"monitor-cycle\":10,\"overload-state-change-time\":\"0000-00-00 00:00:00\",\"current-overload-state\":\"Unoverload\"}]"
        }
      }
      delete {
      }
    }
    
    <subscibegNMI>: sync_response: true

    # PROTO response packet (allow_aggregation = false)

    ++++++++ Recevied subscribe response: ++++++++
    <subscibegNMI>: update {
      timestamp: 1626430004019000000
      prefix {
        elem {
          name: "huawei-debug:debug"
        }
        elem {
          name: "cpu-infos"
        }
        elem {
          name: "cpu-info"
          key {
            key: "position"
            value: "17"
          }
        }
      }
      update {
        path {
          elem {
            name: "overload-threshold"
          }
        }
        val {
          uint_val: 90
        }
      }
      update {
        path {
          elem {
            name: "unoverload-threshold"
          }
        }
        val {
          uint_val: 75
        }
      }
      update {
        path {
          elem {
            name: "interval"
          }
        }
        val {
          uint_val: 8
        }
      }
      update {
        path {
          elem {
            name: "index"
          }
        }
        val {
          uint_val: 17891329
        }
      }
      update {
        path {
          elem {
            name: "system-cpu-usage"
          }
        }
        val {
          uint_val: 3
        }
      }
      update {
        path {
          elem {
            name: "monitor-number"
          }
        }
        val {
          uint_val: 48
        }
      }
      update {
        path {
          elem {
            name: "monitor-cycle"
          }
        }
        val {
          uint_val: 10
        }
      }
      update {
        path {
          elem {
            name: "overload-state-change-time"
          }
        }
        val {
          string_val: "0000-00-00 00:00:00"
        }
      }
      update {
        path {
          elem {
            name: "current-overload-state"
          }
        }
        val {
          string_val: "Unoverload"
        }
      }
      delete {
      }
    }
    
    <subscibegNMI>: sync_response: true

    # PROTO response packet (allow_aggregation = true)

    ++++++++ Recevied subscribe response: ++++++++
    <subscibegNMI>: update {
      timestamp: 1626430056356000000
      update {
        path {
          elem {
            name: "huawei-debug:debug"
          }
          elem {
            name: "cpu-infos"
          }
          elem {
            name: "cpu-info"
          }
        }
        val {
          proto_bytes: "0a023137105a184b2008288180c40830033830400a4a13303030302d30302d30302030303a30303a3030520a556e6f7665726c6f6164"
        }
      }
      delete {
      }
    }
    
    <subscibegNMI>: sync_response: true
  • Common Error Logs
    1. The TLS encryption channel does not support the Capabilities, Set, Get, or Subscribe methods.
      rpc error: code = PermissionDenied desc = Need use tls.
    2. The username or password is incorrect.
      rpc error: code = Unauthenticated desc = Invalid authentication credentials.
    3. Parameters are invalid.
      • The input Path field is invalid.
        rpc error: code = InvalidArgument desc = Argument 'Path' error.
      • The input JSON data is invalid.
        rpc error: code = InvalidArgument desc = The JSON value is invalid.
    4. There is no data.
      rpc error: code = NotFound desc = Not found.
Copyright © Huawei Technologies Co., Ltd.
Copyright © Huawei Technologies Co., Ltd.
< Previous topic