ygot icon indicating copy to clipboard operation
ygot copied to clipboard

Ygot protomap ProtoFromPaths to convert 2+ levels

Open smslo opened this issue 3 years ago • 3 comments

Currently ProtoFromPaths only convert up to 2 levels. The leaves will be missing when the path input is not exact.

smslo avatar Dec 07 '21 20:12 smslo

This is a TODO item in the code. I will take a look at this.

wenovus avatar Dec 07 '21 20:12 wenovus

So what needs to be done here is that protomap.ProtoFromPaths needs to be able to recursively populate fields. Currently, the function only supports unmarshalling direct children, and skips the rest.

I'm seeing two problems that are interesting:

  1. how to unmarshal list keys?
  2. how to unmarshal oneofs?

The approach GoStructs uses is to use the YANG schema information. This is used both to unmarshal list keys to the correct type (from its string representation in the path), as well as to validate the data.

The philosophy of the protomap package is to leave most of the heavy lifting to the GoStructs, so I think there is no rule that we need to validate the input (path, value) pairs to this function. Furthermore, even though oneof seems problematic on the surface, we can simply try to unmarshal into each subtype one-by-one instead of using the schema. This way we take away having to use any YANG schema information during the unmarshalling process.

@robshakir Do you have any objections?

I'm thinking of making ProtoFromPaths do something more like ytypes.SetNode, where each path is unmarshalled step-by-step down, instead of doing a nested for loop among all the paths. This improves performance, and also solves the problem of how to know which list entry to create when encountering a repeated field.

wenovus avatar Dec 10 '21 21:12 wenovus

The protobufs themselves have a specific pattern which means that I don't think you need the schema to unmarshal list keys. Particularly:


container a-container {
  list foo {
    key "bar baz";
   
    leaf bar { type string; }
    leaf baz { type uint32; }

     leaf fish { type string; }
  }
}

creates a proto of the following form:


message AContainer {
  repeated FooKey foo = 1;
}

message FooKey {
   string bar = 1;
   uint32 baz = 2;
   Foo foo = 3;
}

message Foo {
   string fish = 1;
}

So FooKey has three fields - two that are the list keys and then one that is the list member omitting the keys, so as one unmarshals the FooKey message then you know that fields that are not a message type (of which there will always be the same number of as the number of keys in the YANG list) are keys that can be unmarshalled. The fields of Foo are then the remaining fields. With the schemapath annotations the name of the key fields rather than needing the path.

I'm not quite sure that you can avoid the iteration through the fields -- in SetNode you don't have to do this because you have the schema available, but here you don't have this to hand, so you would need to rebuild the (yang.Entry).Dir map through iteration anyway. Right?

robshakir avatar Dec 29 '21 18:12 robshakir