[BMv2] Parse P4runtime_pb2


Because there is no API for register R/W on BMv2, I read register through CPU_IN and CPU_OUT packet. However, when I dumped the data, which type is <class ‘p4.v1.p4runtime_pb2.StreamMessageResponse’>,be like

packet {
  payload: "CNSRL"
  metadata {
    metadata_id: 1
    value: "\377"
  metadata {
    metadata_id: 2
    value: "\242\016>s&"
  metadata {
    metadata_id: 3
    value: "\242\017bZ\300"
  metadata {
    metadata_id: 4
    value: "\242\n\031\241\222"

I think the value field should be hex format but octal and some of them are converted to character(ASCII).

My question is how to parse “value” field and converted into readable data.

Depends on what the data is and what you want to do with it. It’s a bytestring.

If it’s a plain integer, you could use int.from_bytes. For example:

>>> int.from_bytes(b"\377", byteorder="big")
>>> int.from_bytes(b"\242\017bZ\300", byteorder="big")

If you want an hexadecimal string:

>>> b"\242\017bZ\300".hex()

Antonin appreciate your reply!

My final python3 solution as below.

I use str() function convert <class ‘p4.v1.p4runtime_pb2.StreamMessageResponse’> into <class ‘str’>.
Then use regex to extract value fileds

re.findall(r'value: "(.*)(?<!\\)"',str)

Extracted values are strings and have backslash escape character. It can not use int.from_bytes() directly.

value_str = "\\377"

So I did some transfers

value_str = value_str.encode('utf-8').decode('unicode_escape')
value_int = int.from_bytes(bytes(value_str,'latin_1'), byteorder="big")

There is no need to use a regex to parse Protobuf messages…
You are taking a Python object of type p4.v1.p4runtime_pb2.StreamMessageResponse, serializing it to a string, and parsing the string using a regex, all of this to get access to information which is already available as class members of your original object. I find it super confusing.

for metadata in packet.metadata:

Maybe give a quick read to Protocol Buffer Basics: Python  |  Protocol Buffers  |  Google Developers