diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20503e42..1f5a7301 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,14 @@ -name: golangci-lint +name: Lint on: push: - branches: [ 'main' ] + branches: + - main + - develop pull_request: - branches: [ 'main' ] + branches: + - main + - develop types: - opened - reopened @@ -12,15 +16,40 @@ on: - ready_for_review jobs: - golangci: - name: lint + lint: + name: Lint runs-on: ubuntu-latest - if: github.event.pull_request.draft == false + if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.draft == false) steps: - - uses: actions/checkout@v5 - - uses: actions/setup-go@v6 + - name: Checkout code + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + - name: Run golangci-lint uses: golangci/golangci-lint-action@v8 with: version: latest args: --config=.golangci.yml + + - name: Install buf CLI + uses: bufbuild/buf-setup-action@v1 + with: + version: latest + + - name: Run buf lint + run: buf lint + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: latest + + - name: Install markdownlint-cli + run: npm install -g markdownlint-cli + + - name: Run markdownlint + run: markdownlint '**/*.md' --ignore node_modules diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000..e10fb3b4 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,5 @@ +{ + "MD013": false, + "MD033": false, + "MD041": false + } diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 0509a052..535f6a0f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -116,7 +116,7 @@ the community. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. +. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). @@ -124,5 +124,5 @@ enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. +. Translations are available at +. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3c10578..3c5f03a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,15 @@ +# Contributing + +Thank you for considering contributing to Pola PCE! +Below are the guidelines for contributing. + ## Creating Pull Requests -All updates, including those contributed by project members, must be reviewed via Pull Request. -## Creating issues -If you have a bug report, feature request, or other question, please create an issue. However, please refer to [Security Policy](https://github.com/nttcom/pola/blob/main/SECURITY.md) for vulnerabilities. +All updates, including those contributed by project members, +must be reviewed via pull request. + +## Creating Issues + +If you have a bug report, feature request, or other question, please create an issue. +However, please refer to the [security policy](https://github.com/nttcom/pola/blob/main/security.md) +for vulnerabilities. diff --git a/CREDITS b/CREDITS index adc34a8f..8707a45c 100644 --- a/CREDITS +++ b/CREDITS @@ -773,8 +773,8 @@ https://github.com/inconshreveable/mousetrap ================================================================ -github.com/osrg/gobgp/v3 -https://github.com/osrg/gobgp/v3 +github.com/osrg/gobgp/v4 +https://github.com/osrg/gobgp/v4 ---------------------------------------------------------------- Apache License Version 2.0, January 2004 @@ -2672,6 +2672,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================ +gonum.org/v1/gonum +https://gonum.org/v1/gonum +---------------------------------------------------------------- +Copyright ©2013 The Gonum Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Gonum project nor the names of its authors and + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +================================================================ + google.golang.org/genproto/googleapis/rpc https://google.golang.org/genproto/googleapis/rpc ---------------------------------------------------------------- diff --git a/README.md b/README.md index 105b296a..efd5ddcf 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,19 @@

# Pola PCE + [![Linter](https://github.com/nttcom/pola/actions/workflows/ci.yml/badge.svg)](https://github.com/nttcom/pola/actions) [![Releaser](https://github.com/nttcom/pola/actions/workflows/release.yml/badge.svg)](https://github.com/nttcom/pola/actions) -[![Go Report Card](https://goreportcard.com/badge/nttcom/pola)](https://goreportcard.com/report/github.com/nttcom/pola) +[![Go Report Card](https://goreportcard.com/badge/nttcom/pola)](https://goreportcard.com/report/github.com/nttcom/pola) [![Go Reference](https://pkg.go.dev/badge/github.com/nttcom/pola.svg)](https://pkg.go.dev/github.com/nttcom/pola) [![Go version](https://img.shields.io/github/go-mod/go-version/nttcom/pola)](https://go.dev/) [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE) -Pola PCE is an implementation of the Path Computation Element (PCE) and a PCEP Library in Go. +Pola PCE is an implementation of the Path Computation Element (PCE) +and a PCEP Library in Go. ## Features + * Support for SRv6(full-SID/uSID) and SR-MPLS * Implementation of active stateful PCE functionality (PCInitiate, PCUpdate, etc.) * Dynamic and explicit SR policy definition using YAML @@ -20,29 +23,41 @@ Pola PCE is an implementation of the Path Computation Element (PCE) and a PCEP L * Explicit path: Allows users to define and provision any Segment List ## Interoperability + ### SR-MPLS + * IOS-XR * Junos * FRRouting ### SRv6 (full-SID) + * Junos ### SRv6 (uSID) + * IOS-XR * Junos * VRP ## Installation & Use + * [Getting Started](docs/sources/getting-started.md) * Examples (powered by [Containerlab](https://containerlab.dev/)/[Tinet](https://github.com/tinynetwork/tinet)) * [SR-MPLS Example](examples/tinet/sr-mpls_te_l3vpn) * [SRv6 Example](examples/containerlab/srv6_te_l3vpn) ## Contributing -If you are interested in contributing to the project, please refer to the [CONTRIBUTING](https://github.com/nttcom/pola/blob/main/CONTRIBUTING.md) guidelines. -Feel free to fork the repository and create a Pull Request. Your contributions are highly appreciated. + +If you are interested in contributing to the project, please refer to the +[CONTRIBUTING](https://github.com/nttcom/pola/blob/main/CONTRIBUTING.md) +guidelines. +Feel free to fork the repository and create a Pull Request. +Your contributions are highly appreciated. ## Licensing -Pola PCE is licensed under the [MIT license](https://en.wikipedia.org/wiki/MIT_License). -For the full license text, see [LICENSE](https://github.com/nttcom/pola/blob/master/LICENSE). + +Pola PCE is licensed under the +[MIT license](https://en.wikipedia.org/wiki/MIT_License). +For the full license text, see +[LICENSE](https://github.com/nttcom/pola/blob/master/LICENSE). diff --git a/SECURITY.md b/SECURITY.md index d10b4a52..e133da03 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,8 +4,9 @@ **Please do not report security vulnerabilities in public issues on GitHub.** -Instead, please report by email to the Pola PCE maintainer ([watal](https://github.com/watal)). -Include "Vulnerability" in the subject line of the email. +Instead, please report by email to the Pola PCE maintainer ([watal](https://github.com/watal)). +Include "Vulnerability" in the subject line of the email. We will action the vulnerability within 72 hours of receiving the vulnerability report. -If you have suggestions for improving this policy, please submit a PR or Issue for discussion. +If you have suggestions for improving this policy, +please submit a PR or Issue for discussion. diff --git a/api/grpc/pola.pb.go b/api/grpc/pola.pb.go deleted file mode 100644 index 060773f3..00000000 --- a/api/grpc/pola.pb.go +++ /dev/null @@ -1,1473 +0,0 @@ -// Copyright (c) 2022 NTT Communications Corporation -// -// This software is released under the MIT License. -// see https://github.com/nttcom/pola/blob/main/LICENSE - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.34.1 -// protoc v3.12.4 -// source: pola.proto - -package grpc - -import ( - empty "github.com/golang/protobuf/ptypes/empty" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type SRPolicyType int32 - -const ( - SRPolicyType_EXPLICIT SRPolicyType = 0 - SRPolicyType_DYNAMIC SRPolicyType = 1 -) - -// Enum value maps for SRPolicyType. -var ( - SRPolicyType_name = map[int32]string{ - 0: "EXPLICIT", - 1: "DYNAMIC", - } - SRPolicyType_value = map[string]int32{ - "EXPLICIT": 0, - "DYNAMIC": 1, - } -) - -func (x SRPolicyType) Enum() *SRPolicyType { - p := new(SRPolicyType) - *p = x - return p -} - -func (x SRPolicyType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SRPolicyType) Descriptor() protoreflect.EnumDescriptor { - return file_pola_proto_enumTypes[0].Descriptor() -} - -func (SRPolicyType) Type() protoreflect.EnumType { - return &file_pola_proto_enumTypes[0] -} - -func (x SRPolicyType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SRPolicyType.Descriptor instead. -func (SRPolicyType) EnumDescriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{0} -} - -type SessionState int32 - -const ( - SessionState_DOWN SessionState = 0 - SessionState_UP SessionState = 1 -) - -// Enum value maps for SessionState. -var ( - SessionState_name = map[int32]string{ - 0: "DOWN", - 1: "UP", - } - SessionState_value = map[string]int32{ - "DOWN": 0, - "UP": 1, - } -) - -func (x SessionState) Enum() *SessionState { - p := new(SessionState) - *p = x - return p -} - -func (x SessionState) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SessionState) Descriptor() protoreflect.EnumDescriptor { - return file_pola_proto_enumTypes[1].Descriptor() -} - -func (SessionState) Type() protoreflect.EnumType { - return &file_pola_proto_enumTypes[1] -} - -func (x SessionState) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SessionState.Descriptor instead. -func (SessionState) EnumDescriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{1} -} - -type MetricType int32 - -const ( - MetricType_IGP MetricType = 0 - MetricType_TE MetricType = 1 - MetricType_DELAY MetricType = 2 - MetricType_HOPCOUNT MetricType = 3 -) - -// Enum value maps for MetricType. -var ( - MetricType_name = map[int32]string{ - 0: "IGP", - 1: "TE", - 2: "DELAY", - 3: "HOPCOUNT", - } - MetricType_value = map[string]int32{ - "IGP": 0, - "TE": 1, - "DELAY": 2, - "HOPCOUNT": 3, - } -) - -func (x MetricType) Enum() *MetricType { - p := new(MetricType) - *p = x - return p -} - -func (x MetricType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MetricType) Descriptor() protoreflect.EnumDescriptor { - return file_pola_proto_enumTypes[2].Descriptor() -} - -func (MetricType) Type() protoreflect.EnumType { - return &file_pola_proto_enumTypes[2] -} - -func (x MetricType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MetricType.Descriptor instead. -func (MetricType) EnumDescriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{2} -} - -type Segment struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Sid string `protobuf:"bytes,1,opt,name=sid,proto3" json:"sid,omitempty"` - SidStructure string `protobuf:"bytes,2,opt,name=sidStructure,proto3" json:"sidStructure,omitempty"` - LocalAddr string `protobuf:"bytes,3,opt,name=localAddr,proto3" json:"localAddr,omitempty"` - RemoteAddr string `protobuf:"bytes,4,opt,name=remoteAddr,proto3" json:"remoteAddr,omitempty"` -} - -func (x *Segment) Reset() { - *x = Segment{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Segment) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Segment) ProtoMessage() {} - -func (x *Segment) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Segment.ProtoReflect.Descriptor instead. -func (*Segment) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{0} -} - -func (x *Segment) GetSid() string { - if x != nil { - return x.Sid - } - return "" -} - -func (x *Segment) GetSidStructure() string { - if x != nil { - return x.SidStructure - } - return "" -} - -func (x *Segment) GetLocalAddr() string { - if x != nil { - return x.LocalAddr - } - return "" -} - -func (x *Segment) GetRemoteAddr() string { - if x != nil { - return x.RemoteAddr - } - return "" -} - -type SRPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PcepSessionAddr []byte `protobuf:"bytes,1,opt,name=pcepSessionAddr,proto3" json:"pcepSessionAddr,omitempty"` - SrcAddr []byte `protobuf:"bytes,2,opt,name=srcAddr,proto3" json:"srcAddr,omitempty"` - DstAddr []byte `protobuf:"bytes,3,opt,name=dstAddr,proto3" json:"dstAddr,omitempty"` - SrcRouterID string `protobuf:"bytes,4,opt,name=srcRouterID,proto3" json:"srcRouterID,omitempty"` - DstRouterID string `protobuf:"bytes,5,opt,name=dstRouterID,proto3" json:"dstRouterID,omitempty"` - Color uint32 `protobuf:"varint,6,opt,name=color,proto3" json:"color,omitempty"` - Preference uint32 `protobuf:"varint,7,opt,name=preference,proto3" json:"preference,omitempty"` - PolicyName string `protobuf:"bytes,8,opt,name=policyName,proto3" json:"policyName,omitempty"` - Type SRPolicyType `protobuf:"varint,9,opt,name=type,proto3,enum=pb.SRPolicyType" json:"type,omitempty"` - SegmentList []*Segment `protobuf:"bytes,10,rep,name=segmentList,proto3" json:"segmentList,omitempty"` - Metric MetricType `protobuf:"varint,11,opt,name=metric,proto3,enum=pb.MetricType" json:"metric,omitempty"` -} - -func (x *SRPolicy) Reset() { - *x = SRPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SRPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SRPolicy) ProtoMessage() {} - -func (x *SRPolicy) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SRPolicy.ProtoReflect.Descriptor instead. -func (*SRPolicy) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{1} -} - -func (x *SRPolicy) GetPcepSessionAddr() []byte { - if x != nil { - return x.PcepSessionAddr - } - return nil -} - -func (x *SRPolicy) GetSrcAddr() []byte { - if x != nil { - return x.SrcAddr - } - return nil -} - -func (x *SRPolicy) GetDstAddr() []byte { - if x != nil { - return x.DstAddr - } - return nil -} - -func (x *SRPolicy) GetSrcRouterID() string { - if x != nil { - return x.SrcRouterID - } - return "" -} - -func (x *SRPolicy) GetDstRouterID() string { - if x != nil { - return x.DstRouterID - } - return "" -} - -func (x *SRPolicy) GetColor() uint32 { - if x != nil { - return x.Color - } - return 0 -} - -func (x *SRPolicy) GetPreference() uint32 { - if x != nil { - return x.Preference - } - return 0 -} - -func (x *SRPolicy) GetPolicyName() string { - if x != nil { - return x.PolicyName - } - return "" -} - -func (x *SRPolicy) GetType() SRPolicyType { - if x != nil { - return x.Type - } - return SRPolicyType_EXPLICIT -} - -func (x *SRPolicy) GetSegmentList() []*Segment { - if x != nil { - return x.SegmentList - } - return nil -} - -func (x *SRPolicy) GetMetric() MetricType { - if x != nil { - return x.Metric - } - return MetricType_IGP -} - -type CreateSRPolicyInput struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SRPolicy *SRPolicy `protobuf:"bytes,1,opt,name=SRPolicy,proto3" json:"SRPolicy,omitempty"` - Asn uint32 `protobuf:"varint,2,opt,name=asn,proto3" json:"asn,omitempty"` -} - -func (x *CreateSRPolicyInput) Reset() { - *x = CreateSRPolicyInput{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateSRPolicyInput) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateSRPolicyInput) ProtoMessage() {} - -func (x *CreateSRPolicyInput) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreateSRPolicyInput.ProtoReflect.Descriptor instead. -func (*CreateSRPolicyInput) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{2} -} - -func (x *CreateSRPolicyInput) GetSRPolicy() *SRPolicy { - if x != nil { - return x.SRPolicy - } - return nil -} - -func (x *CreateSRPolicyInput) GetAsn() uint32 { - if x != nil { - return x.Asn - } - return 0 -} - -type DeleteSRPolicyInput struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SRPolicy *SRPolicy `protobuf:"bytes,1,opt,name=SRPolicy,proto3" json:"SRPolicy,omitempty"` - Asn uint32 `protobuf:"varint,2,opt,name=asn,proto3" json:"asn,omitempty"` -} - -func (x *DeleteSRPolicyInput) Reset() { - *x = DeleteSRPolicyInput{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteSRPolicyInput) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteSRPolicyInput) ProtoMessage() {} - -func (x *DeleteSRPolicyInput) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DeleteSRPolicyInput.ProtoReflect.Descriptor instead. -func (*DeleteSRPolicyInput) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{3} -} - -func (x *DeleteSRPolicyInput) GetSRPolicy() *SRPolicy { - if x != nil { - return x.SRPolicy - } - return nil -} - -func (x *DeleteSRPolicyInput) GetAsn() uint32 { - if x != nil { - return x.Asn - } - return 0 -} - -type RequestStatus struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - IsSuccess bool `protobuf:"varint,1,opt,name=isSuccess,proto3" json:"isSuccess,omitempty"` -} - -func (x *RequestStatus) Reset() { - *x = RequestStatus{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestStatus) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestStatus) ProtoMessage() {} - -func (x *RequestStatus) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RequestStatus.ProtoReflect.Descriptor instead. -func (*RequestStatus) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{4} -} - -func (x *RequestStatus) GetIsSuccess() bool { - if x != nil { - return x.IsSuccess - } - return false -} - -type Session struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Addr []byte `protobuf:"bytes,1,opt,name=Addr,proto3" json:"Addr,omitempty"` - State SessionState `protobuf:"varint,2,opt,name=State,proto3,enum=pb.SessionState" json:"State,omitempty"` - Caps []string `protobuf:"bytes,3,rep,name=Caps,proto3" json:"Caps,omitempty"` - IsSynced bool `protobuf:"varint,4,opt,name=IsSynced,proto3" json:"IsSynced,omitempty"` -} - -func (x *Session) Reset() { - *x = Session{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Session) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Session) ProtoMessage() {} - -func (x *Session) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Session.ProtoReflect.Descriptor instead. -func (*Session) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{5} -} - -func (x *Session) GetAddr() []byte { - if x != nil { - return x.Addr - } - return nil -} - -func (x *Session) GetState() SessionState { - if x != nil { - return x.State - } - return SessionState_DOWN -} - -func (x *Session) GetCaps() []string { - if x != nil { - return x.Caps - } - return nil -} - -func (x *Session) GetIsSynced() bool { - if x != nil { - return x.IsSynced - } - return false -} - -type SessionList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Sessions []*Session `protobuf:"bytes,1,rep,name=Sessions,proto3" json:"Sessions,omitempty"` -} - -func (x *SessionList) Reset() { - *x = SessionList{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SessionList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SessionList) ProtoMessage() {} - -func (x *SessionList) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SessionList.ProtoReflect.Descriptor instead. -func (*SessionList) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{6} -} - -func (x *SessionList) GetSessions() []*Session { - if x != nil { - return x.Sessions - } - return nil -} - -type SRPolicyList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SRPolicies []*SRPolicy `protobuf:"bytes,1,rep,name=SRPolicies,proto3" json:"SRPolicies,omitempty"` -} - -func (x *SRPolicyList) Reset() { - *x = SRPolicyList{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SRPolicyList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SRPolicyList) ProtoMessage() {} - -func (x *SRPolicyList) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SRPolicyList.ProtoReflect.Descriptor instead. -func (*SRPolicyList) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{7} -} - -func (x *SRPolicyList) GetSRPolicies() []*SRPolicy { - if x != nil { - return x.SRPolicies - } - return nil -} - -type LsPrefix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` - SidIndex uint32 `protobuf:"varint,2,opt,name=sidIndex,proto3" json:"sidIndex,omitempty"` -} - -func (x *LsPrefix) Reset() { - *x = LsPrefix{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LsPrefix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LsPrefix) ProtoMessage() {} - -func (x *LsPrefix) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LsPrefix.ProtoReflect.Descriptor instead. -func (*LsPrefix) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{8} -} - -func (x *LsPrefix) GetPrefix() string { - if x != nil { - return x.Prefix - } - return "" -} - -func (x *LsPrefix) GetSidIndex() uint32 { - if x != nil { - return x.SidIndex - } - return 0 -} - -type Metric struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type MetricType `protobuf:"varint,1,opt,name=type,proto3,enum=pb.MetricType" json:"type,omitempty"` - Value uint32 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *Metric) Reset() { - *x = Metric{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Metric) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Metric) ProtoMessage() {} - -func (x *Metric) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Metric.ProtoReflect.Descriptor instead. -func (*Metric) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{9} -} - -func (x *Metric) GetType() MetricType { - if x != nil { - return x.Type - } - return MetricType_IGP -} - -func (x *Metric) GetValue() uint32 { - if x != nil { - return x.Value - } - return 0 -} - -type LsLink struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - LocalRouterID string `protobuf:"bytes,1,opt,name=localRouterID,proto3" json:"localRouterID,omitempty"` - LocalAsn uint32 `protobuf:"varint,2,opt,name=localAsn,proto3" json:"localAsn,omitempty"` - LocalIP string `protobuf:"bytes,3,opt,name=localIP,proto3" json:"localIP,omitempty"` - RemoteRouterID string `protobuf:"bytes,4,opt,name=remoteRouterID,proto3" json:"remoteRouterID,omitempty"` - RemoteAsn uint32 `protobuf:"varint,5,opt,name=remoteAsn,proto3" json:"remoteAsn,omitempty"` - RemoteIP string `protobuf:"bytes,6,opt,name=remoteIP,proto3" json:"remoteIP,omitempty"` - Metrics []*Metric `protobuf:"bytes,7,rep,name=metrics,proto3" json:"metrics,omitempty"` - AdjSid uint32 `protobuf:"varint,8,opt,name=adjSid,proto3" json:"adjSid,omitempty"` -} - -func (x *LsLink) Reset() { - *x = LsLink{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LsLink) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LsLink) ProtoMessage() {} - -func (x *LsLink) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LsLink.ProtoReflect.Descriptor instead. -func (*LsLink) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{10} -} - -func (x *LsLink) GetLocalRouterID() string { - if x != nil { - return x.LocalRouterID - } - return "" -} - -func (x *LsLink) GetLocalAsn() uint32 { - if x != nil { - return x.LocalAsn - } - return 0 -} - -func (x *LsLink) GetLocalIP() string { - if x != nil { - return x.LocalIP - } - return "" -} - -func (x *LsLink) GetRemoteRouterID() string { - if x != nil { - return x.RemoteRouterID - } - return "" -} - -func (x *LsLink) GetRemoteAsn() uint32 { - if x != nil { - return x.RemoteAsn - } - return 0 -} - -func (x *LsLink) GetRemoteIP() string { - if x != nil { - return x.RemoteIP - } - return "" -} - -func (x *LsLink) GetMetrics() []*Metric { - if x != nil { - return x.Metrics - } - return nil -} - -func (x *LsLink) GetAdjSid() uint32 { - if x != nil { - return x.AdjSid - } - return 0 -} - -type LsNode struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` - RouterID string `protobuf:"bytes,2,opt,name=routerID,proto3" json:"routerID,omitempty"` - IsisAreaID string `protobuf:"bytes,3,opt,name=isisAreaID,proto3" json:"isisAreaID,omitempty"` - Hostname string `protobuf:"bytes,4,opt,name=hostname,proto3" json:"hostname,omitempty"` - SrgbBegin uint32 `protobuf:"varint,5,opt,name=srgbBegin,proto3" json:"srgbBegin,omitempty"` - SrgbEnd uint32 `protobuf:"varint,6,opt,name=srgbEnd,proto3" json:"srgbEnd,omitempty"` - LsLinks []*LsLink `protobuf:"bytes,7,rep,name=lsLinks,proto3" json:"lsLinks,omitempty"` - LsPrefixes []*LsPrefix `protobuf:"bytes,8,rep,name=lsPrefixes,proto3" json:"lsPrefixes,omitempty"` -} - -func (x *LsNode) Reset() { - *x = LsNode{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LsNode) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LsNode) ProtoMessage() {} - -func (x *LsNode) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LsNode.ProtoReflect.Descriptor instead. -func (*LsNode) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{11} -} - -func (x *LsNode) GetAsn() uint32 { - if x != nil { - return x.Asn - } - return 0 -} - -func (x *LsNode) GetRouterID() string { - if x != nil { - return x.RouterID - } - return "" -} - -func (x *LsNode) GetIsisAreaID() string { - if x != nil { - return x.IsisAreaID - } - return "" -} - -func (x *LsNode) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -func (x *LsNode) GetSrgbBegin() uint32 { - if x != nil { - return x.SrgbBegin - } - return 0 -} - -func (x *LsNode) GetSrgbEnd() uint32 { - if x != nil { - return x.SrgbEnd - } - return 0 -} - -func (x *LsNode) GetLsLinks() []*LsLink { - if x != nil { - return x.LsLinks - } - return nil -} - -func (x *LsNode) GetLsPrefixes() []*LsPrefix { - if x != nil { - return x.LsPrefixes - } - return nil -} - -type Ted struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"` - LsNodes []*LsNode `protobuf:"bytes,2,rep,name=lsNodes,proto3" json:"lsNodes,omitempty"` -} - -func (x *Ted) Reset() { - *x = Ted{} - if protoimpl.UnsafeEnabled { - mi := &file_pola_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Ted) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Ted) ProtoMessage() {} - -func (x *Ted) ProtoReflect() protoreflect.Message { - mi := &file_pola_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Ted.ProtoReflect.Descriptor instead. -func (*Ted) Descriptor() ([]byte, []int) { - return file_pola_proto_rawDescGZIP(), []int{12} -} - -func (x *Ted) GetEnable() bool { - if x != nil { - return x.Enable - } - return false -} - -func (x *Ted) GetLsNodes() []*LsNode { - if x != nil { - return x.LsNodes - } - return nil -} - -var File_pola_proto protoreflect.FileDescriptor - -var file_pola_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, - 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7d, 0x0a, - 0x07, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x69, - 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x73, 0x69, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1e, 0x0a, 0x0a, - 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x22, 0xff, 0x02, 0x0a, - 0x08, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x70, 0x63, 0x65, - 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0f, 0x70, 0x63, 0x65, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, - 0x64, 0x64, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x18, 0x0a, - 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x72, 0x63, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x72, - 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x73, 0x74, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x64, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x63, - 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, - 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x24, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, - 0x62, 0x2e, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x73, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x22, 0x51, - 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x28, 0x0a, 0x08, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, - 0x6e, 0x22, 0x51, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x28, 0x0a, 0x08, 0x53, 0x52, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, - 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x03, 0x61, 0x73, 0x6e, 0x22, 0x2d, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x53, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x22, 0x75, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x41, 0x64, - 0x64, 0x72, 0x12, 0x26, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x61, - 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x43, 0x61, 0x70, 0x73, 0x12, 0x1a, - 0x0a, 0x08, 0x49, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x49, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x22, 0x36, 0x0a, 0x0b, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x08, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, - 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x22, 0x3c, 0x0a, 0x0c, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x0a, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x22, 0x3e, 0x0a, 0x08, 0x4c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, - 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x69, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x69, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x22, 0x42, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x84, 0x02, 0x0a, 0x06, 0x4c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, - 0x24, 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x44, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x73, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x73, - 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x50, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x50, 0x12, 0x26, 0x0a, 0x0e, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x73, 0x6e, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x73, - 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x50, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x50, 0x12, 0x24, 0x0a, - 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, - 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x64, 0x6a, 0x53, 0x69, 0x64, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x06, 0x61, 0x64, 0x6a, 0x53, 0x69, 0x64, 0x22, 0xfe, 0x01, 0x0a, 0x06, - 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x49, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x69, 0x73, 0x41, 0x72, 0x65, 0x61, - 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x73, 0x69, 0x73, 0x41, 0x72, - 0x65, 0x61, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x72, 0x67, 0x62, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x72, 0x67, 0x62, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x73, 0x72, 0x67, 0x62, 0x45, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x07, 0x73, 0x72, 0x67, 0x62, 0x45, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x07, 0x6c, 0x73, 0x4c, 0x69, - 0x6e, 0x6b, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x4c, - 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x07, 0x6c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x2c, - 0x0a, 0x0a, 0x6c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x52, 0x0a, 0x6c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x22, 0x43, 0x0a, 0x03, - 0x54, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x07, 0x6c, - 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, - 0x62, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x6c, 0x73, 0x4e, 0x6f, 0x64, 0x65, - 0x73, 0x2a, 0x29, 0x0a, 0x0c, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x58, 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x10, 0x00, 0x12, - 0x0b, 0x0a, 0x07, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, 0x01, 0x2a, 0x20, 0x0a, 0x0c, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, - 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x55, 0x50, 0x10, 0x01, 0x2a, 0x36, - 0x0a, 0x0a, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, - 0x49, 0x47, 0x50, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x54, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, - 0x05, 0x44, 0x45, 0x4c, 0x41, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x48, 0x4f, 0x50, 0x43, - 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x03, 0x32, 0x88, 0x04, 0x0a, 0x0a, 0x50, 0x63, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, - 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, - 0x1a, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, - 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x57, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x4c, 0x69, - 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, - 0x1a, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, - 0x1a, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x1e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x57, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x4c, 0x69, - 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x70, 0x75, 0x74, - 0x1a, 0x11, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, - 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x10, 0x2e, - 0x70, 0x62, 0x2e, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x22, - 0x00, 0x12, 0x2b, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x54, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x07, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x65, 0x64, 0x22, 0x00, 0x12, 0x31, - 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x11, 0x2e, 0x70, - 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0x00, 0x42, 0x21, 0x5a, 0x1f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6e, 0x74, 0x74, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6c, 0x61, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pola_proto_rawDescOnce sync.Once - file_pola_proto_rawDescData = file_pola_proto_rawDesc -) - -func file_pola_proto_rawDescGZIP() []byte { - file_pola_proto_rawDescOnce.Do(func() { - file_pola_proto_rawDescData = protoimpl.X.CompressGZIP(file_pola_proto_rawDescData) - }) - return file_pola_proto_rawDescData -} - -var file_pola_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pola_proto_msgTypes = make([]protoimpl.MessageInfo, 13) -var file_pola_proto_goTypes = []interface{}{ - (SRPolicyType)(0), // 0: pb.SRPolicyType - (SessionState)(0), // 1: pb.SessionState - (MetricType)(0), // 2: pb.MetricType - (*Segment)(nil), // 3: pb.Segment - (*SRPolicy)(nil), // 4: pb.SRPolicy - (*CreateSRPolicyInput)(nil), // 5: pb.CreateSRPolicyInput - (*DeleteSRPolicyInput)(nil), // 6: pb.DeleteSRPolicyInput - (*RequestStatus)(nil), // 7: pb.RequestStatus - (*Session)(nil), // 8: pb.Session - (*SessionList)(nil), // 9: pb.SessionList - (*SRPolicyList)(nil), // 10: pb.SRPolicyList - (*LsPrefix)(nil), // 11: pb.LsPrefix - (*Metric)(nil), // 12: pb.Metric - (*LsLink)(nil), // 13: pb.LsLink - (*LsNode)(nil), // 14: pb.LsNode - (*Ted)(nil), // 15: pb.Ted - (*empty.Empty)(nil), // 16: google.protobuf.Empty -} -var file_pola_proto_depIdxs = []int32{ - 0, // 0: pb.SRPolicy.type:type_name -> pb.SRPolicyType - 3, // 1: pb.SRPolicy.segmentList:type_name -> pb.Segment - 2, // 2: pb.SRPolicy.metric:type_name -> pb.MetricType - 4, // 3: pb.CreateSRPolicyInput.SRPolicy:type_name -> pb.SRPolicy - 4, // 4: pb.DeleteSRPolicyInput.SRPolicy:type_name -> pb.SRPolicy - 1, // 5: pb.Session.State:type_name -> pb.SessionState - 8, // 6: pb.SessionList.Sessions:type_name -> pb.Session - 4, // 7: pb.SRPolicyList.SRPolicies:type_name -> pb.SRPolicy - 2, // 8: pb.Metric.type:type_name -> pb.MetricType - 12, // 9: pb.LsLink.metrics:type_name -> pb.Metric - 13, // 10: pb.LsNode.lsLinks:type_name -> pb.LsLink - 11, // 11: pb.LsNode.lsPrefixes:type_name -> pb.LsPrefix - 14, // 12: pb.Ted.lsNodes:type_name -> pb.LsNode - 5, // 13: pb.PceService.CreateSRPolicy:input_type -> pb.CreateSRPolicyInput - 5, // 14: pb.PceService.CreateSRPolicyWithoutLinkState:input_type -> pb.CreateSRPolicyInput - 6, // 15: pb.PceService.DeleteSRPolicy:input_type -> pb.DeleteSRPolicyInput - 6, // 16: pb.PceService.DeleteSRPolicyWithoutLinkState:input_type -> pb.DeleteSRPolicyInput - 16, // 17: pb.PceService.GetSessionList:input_type -> google.protobuf.Empty - 16, // 18: pb.PceService.GetSRPolicyList:input_type -> google.protobuf.Empty - 16, // 19: pb.PceService.GetTed:input_type -> google.protobuf.Empty - 8, // 20: pb.PceService.DeleteSession:input_type -> pb.Session - 7, // 21: pb.PceService.CreateSRPolicy:output_type -> pb.RequestStatus - 7, // 22: pb.PceService.CreateSRPolicyWithoutLinkState:output_type -> pb.RequestStatus - 7, // 23: pb.PceService.DeleteSRPolicy:output_type -> pb.RequestStatus - 7, // 24: pb.PceService.DeleteSRPolicyWithoutLinkState:output_type -> pb.RequestStatus - 9, // 25: pb.PceService.GetSessionList:output_type -> pb.SessionList - 10, // 26: pb.PceService.GetSRPolicyList:output_type -> pb.SRPolicyList - 15, // 27: pb.PceService.GetTed:output_type -> pb.Ted - 7, // 28: pb.PceService.DeleteSession:output_type -> pb.RequestStatus - 21, // [21:29] is the sub-list for method output_type - 13, // [13:21] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name -} - -func init() { file_pola_proto_init() } -func file_pola_proto_init() { - if File_pola_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pola_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Segment); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SRPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateSRPolicyInput); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteSRPolicyInput); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestStatus); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Session); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SessionList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SRPolicyList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LsPrefix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Metric); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LsLink); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LsNode); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pola_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Ted); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pola_proto_rawDesc, - NumEnums: 3, - NumMessages: 13, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_pola_proto_goTypes, - DependencyIndexes: file_pola_proto_depIdxs, - EnumInfos: file_pola_proto_enumTypes, - MessageInfos: file_pola_proto_msgTypes, - }.Build() - File_pola_proto = out.File - file_pola_proto_rawDesc = nil - file_pola_proto_goTypes = nil - file_pola_proto_depIdxs = nil -} diff --git a/api/grpc/pola.proto b/api/grpc/pola.proto deleted file mode 100644 index 3b91ed9e..00000000 --- a/api/grpc/pola.proto +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2022 NTT Communications Corporation -// -// This software is released under the MIT License. -// see https://github.com/nttcom/pola/blob/main/LICENSE - -syntax = "proto3"; - -package pb; - -option go_package = "github.com/nttcom/pola/api/grpc"; - -import "google/protobuf/empty.proto"; - -service PceService { - rpc CreateSRPolicy (CreateSRPolicyInput) returns (RequestStatus) {}; - - rpc CreateSRPolicyWithoutLinkState (CreateSRPolicyInput) returns (RequestStatus) {}; - - rpc DeleteSRPolicy (DeleteSRPolicyInput) returns (RequestStatus) {}; - - rpc DeleteSRPolicyWithoutLinkState (DeleteSRPolicyInput) returns (RequestStatus) {}; - - rpc GetSessionList (google.protobuf.Empty) returns (SessionList) {}; - - rpc GetSRPolicyList (google.protobuf.Empty) returns (SRPolicyList) {}; - - rpc GetTed (google.protobuf.Empty) returns (Ted) {}; - - rpc DeleteSession (Session) returns (RequestStatus) {}; -} - -message Segment { - string sid = 1; - string sidStructure = 2; - string localAddr = 3; - string remoteAddr = 4; -} - -enum SRPolicyType { - EXPLICIT = 0; - DYNAMIC = 1; -} - -message SRPolicy { - bytes pcepSessionAddr = 1; - bytes srcAddr = 2; - bytes dstAddr = 3; - string srcRouterID = 4; - string dstRouterID = 5; - uint32 color = 6; - uint32 preference = 7; - string policyName = 8; - SRPolicyType type = 9; - repeated Segment segmentList = 10; - MetricType metric = 11; -} - -message CreateSRPolicyInput { - SRPolicy SRPolicy = 1; - uint32 asn = 2; -} - -message DeleteSRPolicyInput { - SRPolicy SRPolicy = 1; - uint32 asn = 2; -} - -message RequestStatus { - bool isSuccess = 1; -} - -enum SessionState { - DOWN = 0; - UP = 1; -} - -message Session { - bytes Addr = 1; - SessionState State = 2; - repeated string Caps = 3; - bool IsSynced = 4; -} - -message SessionList { - repeated Session Sessions = 1; -} - -message SRPolicyList { - repeated SRPolicy SRPolicies = 1; -} - -message LsPrefix { - string prefix = 1; - uint32 sidIndex = 2; -} - -enum MetricType { - IGP = 0; - TE = 1; - DELAY = 2; - HOPCOUNT = 3; -} - -message Metric { - MetricType type = 1; - uint32 value = 2; -} - -message LsLink { - string localRouterID = 1; - uint32 localAsn = 2; - string localIP = 3; - string remoteRouterID = 4; - uint32 remoteAsn = 5; - string remoteIP = 6; - repeated Metric metrics = 7; - uint32 adjSid = 8; -} - -message LsNode { - uint32 asn = 1; - string routerID = 2; - string isisAreaID = 3; - string hostname = 4; - uint32 srgbBegin = 5; - uint32 srgbEnd = 6; - repeated LsLink lsLinks = 7; - repeated LsPrefix lsPrefixes = 8; -} - - -message Ted { - bool enable = 1; - repeated LsNode lsNodes = 2; -} diff --git a/api/grpc/pola_grpc.pb.go b/api/grpc/pola_grpc.pb.go deleted file mode 100644 index 85236891..00000000 --- a/api/grpc/pola_grpc.pb.go +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright (c) 2022 NTT Communications Corporation -// -// This software is released under the MIT License. -// see https://github.com/nttcom/pola/blob/main/LICENSE - -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v3.12.4 -// source: pola.proto - -package grpc - -import ( - context "context" - empty "github.com/golang/protobuf/ptypes/empty" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - PceService_CreateSRPolicy_FullMethodName = "/pb.PceService/CreateSRPolicy" - PceService_CreateSRPolicyWithoutLinkState_FullMethodName = "/pb.PceService/CreateSRPolicyWithoutLinkState" - PceService_DeleteSRPolicy_FullMethodName = "/pb.PceService/DeleteSRPolicy" - PceService_DeleteSRPolicyWithoutLinkState_FullMethodName = "/pb.PceService/DeleteSRPolicyWithoutLinkState" - PceService_GetSessionList_FullMethodName = "/pb.PceService/GetSessionList" - PceService_GetSRPolicyList_FullMethodName = "/pb.PceService/GetSRPolicyList" - PceService_GetTed_FullMethodName = "/pb.PceService/GetTed" - PceService_DeleteSession_FullMethodName = "/pb.PceService/DeleteSession" -) - -// PceServiceClient is the client API for PceService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type PceServiceClient interface { - CreateSRPolicy(ctx context.Context, in *CreateSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) - CreateSRPolicyWithoutLinkState(ctx context.Context, in *CreateSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) - DeleteSRPolicy(ctx context.Context, in *DeleteSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) - DeleteSRPolicyWithoutLinkState(ctx context.Context, in *DeleteSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) - GetSessionList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*SessionList, error) - GetSRPolicyList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*SRPolicyList, error) - GetTed(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Ted, error) - DeleteSession(ctx context.Context, in *Session, opts ...grpc.CallOption) (*RequestStatus, error) -} - -type pceServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewPceServiceClient(cc grpc.ClientConnInterface) PceServiceClient { - return &pceServiceClient{cc} -} - -func (c *pceServiceClient) CreateSRPolicy(ctx context.Context, in *CreateSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) { - out := new(RequestStatus) - err := c.cc.Invoke(ctx, PceService_CreateSRPolicy_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *pceServiceClient) CreateSRPolicyWithoutLinkState(ctx context.Context, in *CreateSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) { - out := new(RequestStatus) - err := c.cc.Invoke(ctx, PceService_CreateSRPolicyWithoutLinkState_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *pceServiceClient) DeleteSRPolicy(ctx context.Context, in *DeleteSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) { - out := new(RequestStatus) - err := c.cc.Invoke(ctx, PceService_DeleteSRPolicy_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *pceServiceClient) DeleteSRPolicyWithoutLinkState(ctx context.Context, in *DeleteSRPolicyInput, opts ...grpc.CallOption) (*RequestStatus, error) { - out := new(RequestStatus) - err := c.cc.Invoke(ctx, PceService_DeleteSRPolicyWithoutLinkState_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *pceServiceClient) GetSessionList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*SessionList, error) { - out := new(SessionList) - err := c.cc.Invoke(ctx, PceService_GetSessionList_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *pceServiceClient) GetSRPolicyList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*SRPolicyList, error) { - out := new(SRPolicyList) - err := c.cc.Invoke(ctx, PceService_GetSRPolicyList_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *pceServiceClient) GetTed(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*Ted, error) { - out := new(Ted) - err := c.cc.Invoke(ctx, PceService_GetTed_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *pceServiceClient) DeleteSession(ctx context.Context, in *Session, opts ...grpc.CallOption) (*RequestStatus, error) { - out := new(RequestStatus) - err := c.cc.Invoke(ctx, PceService_DeleteSession_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// PceServiceServer is the server API for PceService service. -// All implementations must embed UnimplementedPceServiceServer -// for forward compatibility -type PceServiceServer interface { - CreateSRPolicy(context.Context, *CreateSRPolicyInput) (*RequestStatus, error) - CreateSRPolicyWithoutLinkState(context.Context, *CreateSRPolicyInput) (*RequestStatus, error) - DeleteSRPolicy(context.Context, *DeleteSRPolicyInput) (*RequestStatus, error) - DeleteSRPolicyWithoutLinkState(context.Context, *DeleteSRPolicyInput) (*RequestStatus, error) - GetSessionList(context.Context, *empty.Empty) (*SessionList, error) - GetSRPolicyList(context.Context, *empty.Empty) (*SRPolicyList, error) - GetTed(context.Context, *empty.Empty) (*Ted, error) - DeleteSession(context.Context, *Session) (*RequestStatus, error) - mustEmbedUnimplementedPceServiceServer() -} - -// UnimplementedPceServiceServer must be embedded to have forward compatible implementations. -type UnimplementedPceServiceServer struct { -} - -func (UnimplementedPceServiceServer) CreateSRPolicy(context.Context, *CreateSRPolicyInput) (*RequestStatus, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateSRPolicy not implemented") -} -func (UnimplementedPceServiceServer) CreateSRPolicyWithoutLinkState(context.Context, *CreateSRPolicyInput) (*RequestStatus, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateSRPolicyWithoutLinkState not implemented") -} -func (UnimplementedPceServiceServer) DeleteSRPolicy(context.Context, *DeleteSRPolicyInput) (*RequestStatus, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteSRPolicy not implemented") -} -func (UnimplementedPceServiceServer) DeleteSRPolicyWithoutLinkState(context.Context, *DeleteSRPolicyInput) (*RequestStatus, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteSRPolicyWithoutLinkState not implemented") -} -func (UnimplementedPceServiceServer) GetSessionList(context.Context, *empty.Empty) (*SessionList, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetSessionList not implemented") -} -func (UnimplementedPceServiceServer) GetSRPolicyList(context.Context, *empty.Empty) (*SRPolicyList, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetSRPolicyList not implemented") -} -func (UnimplementedPceServiceServer) GetTed(context.Context, *empty.Empty) (*Ted, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetTed not implemented") -} -func (UnimplementedPceServiceServer) DeleteSession(context.Context, *Session) (*RequestStatus, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteSession not implemented") -} -func (UnimplementedPceServiceServer) mustEmbedUnimplementedPceServiceServer() {} - -// UnsafePceServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to PceServiceServer will -// result in compilation errors. -type UnsafePceServiceServer interface { - mustEmbedUnimplementedPceServiceServer() -} - -func RegisterPceServiceServer(s grpc.ServiceRegistrar, srv PceServiceServer) { - s.RegisterService(&PceService_ServiceDesc, srv) -} - -func _PceService_CreateSRPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateSRPolicyInput) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).CreateSRPolicy(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_CreateSRPolicy_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).CreateSRPolicy(ctx, req.(*CreateSRPolicyInput)) - } - return interceptor(ctx, in, info, handler) -} - -func _PceService_CreateSRPolicyWithoutLinkState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateSRPolicyInput) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).CreateSRPolicyWithoutLinkState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_CreateSRPolicyWithoutLinkState_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).CreateSRPolicyWithoutLinkState(ctx, req.(*CreateSRPolicyInput)) - } - return interceptor(ctx, in, info, handler) -} - -func _PceService_DeleteSRPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteSRPolicyInput) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).DeleteSRPolicy(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_DeleteSRPolicy_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).DeleteSRPolicy(ctx, req.(*DeleteSRPolicyInput)) - } - return interceptor(ctx, in, info, handler) -} - -func _PceService_DeleteSRPolicyWithoutLinkState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteSRPolicyInput) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).DeleteSRPolicyWithoutLinkState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_DeleteSRPolicyWithoutLinkState_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).DeleteSRPolicyWithoutLinkState(ctx, req.(*DeleteSRPolicyInput)) - } - return interceptor(ctx, in, info, handler) -} - -func _PceService_GetSessionList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).GetSessionList(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_GetSessionList_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).GetSessionList(ctx, req.(*empty.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _PceService_GetSRPolicyList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).GetSRPolicyList(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_GetSRPolicyList_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).GetSRPolicyList(ctx, req.(*empty.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _PceService_GetTed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).GetTed(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_GetTed_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).GetTed(ctx, req.(*empty.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _PceService_DeleteSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Session) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PceServiceServer).DeleteSession(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: PceService_DeleteSession_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PceServiceServer).DeleteSession(ctx, req.(*Session)) - } - return interceptor(ctx, in, info, handler) -} - -// PceService_ServiceDesc is the grpc.ServiceDesc for PceService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var PceService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "pb.PceService", - HandlerType: (*PceServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "CreateSRPolicy", - Handler: _PceService_CreateSRPolicy_Handler, - }, - { - MethodName: "CreateSRPolicyWithoutLinkState", - Handler: _PceService_CreateSRPolicyWithoutLinkState_Handler, - }, - { - MethodName: "DeleteSRPolicy", - Handler: _PceService_DeleteSRPolicy_Handler, - }, - { - MethodName: "DeleteSRPolicyWithoutLinkState", - Handler: _PceService_DeleteSRPolicyWithoutLinkState_Handler, - }, - { - MethodName: "GetSessionList", - Handler: _PceService_GetSessionList_Handler, - }, - { - MethodName: "GetSRPolicyList", - Handler: _PceService_GetSRPolicyList_Handler, - }, - { - MethodName: "GetTed", - Handler: _PceService_GetTed_Handler, - }, - { - MethodName: "DeleteSession", - Handler: _PceService_DeleteSession_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "pola.proto", -} diff --git a/api/pola/v1/pola.pb.go b/api/pola/v1/pola.pb.go new file mode 100644 index 00000000..aec3d106 --- /dev/null +++ b/api/pola/v1/pola.pb.go @@ -0,0 +1,2581 @@ +// Copyright (c) 2022 NTT Communications Corporation +// +// This software is released under the MIT License. +// see https://github.com/nttcom/pola/blob/main/LICENSE + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.12.4 +// source: pola.proto + +package v1 + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SRPolicyType int32 + +const ( + SRPolicyType_SR_POLICY_TYPE_UNSPECIFIED SRPolicyType = 0 + SRPolicyType_SR_POLICY_TYPE_EXPLICIT SRPolicyType = 1 + SRPolicyType_SR_POLICY_TYPE_DYNAMIC SRPolicyType = 2 +) + +// Enum value maps for SRPolicyType. +var ( + SRPolicyType_name = map[int32]string{ + 0: "SR_POLICY_TYPE_UNSPECIFIED", + 1: "SR_POLICY_TYPE_EXPLICIT", + 2: "SR_POLICY_TYPE_DYNAMIC", + } + SRPolicyType_value = map[string]int32{ + "SR_POLICY_TYPE_UNSPECIFIED": 0, + "SR_POLICY_TYPE_EXPLICIT": 1, + "SR_POLICY_TYPE_DYNAMIC": 2, + } +) + +func (x SRPolicyType) Enum() *SRPolicyType { + p := new(SRPolicyType) + *p = x + return p +} + +func (x SRPolicyType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SRPolicyType) Descriptor() protoreflect.EnumDescriptor { + return file_pola_proto_enumTypes[0].Descriptor() +} + +func (SRPolicyType) Type() protoreflect.EnumType { + return &file_pola_proto_enumTypes[0] +} + +func (x SRPolicyType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SRPolicyType.Descriptor instead. +func (SRPolicyType) EnumDescriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{0} +} + +type SessionState int32 + +const ( + SessionState_SESSION_STATE_UNSPECIFIED SessionState = 0 + SessionState_SESSION_STATE_DOWN SessionState = 1 + SessionState_SESSION_STATE_UP SessionState = 2 +) + +// Enum value maps for SessionState. +var ( + SessionState_name = map[int32]string{ + 0: "SESSION_STATE_UNSPECIFIED", + 1: "SESSION_STATE_DOWN", + 2: "SESSION_STATE_UP", + } + SessionState_value = map[string]int32{ + "SESSION_STATE_UNSPECIFIED": 0, + "SESSION_STATE_DOWN": 1, + "SESSION_STATE_UP": 2, + } +) + +func (x SessionState) Enum() *SessionState { + p := new(SessionState) + *p = x + return p +} + +func (x SessionState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SessionState) Descriptor() protoreflect.EnumDescriptor { + return file_pola_proto_enumTypes[1].Descriptor() +} + +func (SessionState) Type() protoreflect.EnumType { + return &file_pola_proto_enumTypes[1] +} + +func (x SessionState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SessionState.Descriptor instead. +func (SessionState) EnumDescriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{1} +} + +type MetricType int32 + +const ( + MetricType_METRIC_TYPE_UNSPECIFIED MetricType = 0 + MetricType_METRIC_TYPE_IGP MetricType = 1 + MetricType_METRIC_TYPE_TE MetricType = 2 + MetricType_METRIC_TYPE_DELAY MetricType = 3 + MetricType_METRIC_TYPE_HOPCOUNT MetricType = 4 +) + +// Enum value maps for MetricType. +var ( + MetricType_name = map[int32]string{ + 0: "METRIC_TYPE_UNSPECIFIED", + 1: "METRIC_TYPE_IGP", + 2: "METRIC_TYPE_TE", + 3: "METRIC_TYPE_DELAY", + 4: "METRIC_TYPE_HOPCOUNT", + } + MetricType_value = map[string]int32{ + "METRIC_TYPE_UNSPECIFIED": 0, + "METRIC_TYPE_IGP": 1, + "METRIC_TYPE_TE": 2, + "METRIC_TYPE_DELAY": 3, + "METRIC_TYPE_HOPCOUNT": 4, + } +) + +func (x MetricType) Enum() *MetricType { + p := new(MetricType) + *p = x + return p +} + +func (x MetricType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MetricType) Descriptor() protoreflect.EnumDescriptor { + return file_pola_proto_enumTypes[2].Descriptor() +} + +func (MetricType) Type() protoreflect.EnumType { + return &file_pola_proto_enumTypes[2] +} + +func (x MetricType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MetricType.Descriptor instead. +func (MetricType) EnumDescriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{2} +} + +type Segment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sid string `protobuf:"bytes,1,opt,name=sid,proto3" json:"sid,omitempty"` + SidStructure string `protobuf:"bytes,2,opt,name=sid_structure,json=sidStructure,proto3" json:"sid_structure,omitempty"` + LocalAddr string `protobuf:"bytes,3,opt,name=local_addr,json=localAddr,proto3" json:"local_addr,omitempty"` + RemoteAddr string `protobuf:"bytes,4,opt,name=remote_addr,json=remoteAddr,proto3" json:"remote_addr,omitempty"` +} + +func (x *Segment) Reset() { + *x = Segment{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Segment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Segment) ProtoMessage() {} + +func (x *Segment) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Segment.ProtoReflect.Descriptor instead. +func (*Segment) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{0} +} + +func (x *Segment) GetSid() string { + if x != nil { + return x.Sid + } + return "" +} + +func (x *Segment) GetSidStructure() string { + if x != nil { + return x.SidStructure + } + return "" +} + +func (x *Segment) GetLocalAddr() string { + if x != nil { + return x.LocalAddr + } + return "" +} + +func (x *Segment) GetRemoteAddr() string { + if x != nil { + return x.RemoteAddr + } + return "" +} + +type SRPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PcepSessionAddr []byte `protobuf:"bytes,1,opt,name=pcep_session_addr,json=pcepSessionAddr,proto3" json:"pcep_session_addr,omitempty"` + SrcAddr []byte `protobuf:"bytes,2,opt,name=src_addr,json=srcAddr,proto3" json:"src_addr,omitempty"` + DstAddr []byte `protobuf:"bytes,3,opt,name=dst_addr,json=dstAddr,proto3" json:"dst_addr,omitempty"` + SrcRouterId string `protobuf:"bytes,4,opt,name=src_router_id,json=srcRouterId,proto3" json:"src_router_id,omitempty"` + DstRouterId string `protobuf:"bytes,5,opt,name=dst_router_id,json=dstRouterId,proto3" json:"dst_router_id,omitempty"` + Color uint32 `protobuf:"varint,6,opt,name=color,proto3" json:"color,omitempty"` + Preference uint32 `protobuf:"varint,7,opt,name=preference,proto3" json:"preference,omitempty"` + PolicyName string `protobuf:"bytes,8,opt,name=policy_name,json=policyName,proto3" json:"policy_name,omitempty"` + Type SRPolicyType `protobuf:"varint,9,opt,name=type,proto3,enum=api.pola.v1.SRPolicyType" json:"type,omitempty"` + SegmentList []*Segment `protobuf:"bytes,10,rep,name=segment_list,json=segmentList,proto3" json:"segment_list,omitempty"` + Metric MetricType `protobuf:"varint,11,opt,name=metric,proto3,enum=api.pola.v1.MetricType" json:"metric,omitempty"` +} + +func (x *SRPolicy) Reset() { + *x = SRPolicy{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRPolicy) ProtoMessage() {} + +func (x *SRPolicy) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SRPolicy.ProtoReflect.Descriptor instead. +func (*SRPolicy) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{1} +} + +func (x *SRPolicy) GetPcepSessionAddr() []byte { + if x != nil { + return x.PcepSessionAddr + } + return nil +} + +func (x *SRPolicy) GetSrcAddr() []byte { + if x != nil { + return x.SrcAddr + } + return nil +} + +func (x *SRPolicy) GetDstAddr() []byte { + if x != nil { + return x.DstAddr + } + return nil +} + +func (x *SRPolicy) GetSrcRouterId() string { + if x != nil { + return x.SrcRouterId + } + return "" +} + +func (x *SRPolicy) GetDstRouterId() string { + if x != nil { + return x.DstRouterId + } + return "" +} + +func (x *SRPolicy) GetColor() uint32 { + if x != nil { + return x.Color + } + return 0 +} + +func (x *SRPolicy) GetPreference() uint32 { + if x != nil { + return x.Preference + } + return 0 +} + +func (x *SRPolicy) GetPolicyName() string { + if x != nil { + return x.PolicyName + } + return "" +} + +func (x *SRPolicy) GetType() SRPolicyType { + if x != nil { + return x.Type + } + return SRPolicyType_SR_POLICY_TYPE_UNSPECIFIED +} + +func (x *SRPolicy) GetSegmentList() []*Segment { + if x != nil { + return x.SegmentList + } + return nil +} + +func (x *SRPolicy) GetMetric() MetricType { + if x != nil { + return x.Metric + } + return MetricType_METRIC_TYPE_UNSPECIFIED +} + +type CreateSRPolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SrPolicy *SRPolicy `protobuf:"bytes,1,opt,name=sr_policy,json=srPolicy,proto3" json:"sr_policy,omitempty"` + Asn uint32 `protobuf:"varint,2,opt,name=asn,proto3" json:"asn,omitempty"` + SidValidate bool `protobuf:"varint,3,opt,name=sid_validate,json=sidValidate,proto3" json:"sid_validate,omitempty"` +} + +func (x *CreateSRPolicyRequest) Reset() { + *x = CreateSRPolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateSRPolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSRPolicyRequest) ProtoMessage() {} + +func (x *CreateSRPolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateSRPolicyRequest.ProtoReflect.Descriptor instead. +func (*CreateSRPolicyRequest) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateSRPolicyRequest) GetSrPolicy() *SRPolicy { + if x != nil { + return x.SrPolicy + } + return nil +} + +func (x *CreateSRPolicyRequest) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *CreateSRPolicyRequest) GetSidValidate() bool { + if x != nil { + return x.SidValidate + } + return false +} + +type CreateSRPolicyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsSuccess bool `protobuf:"varint,1,opt,name=is_success,json=isSuccess,proto3" json:"is_success,omitempty"` +} + +func (x *CreateSRPolicyResponse) Reset() { + *x = CreateSRPolicyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateSRPolicyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSRPolicyResponse) ProtoMessage() {} + +func (x *CreateSRPolicyResponse) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateSRPolicyResponse.ProtoReflect.Descriptor instead. +func (*CreateSRPolicyResponse) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateSRPolicyResponse) GetIsSuccess() bool { + if x != nil { + return x.IsSuccess + } + return false +} + +type DeleteSRPolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SrPolicy *SRPolicy `protobuf:"bytes,1,opt,name=sr_policy,json=srPolicy,proto3" json:"sr_policy,omitempty"` + Asn uint32 `protobuf:"varint,2,opt,name=asn,proto3" json:"asn,omitempty"` +} + +func (x *DeleteSRPolicyRequest) Reset() { + *x = DeleteSRPolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteSRPolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSRPolicyRequest) ProtoMessage() {} + +func (x *DeleteSRPolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSRPolicyRequest.ProtoReflect.Descriptor instead. +func (*DeleteSRPolicyRequest) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{4} +} + +func (x *DeleteSRPolicyRequest) GetSrPolicy() *SRPolicy { + if x != nil { + return x.SrPolicy + } + return nil +} + +func (x *DeleteSRPolicyRequest) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +type DeleteSRPolicyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsSuccess bool `protobuf:"varint,1,opt,name=is_success,json=isSuccess,proto3" json:"is_success,omitempty"` +} + +func (x *DeleteSRPolicyResponse) Reset() { + *x = DeleteSRPolicyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteSRPolicyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSRPolicyResponse) ProtoMessage() {} + +func (x *DeleteSRPolicyResponse) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSRPolicyResponse.ProtoReflect.Descriptor instead. +func (*DeleteSRPolicyResponse) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{5} +} + +func (x *DeleteSRPolicyResponse) GetIsSuccess() bool { + if x != nil { + return x.IsSuccess + } + return false +} + +type Session struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Addr []byte `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` + State SessionState `protobuf:"varint,2,opt,name=state,proto3,enum=api.pola.v1.SessionState" json:"state,omitempty"` + Caps []string `protobuf:"bytes,3,rep,name=caps,proto3" json:"caps,omitempty"` + IsSynced bool `protobuf:"varint,4,opt,name=is_synced,json=isSynced,proto3" json:"is_synced,omitempty"` +} + +func (x *Session) Reset() { + *x = Session{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Session) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Session) ProtoMessage() {} + +func (x *Session) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Session.ProtoReflect.Descriptor instead. +func (*Session) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{6} +} + +func (x *Session) GetAddr() []byte { + if x != nil { + return x.Addr + } + return nil +} + +func (x *Session) GetState() SessionState { + if x != nil { + return x.State + } + return SessionState_SESSION_STATE_UNSPECIFIED +} + +func (x *Session) GetCaps() []string { + if x != nil { + return x.Caps + } + return nil +} + +func (x *Session) GetIsSynced() bool { + if x != nil { + return x.IsSynced + } + return false +} + +type SessionList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sessions []*Session `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` +} + +func (x *SessionList) Reset() { + *x = SessionList{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SessionList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionList) ProtoMessage() {} + +func (x *SessionList) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionList.ProtoReflect.Descriptor instead. +func (*SessionList) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{7} +} + +func (x *SessionList) GetSessions() []*Session { + if x != nil { + return x.Sessions + } + return nil +} + +type SRPolicyList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SrPolicies []*SRPolicy `protobuf:"bytes,1,rep,name=sr_policies,json=srPolicies,proto3" json:"sr_policies,omitempty"` +} + +func (x *SRPolicyList) Reset() { + *x = SRPolicyList{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRPolicyList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRPolicyList) ProtoMessage() {} + +func (x *SRPolicyList) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SRPolicyList.ProtoReflect.Descriptor instead. +func (*SRPolicyList) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{8} +} + +func (x *SRPolicyList) GetSrPolicies() []*SRPolicy { + if x != nil { + return x.SrPolicies + } + return nil +} + +type EndpointBehavior struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Behavior uint32 `protobuf:"varint,1,opt,name=behavior,proto3" json:"behavior,omitempty"` + Flags uint32 `protobuf:"varint,2,opt,name=flags,proto3" json:"flags,omitempty"` + Algorithm uint32 `protobuf:"varint,3,opt,name=algorithm,proto3" json:"algorithm,omitempty"` +} + +func (x *EndpointBehavior) Reset() { + *x = EndpointBehavior{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EndpointBehavior) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EndpointBehavior) ProtoMessage() {} + +func (x *EndpointBehavior) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EndpointBehavior.ProtoReflect.Descriptor instead. +func (*EndpointBehavior) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{9} +} + +func (x *EndpointBehavior) GetBehavior() uint32 { + if x != nil { + return x.Behavior + } + return 0 +} + +func (x *EndpointBehavior) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *EndpointBehavior) GetAlgorithm() uint32 { + if x != nil { + return x.Algorithm + } + return 0 +} + +type SidStructure struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalBlock uint32 `protobuf:"varint,1,opt,name=local_block,json=localBlock,proto3" json:"local_block,omitempty"` + LocalNode uint32 `protobuf:"varint,2,opt,name=local_node,json=localNode,proto3" json:"local_node,omitempty"` + LocalFunc uint32 `protobuf:"varint,3,opt,name=local_func,json=localFunc,proto3" json:"local_func,omitempty"` + LocalArg uint32 `protobuf:"varint,4,opt,name=local_arg,json=localArg,proto3" json:"local_arg,omitempty"` +} + +func (x *SidStructure) Reset() { + *x = SidStructure{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SidStructure) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SidStructure) ProtoMessage() {} + +func (x *SidStructure) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SidStructure.ProtoReflect.Descriptor instead. +func (*SidStructure) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{10} +} + +func (x *SidStructure) GetLocalBlock() uint32 { + if x != nil { + return x.LocalBlock + } + return 0 +} + +func (x *SidStructure) GetLocalNode() uint32 { + if x != nil { + return x.LocalNode + } + return 0 +} + +func (x *SidStructure) GetLocalFunc() uint32 { + if x != nil { + return x.LocalFunc + } + return 0 +} + +func (x *SidStructure) GetLocalArg() uint32 { + if x != nil { + return x.LocalArg + } + return 0 +} + +type SID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sid string `protobuf:"bytes,1,opt,name=sid,proto3" json:"sid,omitempty"` +} + +func (x *SID) Reset() { + *x = SID{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SID) ProtoMessage() {} + +func (x *SID) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SID.ProtoReflect.Descriptor instead. +func (*SID) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{11} +} + +func (x *SID) GetSid() string { + if x != nil { + return x.Sid + } + return "" +} + +type MultiTopoID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MultiTopoId uint32 `protobuf:"varint,1,opt,name=multi_topo_id,json=multiTopoId,proto3" json:"multi_topo_id,omitempty"` +} + +func (x *MultiTopoID) Reset() { + *x = MultiTopoID{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MultiTopoID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MultiTopoID) ProtoMessage() {} + +func (x *MultiTopoID) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MultiTopoID.ProtoReflect.Descriptor instead. +func (*MultiTopoID) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{12} +} + +func (x *MultiTopoID) GetMultiTopoId() uint32 { + if x != nil { + return x.MultiTopoId + } + return 0 +} + +type LsSrv6SID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sids []*SID `protobuf:"bytes,1,rep,name=sids,proto3" json:"sids,omitempty"` + EndpointBehavior *EndpointBehavior `protobuf:"bytes,2,opt,name=endpoint_behavior,json=endpointBehavior,proto3" json:"endpoint_behavior,omitempty"` + SidStructure *SidStructure `protobuf:"bytes,3,opt,name=sid_structure,json=sidStructure,proto3" json:"sid_structure,omitempty"` + MultiTopoIds []*MultiTopoID `protobuf:"bytes,4,rep,name=multi_topo_ids,json=multiTopoIds,proto3" json:"multi_topo_ids,omitempty"` +} + +func (x *LsSrv6SID) Reset() { + *x = LsSrv6SID{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsSrv6SID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsSrv6SID) ProtoMessage() {} + +func (x *LsSrv6SID) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LsSrv6SID.ProtoReflect.Descriptor instead. +func (*LsSrv6SID) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{13} +} + +func (x *LsSrv6SID) GetSids() []*SID { + if x != nil { + return x.Sids + } + return nil +} + +func (x *LsSrv6SID) GetEndpointBehavior() *EndpointBehavior { + if x != nil { + return x.EndpointBehavior + } + return nil +} + +func (x *LsSrv6SID) GetSidStructure() *SidStructure { + if x != nil { + return x.SidStructure + } + return nil +} + +func (x *LsSrv6SID) GetMultiTopoIds() []*MultiTopoID { + if x != nil { + return x.MultiTopoIds + } + return nil +} + +type LsPrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` + SidIndex uint32 `protobuf:"varint,2,opt,name=sid_index,json=sidIndex,proto3" json:"sid_index,omitempty"` +} + +func (x *LsPrefix) Reset() { + *x = LsPrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsPrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsPrefix) ProtoMessage() {} + +func (x *LsPrefix) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LsPrefix.ProtoReflect.Descriptor instead. +func (*LsPrefix) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{14} +} + +func (x *LsPrefix) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *LsPrefix) GetSidIndex() uint32 { + if x != nil { + return x.SidIndex + } + return 0 +} + +type Metric struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type MetricType `protobuf:"varint,1,opt,name=type,proto3,enum=api.pola.v1.MetricType" json:"type,omitempty"` + Value uint32 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Metric) Reset() { + *x = Metric{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Metric) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Metric) ProtoMessage() {} + +func (x *Metric) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Metric.ProtoReflect.Descriptor instead. +func (*Metric) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{15} +} + +func (x *Metric) GetType() MetricType { + if x != nil { + return x.Type + } + return MetricType_METRIC_TYPE_UNSPECIFIED +} + +func (x *Metric) GetValue() uint32 { + if x != nil { + return x.Value + } + return 0 +} + +type Srv6EndXSID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EndpointBehavior uint32 `protobuf:"varint,1,opt,name=endpoint_behavior,json=endpointBehavior,proto3" json:"endpoint_behavior,omitempty"` + Sids []*SID `protobuf:"bytes,2,rep,name=sids,proto3" json:"sids,omitempty"` + SidStructure *SidStructure `protobuf:"bytes,3,opt,name=sid_structure,json=sidStructure,proto3" json:"sid_structure,omitempty"` +} + +func (x *Srv6EndXSID) Reset() { + *x = Srv6EndXSID{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Srv6EndXSID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Srv6EndXSID) ProtoMessage() {} + +func (x *Srv6EndXSID) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Srv6EndXSID.ProtoReflect.Descriptor instead. +func (*Srv6EndXSID) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{16} +} + +func (x *Srv6EndXSID) GetEndpointBehavior() uint32 { + if x != nil { + return x.EndpointBehavior + } + return 0 +} + +func (x *Srv6EndXSID) GetSids() []*SID { + if x != nil { + return x.Sids + } + return nil +} + +func (x *Srv6EndXSID) GetSidStructure() *SidStructure { + if x != nil { + return x.SidStructure + } + return nil +} + +type LsLink struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalRouterId string `protobuf:"bytes,1,opt,name=local_router_id,json=localRouterId,proto3" json:"local_router_id,omitempty"` + LocalAsn uint32 `protobuf:"varint,2,opt,name=local_asn,json=localAsn,proto3" json:"local_asn,omitempty"` + LocalIp string `protobuf:"bytes,3,opt,name=local_ip,json=localIp,proto3" json:"local_ip,omitempty"` + RemoteRouterId string `protobuf:"bytes,4,opt,name=remote_router_id,json=remoteRouterId,proto3" json:"remote_router_id,omitempty"` + RemoteAsn uint32 `protobuf:"varint,5,opt,name=remote_asn,json=remoteAsn,proto3" json:"remote_asn,omitempty"` + RemoteIp string `protobuf:"bytes,6,opt,name=remote_ip,json=remoteIp,proto3" json:"remote_ip,omitempty"` + Metrics []*Metric `protobuf:"bytes,7,rep,name=metrics,proto3" json:"metrics,omitempty"` + AdjSid uint32 `protobuf:"varint,8,opt,name=adj_sid,json=adjSid,proto3" json:"adj_sid,omitempty"` + Srv6EndXSid *Srv6EndXSID `protobuf:"bytes,9,opt,name=srv6_end_x_sid,json=srv6EndXSid,proto3" json:"srv6_end_x_sid,omitempty"` +} + +func (x *LsLink) Reset() { + *x = LsLink{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsLink) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsLink) ProtoMessage() {} + +func (x *LsLink) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LsLink.ProtoReflect.Descriptor instead. +func (*LsLink) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{17} +} + +func (x *LsLink) GetLocalRouterId() string { + if x != nil { + return x.LocalRouterId + } + return "" +} + +func (x *LsLink) GetLocalAsn() uint32 { + if x != nil { + return x.LocalAsn + } + return 0 +} + +func (x *LsLink) GetLocalIp() string { + if x != nil { + return x.LocalIp + } + return "" +} + +func (x *LsLink) GetRemoteRouterId() string { + if x != nil { + return x.RemoteRouterId + } + return "" +} + +func (x *LsLink) GetRemoteAsn() uint32 { + if x != nil { + return x.RemoteAsn + } + return 0 +} + +func (x *LsLink) GetRemoteIp() string { + if x != nil { + return x.RemoteIp + } + return "" +} + +func (x *LsLink) GetMetrics() []*Metric { + if x != nil { + return x.Metrics + } + return nil +} + +func (x *LsLink) GetAdjSid() uint32 { + if x != nil { + return x.AdjSid + } + return 0 +} + +func (x *LsLink) GetSrv6EndXSid() *Srv6EndXSID { + if x != nil { + return x.Srv6EndXSid + } + return nil +} + +type LsNode struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + RouterId string `protobuf:"bytes,2,opt,name=router_id,json=routerId,proto3" json:"router_id,omitempty"` + IsisAreaId string `protobuf:"bytes,3,opt,name=isis_area_id,json=isisAreaId,proto3" json:"isis_area_id,omitempty"` + Hostname string `protobuf:"bytes,4,opt,name=hostname,proto3" json:"hostname,omitempty"` + SrgbBegin uint32 `protobuf:"varint,5,opt,name=srgb_begin,json=srgbBegin,proto3" json:"srgb_begin,omitempty"` + SrgbEnd uint32 `protobuf:"varint,6,opt,name=srgb_end,json=srgbEnd,proto3" json:"srgb_end,omitempty"` + LsLinks []*LsLink `protobuf:"bytes,7,rep,name=ls_links,json=lsLinks,proto3" json:"ls_links,omitempty"` + LsPrefixes []*LsPrefix `protobuf:"bytes,8,rep,name=ls_prefixes,json=lsPrefixes,proto3" json:"ls_prefixes,omitempty"` + LsSrv6Sids []*LsSrv6SID `protobuf:"bytes,9,rep,name=ls_srv6_sids,json=lsSrv6Sids,proto3" json:"ls_srv6_sids,omitempty"` +} + +func (x *LsNode) Reset() { + *x = LsNode{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsNode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsNode) ProtoMessage() {} + +func (x *LsNode) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LsNode.ProtoReflect.Descriptor instead. +func (*LsNode) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{18} +} + +func (x *LsNode) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *LsNode) GetRouterId() string { + if x != nil { + return x.RouterId + } + return "" +} + +func (x *LsNode) GetIsisAreaId() string { + if x != nil { + return x.IsisAreaId + } + return "" +} + +func (x *LsNode) GetHostname() string { + if x != nil { + return x.Hostname + } + return "" +} + +func (x *LsNode) GetSrgbBegin() uint32 { + if x != nil { + return x.SrgbBegin + } + return 0 +} + +func (x *LsNode) GetSrgbEnd() uint32 { + if x != nil { + return x.SrgbEnd + } + return 0 +} + +func (x *LsNode) GetLsLinks() []*LsLink { + if x != nil { + return x.LsLinks + } + return nil +} + +func (x *LsNode) GetLsPrefixes() []*LsPrefix { + if x != nil { + return x.LsPrefixes + } + return nil +} + +func (x *LsNode) GetLsSrv6Sids() []*LsSrv6SID { + if x != nil { + return x.LsSrv6Sids + } + return nil +} + +type TED struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"` + LsNodes []*LsNode `protobuf:"bytes,2,rep,name=ls_nodes,json=lsNodes,proto3" json:"ls_nodes,omitempty"` +} + +func (x *TED) Reset() { + *x = TED{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TED) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TED) ProtoMessage() {} + +func (x *TED) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TED.ProtoReflect.Descriptor instead. +func (*TED) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{19} +} + +func (x *TED) GetEnable() bool { + if x != nil { + return x.Enable + } + return false +} + +func (x *TED) GetLsNodes() []*LsNode { + if x != nil { + return x.LsNodes + } + return nil +} + +type GetSessionListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetSessionListRequest) Reset() { + *x = GetSessionListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSessionListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSessionListRequest) ProtoMessage() {} + +func (x *GetSessionListRequest) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSessionListRequest.ProtoReflect.Descriptor instead. +func (*GetSessionListRequest) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{20} +} + +type GetSessionListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sessions []*Session `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` +} + +func (x *GetSessionListResponse) Reset() { + *x = GetSessionListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSessionListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSessionListResponse) ProtoMessage() {} + +func (x *GetSessionListResponse) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSessionListResponse.ProtoReflect.Descriptor instead. +func (*GetSessionListResponse) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{21} +} + +func (x *GetSessionListResponse) GetSessions() []*Session { + if x != nil { + return x.Sessions + } + return nil +} + +type GetSRPolicyListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetSRPolicyListRequest) Reset() { + *x = GetSRPolicyListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSRPolicyListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSRPolicyListRequest) ProtoMessage() {} + +func (x *GetSRPolicyListRequest) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSRPolicyListRequest.ProtoReflect.Descriptor instead. +func (*GetSRPolicyListRequest) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{22} +} + +type GetSRPolicyListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SrPolicies []*SRPolicy `protobuf:"bytes,1,rep,name=sr_policies,json=srPolicies,proto3" json:"sr_policies,omitempty"` +} + +func (x *GetSRPolicyListResponse) Reset() { + *x = GetSRPolicyListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSRPolicyListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSRPolicyListResponse) ProtoMessage() {} + +func (x *GetSRPolicyListResponse) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSRPolicyListResponse.ProtoReflect.Descriptor instead. +func (*GetSRPolicyListResponse) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{23} +} + +func (x *GetSRPolicyListResponse) GetSrPolicies() []*SRPolicy { + if x != nil { + return x.SrPolicies + } + return nil +} + +type GetTEDRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetTEDRequest) Reset() { + *x = GetTEDRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTEDRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTEDRequest) ProtoMessage() {} + +func (x *GetTEDRequest) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTEDRequest.ProtoReflect.Descriptor instead. +func (*GetTEDRequest) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{24} +} + +type GetTEDResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"` + LsNodes []*LsNode `protobuf:"bytes,2,rep,name=ls_nodes,json=lsNodes,proto3" json:"ls_nodes,omitempty"` +} + +func (x *GetTEDResponse) Reset() { + *x = GetTEDResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTEDResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTEDResponse) ProtoMessage() {} + +func (x *GetTEDResponse) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTEDResponse.ProtoReflect.Descriptor instead. +func (*GetTEDResponse) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{25} +} + +func (x *GetTEDResponse) GetEnable() bool { + if x != nil { + return x.Enable + } + return false +} + +func (x *GetTEDResponse) GetLsNodes() []*LsNode { + if x != nil { + return x.LsNodes + } + return nil +} + +type DeleteSessionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Addr []byte `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` +} + +func (x *DeleteSessionRequest) Reset() { + *x = DeleteSessionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSessionRequest) ProtoMessage() {} + +func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSessionRequest.ProtoReflect.Descriptor instead. +func (*DeleteSessionRequest) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{26} +} + +func (x *DeleteSessionRequest) GetAddr() []byte { + if x != nil { + return x.Addr + } + return nil +} + +type DeleteSessionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsSuccess bool `protobuf:"varint,1,opt,name=is_success,json=isSuccess,proto3" json:"is_success,omitempty"` +} + +func (x *DeleteSessionResponse) Reset() { + *x = DeleteSessionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pola_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSessionResponse) ProtoMessage() {} + +func (x *DeleteSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_pola_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSessionResponse.ProtoReflect.Descriptor instead. +func (*DeleteSessionResponse) Descriptor() ([]byte, []int) { + return file_pola_proto_rawDescGZIP(), []int{27} +} + +func (x *DeleteSessionResponse) GetIsSuccess() bool { + if x != nil { + return x.IsSuccess + } + return false +} + +var File_pola_proto protoreflect.FileDescriptor + +var file_pola_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x22, 0x80, 0x01, 0x0a, 0x07, 0x53, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x69, 0x64, 0x5f, 0x73, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x73, 0x69, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x72, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x22, 0xa4, 0x03, 0x0a, + 0x08, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x63, 0x65, + 0x70, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x70, 0x63, 0x65, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, + 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x73, + 0x72, 0x63, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x73, 0x72, 0x63, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x64, 0x73, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x70, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, + 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, + 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x22, 0x80, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x52, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, + 0x09, 0x73, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x73, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, + 0x61, 0x73, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, 0x69, 0x64, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x22, 0x37, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, + 0x5d, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x72, 0x5f, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x52, 0x08, 0x73, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x61, 0x73, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x22, 0x37, + 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, + 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x7f, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x61, 0x70, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x63, 0x61, 0x70, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, + 0x73, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x69, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x22, 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x46, 0x0a, 0x0c, 0x53, 0x52, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0b, 0x73, 0x72, 0x5f, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x52, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x73, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x22, 0x62, 0x0a, 0x10, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, + 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, + 0x72, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, + 0x69, 0x74, 0x68, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, + 0x72, 0x69, 0x74, 0x68, 0x6d, 0x22, 0x8a, 0x01, 0x0a, 0x0c, 0x53, 0x69, 0x64, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, + 0x66, 0x75, 0x6e, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x46, 0x75, 0x6e, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, + 0x72, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, + 0x72, 0x67, 0x22, 0x17, 0x0a, 0x03, 0x53, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x22, 0x31, 0x0a, 0x0b, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x54, 0x6f, 0x70, 0x6f, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x75, + 0x6c, 0x74, 0x69, 0x5f, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x6f, 0x70, 0x6f, 0x49, 0x64, 0x22, 0xfd, + 0x01, 0x0a, 0x09, 0x4c, 0x73, 0x53, 0x72, 0x76, 0x36, 0x53, 0x49, 0x44, 0x12, 0x24, 0x0a, 0x04, + 0x73, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x49, 0x44, 0x52, 0x04, 0x73, 0x69, + 0x64, 0x73, 0x12, 0x4a, 0x0a, 0x11, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x62, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x10, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x3e, + 0x0a, 0x0d, 0x73, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x0c, 0x73, 0x69, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x3e, + 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x74, 0x6f, 0x70, 0x6f, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, + 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x6f, 0x70, 0x6f, 0x49, 0x44, + 0x52, 0x0c, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x6f, 0x70, 0x6f, 0x49, 0x64, 0x73, 0x22, 0x3f, + 0x0a, 0x08, 0x4c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x69, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, + 0x4b, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, + 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa0, 0x01, 0x0a, + 0x0b, 0x53, 0x72, 0x76, 0x36, 0x45, 0x6e, 0x64, 0x58, 0x53, 0x49, 0x44, 0x12, 0x2b, 0x0a, 0x11, + 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x24, 0x0a, 0x04, 0x73, 0x69, 0x64, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, + 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x49, 0x44, 0x52, 0x04, 0x73, 0x69, 0x64, 0x73, 0x12, + 0x3e, 0x0a, 0x0d, 0x73, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, + 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x0c, 0x73, 0x69, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x22, + 0xd5, 0x02, 0x0a, 0x06, 0x4c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x73, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x73, 0x6e, 0x12, + 0x19, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x61, + 0x73, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x41, 0x73, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x70, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x70, + 0x12, 0x2d, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, + 0x17, 0x0a, 0x07, 0x61, 0x64, 0x6a, 0x5f, 0x73, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x06, 0x61, 0x64, 0x6a, 0x53, 0x69, 0x64, 0x12, 0x3d, 0x0a, 0x0e, 0x73, 0x72, 0x76, 0x36, + 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x78, 0x5f, 0x73, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x72, 0x76, 0x36, 0x45, 0x6e, 0x64, 0x58, 0x53, 0x49, 0x44, 0x52, 0x0b, 0x73, 0x72, 0x76, 0x36, + 0x45, 0x6e, 0x64, 0x58, 0x53, 0x69, 0x64, 0x22, 0xd1, 0x02, 0x0a, 0x06, 0x4c, 0x73, 0x4e, 0x6f, + 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x73, 0x69, 0x73, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x73, 0x69, 0x73, 0x41, 0x72, 0x65, + 0x61, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x72, 0x67, 0x62, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x72, 0x67, 0x62, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x19, + 0x0a, 0x08, 0x73, 0x72, 0x67, 0x62, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x73, 0x72, 0x67, 0x62, 0x45, 0x6e, 0x64, 0x12, 0x2e, 0x0a, 0x08, 0x6c, 0x73, 0x5f, + 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, + 0x52, 0x07, 0x6c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x6c, 0x73, 0x5f, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x73, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x0a, 0x6c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, + 0x73, 0x12, 0x38, 0x0a, 0x0c, 0x6c, 0x73, 0x5f, 0x73, 0x72, 0x76, 0x36, 0x5f, 0x73, 0x69, 0x64, + 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, + 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x73, 0x53, 0x72, 0x76, 0x36, 0x53, 0x49, 0x44, 0x52, + 0x0a, 0x6c, 0x73, 0x53, 0x72, 0x76, 0x36, 0x53, 0x69, 0x64, 0x73, 0x22, 0x4d, 0x0a, 0x03, 0x54, + 0x45, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x6c, 0x73, + 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x07, 0x6c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, + 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0x4a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, + 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x51, 0x0a, 0x17, 0x47, 0x65, 0x74, + 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x73, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x0a, 0x73, 0x72, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x0f, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x54, 0x45, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x58, 0x0a, + 0x0e, 0x47, 0x65, 0x74, 0x54, 0x45, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x6c, 0x73, 0x5f, 0x6e, 0x6f, + 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, + 0x6c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x2a, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x61, + 0x64, 0x64, 0x72, 0x22, 0x36, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x69, 0x73, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2a, 0x67, 0x0a, 0x0c, 0x53, + 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x53, + 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, + 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, + 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x52, 0x5f, 0x50, + 0x4f, 0x4c, 0x49, 0x43, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, + 0x49, 0x43, 0x10, 0x02, 0x2a, 0x5b, 0x0a, 0x0c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, + 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x50, 0x10, + 0x02, 0x2a, 0x83, 0x01, 0x0a, 0x0a, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, + 0x0f, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x47, 0x50, + 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x54, 0x45, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x41, 0x59, 0x10, 0x03, 0x12, 0x18, 0x0a, + 0x14, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x48, 0x4f, 0x50, + 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x04, 0x32, 0x96, 0x04, 0x0a, 0x0a, 0x50, 0x43, 0x45, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, + 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x52, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x59, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, + 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x52, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x22, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x52, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x23, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x52, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x53, 0x52, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x54, 0x45, 0x44, 0x12, + 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x45, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x45, 0x44, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x70, 0x6f, 0x6c, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6e, + 0x74, 0x74, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6c, 0x61, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, + 0x6f, 0x6c, 0x61, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pola_proto_rawDescOnce sync.Once + file_pola_proto_rawDescData = file_pola_proto_rawDesc +) + +func file_pola_proto_rawDescGZIP() []byte { + file_pola_proto_rawDescOnce.Do(func() { + file_pola_proto_rawDescData = protoimpl.X.CompressGZIP(file_pola_proto_rawDescData) + }) + return file_pola_proto_rawDescData +} + +var file_pola_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_pola_proto_msgTypes = make([]protoimpl.MessageInfo, 28) +var file_pola_proto_goTypes = []interface{}{ + (SRPolicyType)(0), // 0: api.pola.v1.SRPolicyType + (SessionState)(0), // 1: api.pola.v1.SessionState + (MetricType)(0), // 2: api.pola.v1.MetricType + (*Segment)(nil), // 3: api.pola.v1.Segment + (*SRPolicy)(nil), // 4: api.pola.v1.SRPolicy + (*CreateSRPolicyRequest)(nil), // 5: api.pola.v1.CreateSRPolicyRequest + (*CreateSRPolicyResponse)(nil), // 6: api.pola.v1.CreateSRPolicyResponse + (*DeleteSRPolicyRequest)(nil), // 7: api.pola.v1.DeleteSRPolicyRequest + (*DeleteSRPolicyResponse)(nil), // 8: api.pola.v1.DeleteSRPolicyResponse + (*Session)(nil), // 9: api.pola.v1.Session + (*SessionList)(nil), // 10: api.pola.v1.SessionList + (*SRPolicyList)(nil), // 11: api.pola.v1.SRPolicyList + (*EndpointBehavior)(nil), // 12: api.pola.v1.EndpointBehavior + (*SidStructure)(nil), // 13: api.pola.v1.SidStructure + (*SID)(nil), // 14: api.pola.v1.SID + (*MultiTopoID)(nil), // 15: api.pola.v1.MultiTopoID + (*LsSrv6SID)(nil), // 16: api.pola.v1.LsSrv6SID + (*LsPrefix)(nil), // 17: api.pola.v1.LsPrefix + (*Metric)(nil), // 18: api.pola.v1.Metric + (*Srv6EndXSID)(nil), // 19: api.pola.v1.Srv6EndXSID + (*LsLink)(nil), // 20: api.pola.v1.LsLink + (*LsNode)(nil), // 21: api.pola.v1.LsNode + (*TED)(nil), // 22: api.pola.v1.TED + (*GetSessionListRequest)(nil), // 23: api.pola.v1.GetSessionListRequest + (*GetSessionListResponse)(nil), // 24: api.pola.v1.GetSessionListResponse + (*GetSRPolicyListRequest)(nil), // 25: api.pola.v1.GetSRPolicyListRequest + (*GetSRPolicyListResponse)(nil), // 26: api.pola.v1.GetSRPolicyListResponse + (*GetTEDRequest)(nil), // 27: api.pola.v1.GetTEDRequest + (*GetTEDResponse)(nil), // 28: api.pola.v1.GetTEDResponse + (*DeleteSessionRequest)(nil), // 29: api.pola.v1.DeleteSessionRequest + (*DeleteSessionResponse)(nil), // 30: api.pola.v1.DeleteSessionResponse +} +var file_pola_proto_depIdxs = []int32{ + 0, // 0: api.pola.v1.SRPolicy.type:type_name -> api.pola.v1.SRPolicyType + 3, // 1: api.pola.v1.SRPolicy.segment_list:type_name -> api.pola.v1.Segment + 2, // 2: api.pola.v1.SRPolicy.metric:type_name -> api.pola.v1.MetricType + 4, // 3: api.pola.v1.CreateSRPolicyRequest.sr_policy:type_name -> api.pola.v1.SRPolicy + 4, // 4: api.pola.v1.DeleteSRPolicyRequest.sr_policy:type_name -> api.pola.v1.SRPolicy + 1, // 5: api.pola.v1.Session.state:type_name -> api.pola.v1.SessionState + 9, // 6: api.pola.v1.SessionList.sessions:type_name -> api.pola.v1.Session + 4, // 7: api.pola.v1.SRPolicyList.sr_policies:type_name -> api.pola.v1.SRPolicy + 14, // 8: api.pola.v1.LsSrv6SID.sids:type_name -> api.pola.v1.SID + 12, // 9: api.pola.v1.LsSrv6SID.endpoint_behavior:type_name -> api.pola.v1.EndpointBehavior + 13, // 10: api.pola.v1.LsSrv6SID.sid_structure:type_name -> api.pola.v1.SidStructure + 15, // 11: api.pola.v1.LsSrv6SID.multi_topo_ids:type_name -> api.pola.v1.MultiTopoID + 2, // 12: api.pola.v1.Metric.type:type_name -> api.pola.v1.MetricType + 14, // 13: api.pola.v1.Srv6EndXSID.sids:type_name -> api.pola.v1.SID + 13, // 14: api.pola.v1.Srv6EndXSID.sid_structure:type_name -> api.pola.v1.SidStructure + 18, // 15: api.pola.v1.LsLink.metrics:type_name -> api.pola.v1.Metric + 19, // 16: api.pola.v1.LsLink.srv6_end_x_sid:type_name -> api.pola.v1.Srv6EndXSID + 20, // 17: api.pola.v1.LsNode.ls_links:type_name -> api.pola.v1.LsLink + 17, // 18: api.pola.v1.LsNode.ls_prefixes:type_name -> api.pola.v1.LsPrefix + 16, // 19: api.pola.v1.LsNode.ls_srv6_sids:type_name -> api.pola.v1.LsSrv6SID + 21, // 20: api.pola.v1.TED.ls_nodes:type_name -> api.pola.v1.LsNode + 9, // 21: api.pola.v1.GetSessionListResponse.sessions:type_name -> api.pola.v1.Session + 4, // 22: api.pola.v1.GetSRPolicyListResponse.sr_policies:type_name -> api.pola.v1.SRPolicy + 21, // 23: api.pola.v1.GetTEDResponse.ls_nodes:type_name -> api.pola.v1.LsNode + 5, // 24: api.pola.v1.PCEService.CreateSRPolicy:input_type -> api.pola.v1.CreateSRPolicyRequest + 7, // 25: api.pola.v1.PCEService.DeleteSRPolicy:input_type -> api.pola.v1.DeleteSRPolicyRequest + 23, // 26: api.pola.v1.PCEService.GetSessionList:input_type -> api.pola.v1.GetSessionListRequest + 25, // 27: api.pola.v1.PCEService.GetSRPolicyList:input_type -> api.pola.v1.GetSRPolicyListRequest + 27, // 28: api.pola.v1.PCEService.GetTED:input_type -> api.pola.v1.GetTEDRequest + 29, // 29: api.pola.v1.PCEService.DeleteSession:input_type -> api.pola.v1.DeleteSessionRequest + 6, // 30: api.pola.v1.PCEService.CreateSRPolicy:output_type -> api.pola.v1.CreateSRPolicyResponse + 8, // 31: api.pola.v1.PCEService.DeleteSRPolicy:output_type -> api.pola.v1.DeleteSRPolicyResponse + 24, // 32: api.pola.v1.PCEService.GetSessionList:output_type -> api.pola.v1.GetSessionListResponse + 26, // 33: api.pola.v1.PCEService.GetSRPolicyList:output_type -> api.pola.v1.GetSRPolicyListResponse + 28, // 34: api.pola.v1.PCEService.GetTED:output_type -> api.pola.v1.GetTEDResponse + 30, // 35: api.pola.v1.PCEService.DeleteSession:output_type -> api.pola.v1.DeleteSessionResponse + 30, // [30:36] is the sub-list for method output_type + 24, // [24:30] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name +} + +func init() { file_pola_proto_init() } +func file_pola_proto_init() { + if File_pola_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pola_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Segment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRPolicy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateSRPolicyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateSRPolicyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteSRPolicyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteSRPolicyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Session); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SessionList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRPolicyList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EndpointBehavior); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SidStructure); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MultiTopoID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsSrv6SID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsPrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Metric); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Srv6EndXSID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsLink); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsNode); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TED); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSessionListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSessionListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSRPolicyListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSRPolicyListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTEDRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTEDResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteSessionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pola_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteSessionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pola_proto_rawDesc, + NumEnums: 3, + NumMessages: 28, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_pola_proto_goTypes, + DependencyIndexes: file_pola_proto_depIdxs, + EnumInfos: file_pola_proto_enumTypes, + MessageInfos: file_pola_proto_msgTypes, + }.Build() + File_pola_proto = out.File + file_pola_proto_rawDesc = nil + file_pola_proto_goTypes = nil + file_pola_proto_depIdxs = nil +} diff --git a/api/pola/v1/pola.proto b/api/pola/v1/pola.proto new file mode 100644 index 00000000..100f6346 --- /dev/null +++ b/api/pola/v1/pola.proto @@ -0,0 +1,197 @@ +// Copyright (c) 2022 NTT Communications Corporation +// +// This software is released under the MIT License. +// see https://github.com/nttcom/pola/blob/main/LICENSE + +syntax = "proto3"; + +package api.pola.v1; + +option go_package = "github.com/nttcom/pola/api/pola/v1"; + +service PCEService { + rpc CreateSRPolicy (CreateSRPolicyRequest) returns (CreateSRPolicyResponse); + rpc DeleteSRPolicy (DeleteSRPolicyRequest) returns (DeleteSRPolicyResponse); + rpc GetSessionList (GetSessionListRequest) returns (GetSessionListResponse); + rpc GetSRPolicyList (GetSRPolicyListRequest) returns (GetSRPolicyListResponse); + rpc GetTED (GetTEDRequest) returns (GetTEDResponse); + rpc DeleteSession (DeleteSessionRequest) returns (DeleteSessionResponse); +} + +message Segment { + string sid = 1; + string sid_structure = 2; + string local_addr = 3; + string remote_addr = 4; +} + +enum SRPolicyType { + SR_POLICY_TYPE_UNSPECIFIED = 0; + SR_POLICY_TYPE_EXPLICIT = 1; + SR_POLICY_TYPE_DYNAMIC = 2; +} + +message SRPolicy { + bytes pcep_session_addr = 1; + bytes src_addr = 2; + bytes dst_addr = 3; + string src_router_id = 4; + string dst_router_id = 5; + uint32 color = 6; + uint32 preference = 7; + string policy_name = 8; + SRPolicyType type = 9; + repeated Segment segment_list = 10; + MetricType metric = 11; +} + +message CreateSRPolicyRequest { + SRPolicy sr_policy = 1; + uint32 asn = 2; + bool sid_validate = 3; +} + +message CreateSRPolicyResponse { + bool is_success = 1; +} + +message DeleteSRPolicyRequest { + SRPolicy sr_policy = 1; + uint32 asn = 2; +} + +message DeleteSRPolicyResponse { + bool is_success = 1; +} + +enum SessionState { + SESSION_STATE_UNSPECIFIED = 0; + SESSION_STATE_DOWN = 1; + SESSION_STATE_UP = 2; +} + +message Session { + bytes addr = 1; + SessionState state = 2; + repeated string caps = 3; + bool is_synced = 4; +} + +message SessionList { + repeated Session sessions = 1; +} + +message SRPolicyList { + repeated SRPolicy sr_policies = 1; +} + +message EndpointBehavior { + uint32 behavior = 1; + uint32 flags = 2; + uint32 algorithm = 3; +} + +message SidStructure { + uint32 local_block = 1; + uint32 local_node = 2; + uint32 local_func = 3; + uint32 local_arg = 4; +} + +message SID { + string sid = 1; +} + +message MultiTopoID { + uint32 multi_topo_id = 1; +} + +message LsSrv6SID { + repeated SID sids = 1; + EndpointBehavior endpoint_behavior = 2; + SidStructure sid_structure = 3; + repeated MultiTopoID multi_topo_ids = 4; +} + +message LsPrefix { + string prefix = 1; + uint32 sid_index = 2; +} + +enum MetricType { + METRIC_TYPE_UNSPECIFIED = 0; + METRIC_TYPE_IGP = 1; + METRIC_TYPE_TE = 2; + METRIC_TYPE_DELAY = 3; + METRIC_TYPE_HOPCOUNT = 4; +} + +message Metric { + MetricType type = 1; + uint32 value = 2; +} + +message Srv6EndXSID { + uint32 endpoint_behavior = 1; + repeated SID sids = 2; + SidStructure sid_structure = 3; +} + +message LsLink { + string local_router_id = 1; + uint32 local_asn = 2; + string local_ip = 3; + string remote_router_id = 4; + uint32 remote_asn = 5; + string remote_ip = 6; + repeated Metric metrics = 7; + uint32 adj_sid = 8; + Srv6EndXSID srv6_end_x_sid = 9; +} + +message LsNode { + uint32 asn = 1; + string router_id = 2; + string isis_area_id = 3; + string hostname = 4; + uint32 srgb_begin = 5; + uint32 srgb_end = 6; + repeated LsLink ls_links = 7; + repeated LsPrefix ls_prefixes = 8; + repeated LsSrv6SID ls_srv6_sids = 9; +} + +message TED { + bool enable = 1; + repeated LsNode ls_nodes = 2; +} + +message GetSessionListRequest { +} + +message GetSessionListResponse { + repeated Session sessions = 1; +} + +message GetSRPolicyListRequest { +} + +message GetSRPolicyListResponse { + repeated SRPolicy sr_policies = 1; +} + +message GetTEDRequest { +} + +message GetTEDResponse { + bool enable = 1; + repeated LsNode ls_nodes = 2; +} + +message DeleteSessionRequest { + bytes addr = 1; +} + +message DeleteSessionResponse { + bool is_success = 1; +} diff --git a/api/grpc/pola.zap.go b/api/pola/v1/pola.zap.go similarity index 78% rename from api/grpc/pola.zap.go rename to api/pola/v1/pola.zap.go index b4c360b9..e13fdbdd 100644 --- a/api/grpc/pola.zap.go +++ b/api/pola/v1/pola.zap.go @@ -3,7 +3,7 @@ // This software is released under the MIT License. // see https://github.com/nttcom/pola/blob/main/LICENSE -package grpc +package v1 import ( "net/netip" @@ -15,15 +15,15 @@ import ( func (x *SRPolicy) MarshalLogObject(enc zapcore.ObjectEncoder) error { // Convert IP address slices to netip.Addr ssAddr, _ := netip.AddrFromSlice(x.GetPcepSessionAddr()) - enc.AddString("PcepSessionAddr", ssAddr.String()) + enc.AddString("PCEPSessionAddr", ssAddr.String()) srcAddr, _ := netip.AddrFromSlice(x.GetSrcAddr()) enc.AddString("SrcAddr", srcAddr.String()) dstAddr, _ := netip.AddrFromSlice(x.GetDstAddr()) enc.AddString("DstAddr", dstAddr.String()) - if srcRouterID := x.GetSrcRouterID(); srcRouterID != "" { + if srcRouterID := x.GetSrcRouterId(); srcRouterID != "" { enc.AddString("SrcRouterID", srcRouterID) } - if dstRouterID := x.DstRouterID; dstRouterID != "" { + if dstRouterID := x.DstRouterId; dstRouterID != "" { enc.AddString("DstRouterID", dstRouterID) } enc.AddUint32("Color", x.GetColor()) @@ -31,11 +31,11 @@ func (x *SRPolicy) MarshalLogObject(enc zapcore.ObjectEncoder) error { enc.AddString("PolicyName", x.GetPolicyName()) enc.AddString("Type", x.GetType().String()) - if x.GetType() == SRPolicyType_EXPLICIT { + if x.GetType() == SRPolicyType_SR_POLICY_TYPE_EXPLICIT { if err := enc.AddReflected("SegmentList", x.GetSegmentList()); err != nil { return err } - } else if x.GetType() == SRPolicyType_DYNAMIC { + } else if x.GetType() == SRPolicyType_SR_POLICY_TYPE_DYNAMIC { enc.AddString("Metric", x.Metric.String()) } return nil @@ -43,6 +43,6 @@ func (x *SRPolicy) MarshalLogObject(enc zapcore.ObjectEncoder) error { // Implements zapcore.ObjectMarshaler interface for Segment func (x *Segment) MarshalLogObject(enc zapcore.ObjectEncoder) error { - enc.AddString("Sid", x.GetSid()) + enc.AddString("SID", x.GetSid()) return nil } diff --git a/api/pola/v1/pola_grpc.pb.go b/api/pola/v1/pola_grpc.pb.go new file mode 100644 index 00000000..3c6b0a90 --- /dev/null +++ b/api/pola/v1/pola_grpc.pb.go @@ -0,0 +1,281 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// PCEServiceClient is the client API for PCEService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PCEServiceClient interface { + CreateSRPolicy(ctx context.Context, in *CreateSRPolicyRequest, opts ...grpc.CallOption) (*CreateSRPolicyResponse, error) + DeleteSRPolicy(ctx context.Context, in *DeleteSRPolicyRequest, opts ...grpc.CallOption) (*DeleteSRPolicyResponse, error) + GetSessionList(ctx context.Context, in *GetSessionListRequest, opts ...grpc.CallOption) (*GetSessionListResponse, error) + GetSRPolicyList(ctx context.Context, in *GetSRPolicyListRequest, opts ...grpc.CallOption) (*GetSRPolicyListResponse, error) + GetTED(ctx context.Context, in *GetTEDRequest, opts ...grpc.CallOption) (*GetTEDResponse, error) + DeleteSession(ctx context.Context, in *DeleteSessionRequest, opts ...grpc.CallOption) (*DeleteSessionResponse, error) +} + +type pCEServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewPCEServiceClient(cc grpc.ClientConnInterface) PCEServiceClient { + return &pCEServiceClient{cc} +} + +func (c *pCEServiceClient) CreateSRPolicy(ctx context.Context, in *CreateSRPolicyRequest, opts ...grpc.CallOption) (*CreateSRPolicyResponse, error) { + out := new(CreateSRPolicyResponse) + err := c.cc.Invoke(ctx, "/api.pola.v1.PCEService/CreateSRPolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pCEServiceClient) DeleteSRPolicy(ctx context.Context, in *DeleteSRPolicyRequest, opts ...grpc.CallOption) (*DeleteSRPolicyResponse, error) { + out := new(DeleteSRPolicyResponse) + err := c.cc.Invoke(ctx, "/api.pola.v1.PCEService/DeleteSRPolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pCEServiceClient) GetSessionList(ctx context.Context, in *GetSessionListRequest, opts ...grpc.CallOption) (*GetSessionListResponse, error) { + out := new(GetSessionListResponse) + err := c.cc.Invoke(ctx, "/api.pola.v1.PCEService/GetSessionList", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pCEServiceClient) GetSRPolicyList(ctx context.Context, in *GetSRPolicyListRequest, opts ...grpc.CallOption) (*GetSRPolicyListResponse, error) { + out := new(GetSRPolicyListResponse) + err := c.cc.Invoke(ctx, "/api.pola.v1.PCEService/GetSRPolicyList", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pCEServiceClient) GetTED(ctx context.Context, in *GetTEDRequest, opts ...grpc.CallOption) (*GetTEDResponse, error) { + out := new(GetTEDResponse) + err := c.cc.Invoke(ctx, "/api.pola.v1.PCEService/GetTED", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pCEServiceClient) DeleteSession(ctx context.Context, in *DeleteSessionRequest, opts ...grpc.CallOption) (*DeleteSessionResponse, error) { + out := new(DeleteSessionResponse) + err := c.cc.Invoke(ctx, "/api.pola.v1.PCEService/DeleteSession", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// PCEServiceServer is the server API for PCEService service. +// All implementations must embed UnimplementedPCEServiceServer +// for forward compatibility +type PCEServiceServer interface { + CreateSRPolicy(context.Context, *CreateSRPolicyRequest) (*CreateSRPolicyResponse, error) + DeleteSRPolicy(context.Context, *DeleteSRPolicyRequest) (*DeleteSRPolicyResponse, error) + GetSessionList(context.Context, *GetSessionListRequest) (*GetSessionListResponse, error) + GetSRPolicyList(context.Context, *GetSRPolicyListRequest) (*GetSRPolicyListResponse, error) + GetTED(context.Context, *GetTEDRequest) (*GetTEDResponse, error) + DeleteSession(context.Context, *DeleteSessionRequest) (*DeleteSessionResponse, error) + mustEmbedUnimplementedPCEServiceServer() +} + +// UnimplementedPCEServiceServer must be embedded to have forward compatible implementations. +type UnimplementedPCEServiceServer struct { +} + +func (UnimplementedPCEServiceServer) CreateSRPolicy(context.Context, *CreateSRPolicyRequest) (*CreateSRPolicyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateSRPolicy not implemented") +} +func (UnimplementedPCEServiceServer) DeleteSRPolicy(context.Context, *DeleteSRPolicyRequest) (*DeleteSRPolicyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteSRPolicy not implemented") +} +func (UnimplementedPCEServiceServer) GetSessionList(context.Context, *GetSessionListRequest) (*GetSessionListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSessionList not implemented") +} +func (UnimplementedPCEServiceServer) GetSRPolicyList(context.Context, *GetSRPolicyListRequest) (*GetSRPolicyListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSRPolicyList not implemented") +} +func (UnimplementedPCEServiceServer) GetTED(context.Context, *GetTEDRequest) (*GetTEDResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTED not implemented") +} +func (UnimplementedPCEServiceServer) DeleteSession(context.Context, *DeleteSessionRequest) (*DeleteSessionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteSession not implemented") +} +func (UnimplementedPCEServiceServer) mustEmbedUnimplementedPCEServiceServer() {} + +// UnsafePCEServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PCEServiceServer will +// result in compilation errors. +type UnsafePCEServiceServer interface { + mustEmbedUnimplementedPCEServiceServer() +} + +func RegisterPCEServiceServer(s grpc.ServiceRegistrar, srv PCEServiceServer) { + s.RegisterService(&PCEService_ServiceDesc, srv) +} + +func _PCEService_CreateSRPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateSRPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PCEServiceServer).CreateSRPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.pola.v1.PCEService/CreateSRPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PCEServiceServer).CreateSRPolicy(ctx, req.(*CreateSRPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PCEService_DeleteSRPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteSRPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PCEServiceServer).DeleteSRPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.pola.v1.PCEService/DeleteSRPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PCEServiceServer).DeleteSRPolicy(ctx, req.(*DeleteSRPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PCEService_GetSessionList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSessionListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PCEServiceServer).GetSessionList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.pola.v1.PCEService/GetSessionList", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PCEServiceServer).GetSessionList(ctx, req.(*GetSessionListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PCEService_GetSRPolicyList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSRPolicyListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PCEServiceServer).GetSRPolicyList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.pola.v1.PCEService/GetSRPolicyList", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PCEServiceServer).GetSRPolicyList(ctx, req.(*GetSRPolicyListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PCEService_GetTED_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTEDRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PCEServiceServer).GetTED(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.pola.v1.PCEService/GetTED", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PCEServiceServer).GetTED(ctx, req.(*GetTEDRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PCEService_DeleteSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteSessionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PCEServiceServer).DeleteSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.pola.v1.PCEService/DeleteSession", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PCEServiceServer).DeleteSession(ctx, req.(*DeleteSessionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// PCEService_ServiceDesc is the grpc.ServiceDesc for PCEService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var PCEService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "api.pola.v1.PCEService", + HandlerType: (*PCEServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateSRPolicy", + Handler: _PCEService_CreateSRPolicy_Handler, + }, + { + MethodName: "DeleteSRPolicy", + Handler: _PCEService_DeleteSRPolicy_Handler, + }, + { + MethodName: "GetSessionList", + Handler: _PCEService_GetSessionList_Handler, + }, + { + MethodName: "GetSRPolicyList", + Handler: _PCEService_GetSRPolicyList_Handler, + }, + { + MethodName: "GetTED", + Handler: _PCEService_GetTED_Handler, + }, + { + MethodName: "DeleteSession", + Handler: _PCEService_DeleteSession_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "pola.proto", +} diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 00000000..8808a922 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,2 @@ +version: v1 +name: github.com/nttcom/pola diff --git a/build/package/README.md b/build/package/README.md index 5ea7c29a..958a1fce 100644 --- a/build/package/README.md +++ b/build/package/README.md @@ -25,7 +25,6 @@ docker run -itd --network host \ /bin/bash -c "source ~/.bashrc;polad" ``` - ## Use bridge network mode ```bash @@ -49,7 +48,9 @@ docker pull ghcr.io/nttcom/pola:latest # Container up and detach CURRENTDIR=`pwd` docker run -itd --network pcep_net --ip \ - -v $CURRENTDIR/$MOUNTDIR:/$MOUNTDIR -v $LOGDIR:$LOGDIR -w /$MOUNTDIR ghcr.io/nttcom/pola:latest \ + -v $CURRENTDIR/$MOUNTDIR:/$MOUNTDIR \ + -v $LOGDIR:$LOGDIR \ + -w /$MOUNTDIR ghcr.io/nttcom/pola:latest \ /bin/bash -c "source ~/.bashrc;polad" # Connect the container's PCC to the network diff --git a/cmd/pola/README.md b/cmd/pola/README.md index 5db54f4b..ad95d62e 100644 --- a/cmd/pola/README.md +++ b/cmd/pola/README.md @@ -5,33 +5,35 @@ ### From Go Package ```bash -$ go install github.com/nttcom/pola/cmd/pola@latest +go install github.com/nttcom/pola/cmd/pola@latest ``` ### From Source -**Getting the Source** +#### Getting the Source ```bash -$ git clone https://github.com/nttcom/pola.git +git clone https://github.com/nttcom/pola.git ``` -**Build & install** +#### Build & install ```bash -$ cd pola -$ go install ./cmd/pola +cd pola +go install ./cmd/pola # or, install with daemon -$ go install ./... +go install ./... ``` ## Command Reference ### pola session \[-j\] + Displays the peer addresses of the active session. JSON formatted response + ```json [ { @@ -59,9 +61,11 @@ JSON formatted response ``` ### pola session del *Address* \[-j\] + Deletes the specified session. JSON formatted response + ```json { "status": "success" @@ -69,102 +73,107 @@ JSON formatted response ``` ### pola sr-policy list \[-j\] + Displays the lsp list managed by polad. JSON formatted response + ```json { - "lsps": [ - { - "color": 999, - "dstAddr": "192.0.2.1", - "segmentList": [ - 16003, - 16001 - ], - "peerAddr": "192.0.2.2", - "policyName": "sample_policy1", - "preference": 100, - "srcAddr": "192.0.2.2" - }, - { - "color": 888 - "dstAddr": "192.0.2.2", - "segmentList": [ - 16003, - 16002 - ], - "peerAddr": "192.0.2.1", - "policyName": "sample_policy2", - "preference": 100, - "srcAddr": "192.0.2.1" - } - ] + "lsps": [ + { + "color": 999, + "dstAddr": "192.0.2.1", + "segmentList": [ + 16003, + 16001 + ], + "peerAddr": "192.0.2.2", + "policyName": "sample_policy1", + "preference": 100, + "srcAddr": "192.0.2.2" + }, + { + "color": 888, + "dstAddr": "192.0.2.2", + "segmentList": [ + 16003, + 16002 + ], + "peerAddr": "192.0.2.1", + "policyName": "sample_policy2", + "preference": 100, + "srcAddr": "192.0.2.1" + } + ] } ``` ※ want to change to this format later. + ```json -{ - "peers": [ + "peers": [ + { + "peerAddr": "192.0.2.1", + "lsps": [ { - "peerAddr": "192.0.2.1", - "lsps": [ - { - "policyName": "sample_policy1", - "srcAddr": "192.0.2.1", - "dstAddr": "192.0.2.2", - "segmentList": [ - 16003, - 16002 - ] - }, - { - "policyName": "sample_policy2", - "srcAddr": "192.0.2.1", - "dstAddr": "192.0.2.2", - "segmentList": [ - 16003, - 16001, - 16002 - ] - }, - ] + "policyName": "sample_policy1", + "srcAddr": "192.0.2.1", + "dstAddr": "192.0.2.2", + "segmentList": [ + 16003, + 16002 + ] }, { - "peerAddr": "192.0.2.2", - "lsps": [ - { - "policyName": "sample_policy3", - "srcAddr": "192.0.2.2", - "dstAddr": "192.0.2.1", - "segmentList": [ - 16003, - 16001 - ] - }, - { - "policyName": "sample_policy4", - "srcAddr": "192.0.2.2", - "dstAddr": "192.0.2.1", - "segmentList": [ - 16003, - 16002, - 16001 - ] - }, - ] - }, -] + "policyName": "sample_policy2", + "srcAddr": "192.0.2.1", + "dstAddr": "192.0.2.2", + "segmentList": [ + 16003, + 16001, + 16002 + ] + } + ] + }, + { + "peerAddr": "192.0.2.2", + "lsps": [ + { + "policyName": "sample_policy3", + "srcAddr": "192.0.2.2", + "dstAddr": "192.0.2.1", + "segmentList": [ + 16003, + 16001 + ] + }, + { + "policyName": "sample_policy4", + "srcAddr": "192.0.2.2", + "dstAddr": "192.0.2.1", + "segmentList": [ + 16003, + 16002, + 16001 + ] + } + ] + } + ] +} + ``` -### pola sr-policy add -f _filepath_ +### pola sr-policy add -f `filepath` -Create a new SR Policy **using TED** +Create a new SR Policy **using TED** #### Case: Dynamic Path calculate YAML input format + ```yaml asn: 65000 srPolicy: @@ -178,15 +187,17 @@ srPolicy: ``` JSON formatted response + ```json { - "status": "success" + "status": "success" } ``` #### Case: Explicit Path YAML input format + ```yaml asn: 65000 srPolicy: @@ -203,21 +214,24 @@ srPolicy: ``` JSON formatted response + ```json { - "status": "success" + "status": "success" } ``` -### pola sr-policy add -f _filepath_ --no-link-state +### pola sr-policy add -f `filepath` --no-sid-validate Create a new SR Policy **without using TED** -Should write the `localAddress` (and `remoteAddr` if Adj-SID) of each sid for creation of Nai +For each SID, write the `localAddress` (and `remoteAddr` if it's an Adj-SID) +to construct the NAI. See [JSON shema](schemas/polad_config.json) for input details. YAML input format + ```yaml srPolicy: pcepSessionAddr: "2001:0db8::1" @@ -241,177 +255,183 @@ srPolicy: ``` json formatted response + ```json { - "status": "success" + "status": "success" } ``` ### pola ted \[-j\] + Displays the ted managed by polad. JSON formatted response + ```json { - "ted": [ - { - "asn": 65000, - "hostname": "host1", - "isisAreaID": "490000", - "links": [ - { - "adjSid": 17, - "localIP": "10.0.1.1", - "metrics": [ - { - "type": "IGP", - "value": 10 - } - ], - "remoteIP": "10.0.1.2", - "remoteNode": "0000.0aff.0003" - }, - { - "adjSid": 18, - "localIP": "10.0.0.1", - "metrics": [ - { - "type": "IGP", - "value": 10 - } - ], - "remoteIP": "10.0.0.2", - "remoteNode": "0000.0aff.0002" - } - ], - "prefixes": [ - { - "prefix": "10.0.1.0/30" - }, - { - "prefix": "10.0.0.0/30" - }, - { - "prefix": "10.255.0.1/32", - "sidIndex": 1 - } - ], - "routerID": "0000.0aff.0001", - "srgbBegin": 16000, - "srgbEnd": 24000 - }, - { - "asn": 65000, - "hostname": "host2", - "isisAreaID": "490000", - "links": [ - { - "adjSid": 17, - "localIP": "10.0.1.2", - "metrics": [ - { - "type": "IGP", - "value": 10 - } - ], - "remoteIP": "10.0.1.1", - "remoteNode": "0000.0aff.0001" - }, - { - "adjSid": 16, - "localIP": "10.0.2.2", - "metrics": [ - { - "type": "IGP", - "value": 10 - } - ], - "remoteIP": "10.0.2.1", - "remoteNode": "0000.0aff.0002" - } - ], - "prefixes": [ - { - "prefix": "10.255.0.3/32", - "sidIndex": 3 - }, - { - "prefix": "10.0.2.0/30" - }, - { - "prefix": "10.0.1.0/30" - } - ], - "routerID": "0000.0aff.0003", - "srgbBegin": 16000, - "srgbEnd": 24000 - }, - { - "asn": 65000, - "hostname": "host3", - "isisAreaID": "490000", - "links": [ - { - "adjSid": 24001, - "localIP": "10.0.0.2", - "metrics": [ - { - "type": "IGP", - "value": 10 - } - ], - "remoteIP": "10.0.0.1", - "remoteNode": "0000.0aff.0001" - }, - { - "adjSid": 24003, - "localIP": "10.0.2.1", - "metrics": [ - { - "type": "IGP", - "value": 10 - } - ], - "remoteIP": "10.0.2.2", - "remoteNode": "0000.0aff.0201" - } - ], - "prefixes": [ - { - "prefix": "10.0.2.0/30" - }, - { - "prefix": "10.0.0.0/30" - }, - { - "prefix": "10.255.0.2/32", - "sidIndex": 2 - } - ], - "routerID": "0000.0aff.0002", - "srgbBegin": 16000, - "srgbEnd": 24000 - } - ] + "ted": [ + { + "asn": 65000, + "hostname": "host1", + "isisAreaID": "490000", + "links": [ + { + "adjSid": 17, + "localIP": "10.0.1.1", + "metrics": [ + { + "type": "IGP", + "value": 10 + } + ], + "remoteIP": "10.0.1.2", + "remoteNode": "0000.0aff.0003" + }, + { + "adjSid": 18, + "localIP": "10.0.0.1", + "metrics": [ + { + "type": "IGP", + "value": 10 + } + ], + "remoteIP": "10.0.0.2", + "remoteNode": "0000.0aff.0002" + } + ], + "prefixes": [ + { + "prefix": "10.0.1.0/30" + }, + { + "prefix": "10.0.0.0/30" + }, + { + "prefix": "10.255.0.1/32", + "sidIndex": 1 + } + ], + "routerID": "0000.0aff.0001", + "srgbBegin": 16000, + "srgbEnd": 24000 + }, + { + "asn": 65000, + "hostname": "host2", + "isisAreaID": "490000", + "links": [ + { + "adjSid": 17, + "localIP": "10.0.1.2", + "metrics": [ + { + "type": "IGP", + "value": 10 + } + ], + "remoteIP": "10.0.1.1", + "remoteNode": "0000.0aff.0001" + }, + { + "adjSid": 16, + "localIP": "10.0.2.2", + "metrics": [ + { + "type": "IGP", + "value": 10 + } + ], + "remoteIP": "10.0.2.1", + "remoteNode": "0000.0aff.0002" + } + ], + "prefixes": [ + { + "prefix": "10.255.0.3/32", + "sidIndex": 3 + }, + { + "prefix": "10.0.2.0/30" + }, + { + "prefix": "10.0.1.0/30" + } + ], + "routerID": "0000.0aff.0003", + "srgbBegin": 16000, + "srgbEnd": 24000 + }, + { + "asn": 65000, + "hostname": "host3", + "isisAreaID": "490000", + "links": [ + { + "adjSid": 24001, + "localIP": "10.0.0.2", + "metrics": [ + { + "type": "IGP", + "value": 10 + } + ], + "remoteIP": "10.0.0.1", + "remoteNode": "0000.0aff.0001" + }, + { + "adjSid": 24003, + "localIP": "10.0.2.1", + "metrics": [ + { + "type": "IGP", + "value": 10 + } + ], + "remoteIP": "10.0.2.2", + "remoteNode": "0000.0aff.0201" + } + ], + "prefixes": [ + { + "prefix": "10.0.2.0/30" + }, + { + "prefix": "10.0.0.0/30" + }, + { + "prefix": "10.255.0.2/32", + "sidIndex": 2 + } + ], + "routerID": "0000.0aff.0002", + "srgbBegin": 16000, + "srgbEnd": 24000 + } + ] } ``` ## Completion ## Bash + ```bash pola completion bash | sudo tee -a /usr/share/bash-completion/completions/pola >/dev/null source /usr/share/bash-completion/completions/pola ``` ## Zsh -```sh + +```bash pola completion zsh > /usr/local/share/zsh/site-functions/_pola compinit ``` ## Fish -```sh + +```bash pola completion fish > ~/.config/fish/completions/pola.fish fish_update_completions ``` diff --git a/cmd/pola/grpc/grpc_client.go b/cmd/pola/grpc/grpc_client.go index ebd115f9..b695c193 100644 --- a/cmd/pola/grpc/grpc_client.go +++ b/cmd/pola/grpc/grpc_client.go @@ -11,8 +11,7 @@ import ( "net/netip" "time" - "github.com/golang/protobuf/ptypes/empty" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" "github.com/nttcom/pola/internal/pkg/table" ) @@ -27,11 +26,11 @@ type Session struct { IsSynced bool } -func GetSessions(client pb.PceServiceClient) ([]Session, error) { +func GetSessions(client pb.PCEServiceClient) ([]Session, error) { ctx, cancel := withTimeout() defer cancel() - ret, err := client.GetSessionList(ctx, &empty.Empty{}) + ret, err := client.GetSessionList(ctx, &pb.GetSessionListRequest{}) if err != nil { return nil, err } @@ -52,28 +51,29 @@ func GetSessions(client pb.PceServiceClient) ([]Session, error) { return sessions, nil } -func DeleteSession(client pb.PceServiceClient, session *pb.Session) error { +func DeleteSession(client pb.PCEServiceClient, req *pb.DeleteSessionRequest) error { ctx, cancel := withTimeout() defer cancel() - _, err := client.DeleteSession(ctx, session) + + _, err := client.DeleteSession(ctx, req) if err != nil { return err } return nil } -func GetSRPolicyList(client pb.PceServiceClient) (map[netip.Addr][]table.SRPolicy, error) { +func GetSRPolicyList(client pb.PCEServiceClient) (map[netip.Addr][]table.SRPolicy, error) { ctx, cancel := withTimeout() defer cancel() - ret, err := client.GetSRPolicyList(ctx, &empty.Empty{}) + ret, err := client.GetSRPolicyList(ctx, &pb.GetSRPolicyListRequest{}) if err != nil { return nil, err } - policies := make(map[netip.Addr][]table.SRPolicy, len(ret.GetSRPolicies())) + policies := make(map[netip.Addr][]table.SRPolicy, len(ret.GetSrPolicies())) - for _, p := range ret.GetSRPolicies() { + for _, p := range ret.GetSrPolicies() { peerAddr, _ := netip.AddrFromSlice(p.PcepSessionAddr) srcAddr, _ := netip.AddrFromSlice(p.SrcAddr) dstAddr, _ := netip.AddrFromSlice(p.DstAddr) @@ -99,35 +99,27 @@ func GetSRPolicyList(client pb.PceServiceClient) (map[netip.Addr][]table.SRPolic return policies, nil } -func CreateSRPolicy(client pb.PceServiceClient, input *pb.CreateSRPolicyInput) error { - ctx, cancel := withTimeout() - defer cancel() - - _, err := client.CreateSRPolicy(ctx, input) - return err -} - -func CreateSRPolicyWithoutLinkState(client pb.PceServiceClient, input *pb.CreateSRPolicyInput) error { +func CreateSRPolicy(client pb.PCEServiceClient, req *pb.CreateSRPolicyRequest) error { ctx, cancel := withTimeout() defer cancel() - _, err := client.CreateSRPolicyWithoutLinkState(ctx, input) + _, err := client.CreateSRPolicy(ctx, req) return err } -func DeleteSRPolicy(client pb.PceServiceClient, input *pb.DeleteSRPolicyInput) error { +func DeleteSRPolicy(client pb.PCEServiceClient, req *pb.DeleteSRPolicyRequest) error { ctx, cancel := withTimeout() defer cancel() - _, err := client.DeleteSRPolicy(ctx, input) + _, err := client.DeleteSRPolicy(ctx, req) return err } -func GetTed(client pb.PceServiceClient) (*table.LsTed, error) { +func GetTED(client pb.PCEServiceClient) (*table.LsTED, error) { ctx, cancel := withTimeout() defer cancel() - ret, err := client.GetTed(ctx, &empty.Empty{}) + ret, err := client.GetTED(ctx, &pb.GetTEDRequest{}) if err != nil { return nil, err } @@ -136,7 +128,7 @@ func GetTed(client pb.PceServiceClient) (*table.LsTed, error) { return nil, errors.New("ted is disabled") } - ted := &table.LsTed{ + ted := &table.LsTED{ ID: 1, Nodes: make(map[uint32]map[string]*table.LsNode), } @@ -152,46 +144,54 @@ func GetTed(client pb.PceServiceClient) (*table.LsTed, error) { return ted, nil } -// initializeLsNodes initializes LsNodes in the LsTed table using the given array of nodes -func initializeLsNodes(ted *table.LsTed, nodes []*pb.LsNode) { +// initializeLsNodes initializes LsNodes in the LsTED table using the given array of nodes +func initializeLsNodes(ted *table.LsTED, nodes []*pb.LsNode) { for _, node := range nodes { - lsNode := table.NewLsNode(node.GetAsn(), node.GetRouterID()) + lsNode := table.NewLsNode(node.GetAsn(), node.GetRouterId()) lsNode.Hostname = node.GetHostname() - lsNode.IsisAreaID = node.GetIsisAreaID() + lsNode.IsisAreaID = node.GetIsisAreaId() lsNode.SrgbBegin = node.GetSrgbBegin() lsNode.SrgbEnd = node.GetSrgbEnd() - if _, ok := ted.Nodes[lsNode.Asn]; !ok { - ted.Nodes[lsNode.Asn] = map[string]*table.LsNode{} + if _, ok := ted.Nodes[lsNode.ASN]; !ok { + ted.Nodes[lsNode.ASN] = map[string]*table.LsNode{} } - ted.Nodes[lsNode.Asn][lsNode.RouterID] = lsNode + ted.Nodes[lsNode.ASN][lsNode.RouterID] = lsNode } } -func addLsNode(ted *table.LsTed, node *pb.LsNode) error { +func addLsNode(ted *table.LsTED, node *pb.LsNode) error { for _, link := range node.GetLsLinks() { - localNode := ted.Nodes[link.LocalAsn][link.LocalRouterID] - remoteNode := ted.Nodes[link.RemoteAsn][link.RemoteRouterID] + localNode := ted.Nodes[link.LocalAsn][link.LocalRouterId] + remoteNode := ted.Nodes[link.RemoteAsn][link.RemoteRouterId] lsLink, err := createLsLink(localNode, remoteNode, link) if err != nil { return err } - ted.Nodes[node.GetAsn()][node.GetRouterID()].Links = append(ted.Nodes[node.GetAsn()][node.GetRouterID()].Links, lsLink) + ted.Nodes[node.GetAsn()][node.GetRouterId()].Links = append(ted.Nodes[node.GetAsn()][node.GetRouterId()].Links, lsLink) } for _, prefix := range node.LsPrefixes { - lsPrefix, err := createLsPrefix(ted.Nodes[node.GetAsn()][node.GetRouterID()], prefix) + lsPrefix, err := createLsPrefix(ted.Nodes[node.GetAsn()][node.GetRouterId()], prefix) if err != nil { return err } - ted.Nodes[node.GetAsn()][node.GetRouterID()].Prefixes = append(ted.Nodes[node.GetAsn()][node.GetRouterID()].Prefixes, lsPrefix) + ted.Nodes[node.GetAsn()][node.GetRouterId()].Prefixes = append(ted.Nodes[node.GetAsn()][node.GetRouterId()].Prefixes, lsPrefix) + } + + for _, srv6SID := range node.LsSrv6Sids { + lsSrv6SID, err := createSrv6SID(ted.Nodes[node.GetAsn()][node.GetRouterId()], srv6SID) + if err != nil { + return err + } + ted.Nodes[node.GetAsn()][node.GetRouterId()].SRv6SIDs = append(ted.Nodes[node.GetAsn()][node.GetRouterId()].SRv6SIDs, lsSrv6SID) } return nil } -func createLsPrefix(lsNode *table.LsNode, prefix *pb.LsPrefix) (*table.LsPrefixV4, error) { - lsPrefix := table.NewLsPrefixV4(lsNode) +func createLsPrefix(lsNode *table.LsNode, prefix *pb.LsPrefix) (*table.LsPrefix, error) { + lsPrefix := table.NewLsPrefix(lsNode) var err error lsPrefix.Prefix, err = netip.ParsePrefix(prefix.GetPrefix()) if err != nil { @@ -209,11 +209,11 @@ func createLsLink(localNode, remoteNode *table.LsNode, link *pb.LsLink) (*table. AdjSid: link.GetAdjSid(), } var err error - lsLink.LocalIP, err = netip.ParseAddr(link.GetLocalIP()) + err = lsLink.LocalIP.UnmarshalText([]byte(link.GetLocalIp())) if err != nil { return nil, err } - lsLink.RemoteIP, err = netip.ParseAddr(link.GetRemoteIP()) + err = lsLink.RemoteIP.UnmarshalText([]byte(link.GetRemoteIp())) if err != nil { return nil, err } @@ -224,20 +224,68 @@ func createLsLink(localNode, remoteNode *table.LsNode, link *pb.LsLink) (*table. } lsLink.Metrics = append(lsLink.Metrics, metric) } + if link.GetSrv6EndXSid() != nil { + srv6EndXSID, err := createSrv6EndXSID(link.GetSrv6EndXSid()) + if err != nil { + return nil, err + } + lsLink.Srv6EndXSID = srv6EndXSID + } return lsLink, nil } func createMetric(metricInfo *pb.Metric) (*table.Metric, error) { switch metricInfo.GetType() { - case pb.MetricType_IGP: - return table.NewMetric(table.IGP_METRIC, metricInfo.GetValue()), nil - case pb.MetricType_TE: - return table.NewMetric(table.TE_METRIC, metricInfo.GetValue()), nil - case pb.MetricType_DELAY: - return table.NewMetric(table.DELAY_METRIC, metricInfo.GetValue()), nil - case pb.MetricType_HOPCOUNT: - return table.NewMetric(table.HOPCOUNT_METRIC, metricInfo.GetValue()), nil + case pb.MetricType_METRIC_TYPE_IGP: + return table.NewMetric(table.IGPMetric, metricInfo.GetValue()), nil + case pb.MetricType_METRIC_TYPE_TE: + return table.NewMetric(table.TEMetric, metricInfo.GetValue()), nil + case pb.MetricType_METRIC_TYPE_DELAY: + return table.NewMetric(table.DelayMetric, metricInfo.GetValue()), nil + case pb.MetricType_METRIC_TYPE_HOPCOUNT: + return table.NewMetric(table.HopcountMetric, metricInfo.GetValue()), nil default: return nil, errors.New("unknown metric type") } } + +func createSrv6EndXSID(srv6EndXSID *pb.Srv6EndXSID) (*table.Srv6EndXSID, error) { + lsSrv6EndXSID := &table.Srv6EndXSID{ + EndpointBehavior: uint16(srv6EndXSID.EndpointBehavior), + Sids: []string{}, + Srv6SIDStructure: table.SIDStructure{ + LocalBlock: uint8(srv6EndXSID.GetSidStructure().GetLocalBlock()), + LocalNode: uint8(srv6EndXSID.GetSidStructure().GetLocalNode()), + LocalFunc: uint8(srv6EndXSID.GetSidStructure().GetLocalFunc()), + LocalArg: uint8(srv6EndXSID.GetSidStructure().GetLocalArg()), + }, + } + + for _, sid := range srv6EndXSID.GetSids() { + lsSrv6EndXSID.Sids = append(lsSrv6EndXSID.Sids, sid.GetSid()) + } + + return lsSrv6EndXSID, nil +} + +func createSrv6SID(lsNode *table.LsNode, srv6SID *pb.LsSrv6SID) (*table.LsSrv6SID, error) { + lsSrv6SID := table.NewLsSrv6SID(lsNode) + + for _, sid := range srv6SID.GetSids() { + lsSrv6SID.Sids = append(lsSrv6SID.Sids, sid.GetSid()) + } + for _, topoID := range srv6SID.GetMultiTopoIds() { + lsSrv6SID.MultiTopoIDs = append(lsSrv6SID.MultiTopoIDs, topoID.GetMultiTopoId()) + } + + lsSrv6SID.EndpointBehavior.Behavior = uint16(srv6SID.GetEndpointBehavior().GetBehavior()) + lsSrv6SID.EndpointBehavior.Flags = uint8(srv6SID.GetEndpointBehavior().GetFlags()) + lsSrv6SID.EndpointBehavior.Algorithm = uint8(srv6SID.GetEndpointBehavior().GetAlgorithm()) + + lsSrv6SID.SIDStructure.LocalBlock = uint8(srv6SID.GetSidStructure().GetLocalBlock()) + lsSrv6SID.SIDStructure.LocalNode = uint8(srv6SID.GetSidStructure().GetLocalNode()) + lsSrv6SID.SIDStructure.LocalFunc = uint8(srv6SID.GetSidStructure().GetLocalFunc()) + lsSrv6SID.SIDStructure.LocalArg = uint8(srv6SID.GetSidStructure().GetLocalArg()) + + return lsSrv6SID, nil +} diff --git a/cmd/pola/root.go b/cmd/pola/root.go index 27d97149..12fb57cb 100644 --- a/cmd/pola/root.go +++ b/cmd/pola/root.go @@ -9,14 +9,14 @@ import ( "fmt" "net" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" "github.com/spf13/cobra" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) var ( - client pb.PceServiceClient + client pb.PCEServiceClient jsonFmt bool ) @@ -28,7 +28,7 @@ func newRootCmd() *cobra.Command { rootCmd.PersistentFlags().String("host", "127.0.0.1", "polad connection address") rootCmd.PersistentFlags().StringP("port", "p", "50051", "polad connection port") - rootCmd.AddCommand(newSessionCmd(), newSRPolicyCmd(), newTedCmd()) + rootCmd.AddCommand(newSessionCmd(), newSRPolicyCmd(), newTEDCmd()) rootCmd.PersistentPreRunE = persistentPreRunE rootCmd.Run = runRootCmd @@ -44,7 +44,7 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to dial polad connection: %v", err) } - client = pb.NewPceServiceClient(conn) + client = pb.NewPCEServiceClient(conn) return nil } diff --git a/cmd/pola/session_del.go b/cmd/pola/session_del.go index 357a03ab..21b32c14 100644 --- a/cmd/pola/session_del.go +++ b/cmd/pola/session_del.go @@ -9,7 +9,7 @@ import ( "fmt" "net/netip" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" "github.com/nttcom/pola/cmd/pola/grpc" "github.com/spf13/cobra" ) @@ -35,10 +35,10 @@ func newSessionDelCmd() *cobra.Command { } func delSession(session netip.Addr, jsonFlag bool) error { - ss := &pb.Session{ + request := &pb.DeleteSessionRequest{ Addr: session.AsSlice(), } - err := grpc.DeleteSession(client, ss) + err := grpc.DeleteSession(client, request) if err != nil { return err } diff --git a/cmd/pola/sr_policy_add.go b/cmd/pola/sr_policy_add.go index 5a142b2d..51063397 100644 --- a/cmd/pola/sr_policy_add.go +++ b/cmd/pola/sr_policy_add.go @@ -14,7 +14,7 @@ import ( "github.com/spf13/cobra" yaml "gopkg.in/yaml.v2" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" "github.com/nttcom/pola/cmd/pola/grpc" ) @@ -22,9 +22,9 @@ func newSRPolicyAddCmd() *cobra.Command { srPolicyAddCmd := &cobra.Command{ Use: "add", RunE: func(cmd *cobra.Command, args []string) error { - noLinkStateFlag, err := cmd.Flags().GetBool("no-link-state") + noSIDValidateFlag, err := cmd.Flags().GetBool("no-sid-validate") if err != nil { - return fmt.Errorf("failed to retrieve 'no-link-state' flag: %v", err) + return fmt.Errorf("failed to retrieve 'no-sid-validate' flag: %v", err) } filepath, err := cmd.Flags().GetString("file") @@ -50,30 +50,28 @@ func newSRPolicyAddCmd() *cobra.Command { return fmt.Errorf("YAML syntax error in file \"%s\": %v", filepath, err) } - if err := addSRPolicy(inputData, jsonFmt, noLinkStateFlag); err != nil { + if err := addSRPolicy(inputData, jsonFmt, noSIDValidateFlag); err != nil { return fmt.Errorf("failed to add SR policy: %v", err) } return nil }, } - srPolicyAddCmd.Flags().BoolP("no-link-state", "l", false, "add SR Policy without Link State") + srPolicyAddCmd.Flags().BoolP("no-sid-validate", "s", false, "disable SR policy SID validation") srPolicyAddCmd.Flags().StringP("file", "f", "", "[mandatory] path to YAML formatted LSP information file") return srPolicyAddCmd } -// Unify with table.Segment type Segment struct { - Sid string `yaml:"sid"` + SID string `yaml:"sid"` LocalAddr string `yaml:"localAddr"` RemoteAddr string `yaml:"remoteAddr"` - SidStructure string `yaml:"sidStructure"` + SIDStructure string `yaml:"sidStructure"` } -// Unify with table.SRPolciy type SRPolicy struct { - PcepSessionAddr netip.Addr `yaml:"pcepSessionAddr"` + PCEPSessionAddr netip.Addr `yaml:"pcepSessionAddr"` SrcAddr netip.Addr `yaml:"srcAddr"` DstAddr netip.Addr `yaml:"dstAddr"` SrcRouterID string `yaml:"srcRouterID"` @@ -87,16 +85,16 @@ type SRPolicy struct { type InputFormat struct { SRPolicy SRPolicy `yaml:"srPolicy"` - Asn uint32 `yaml:"asn"` + ASN uint32 `yaml:"asn"` } -func addSRPolicy(input InputFormat, jsonFlag bool, noLinkStateFlag bool) error { - if noLinkStateFlag { - if err := addSRPolicyNoLinkState(input); err != nil { +func addSRPolicy(input InputFormat, jsonFlag bool, explicitPathFlag bool) error { + if explicitPathFlag { + if err := addSRPolicyWithoutSIDValidation(input); err != nil { return err } } else { - if err := addSRPolicyLinkState(input); err != nil { + if err := addSRPolicyWithSIDValidation(input); err != nil { return err } } @@ -109,8 +107,8 @@ func addSRPolicy(input InputFormat, jsonFlag bool, noLinkStateFlag bool) error { return nil } -func addSRPolicyNoLinkState(input InputFormat) error { - if !input.SRPolicy.PcepSessionAddr.IsValid() || input.SRPolicy.Color == 0 || !input.SRPolicy.SrcAddr.IsValid() || !input.SRPolicy.DstAddr.IsValid() || len(input.SRPolicy.SegmentList) == 0 { +func addSRPolicyWithoutSIDValidation(input InputFormat) error { + if !input.SRPolicy.PCEPSessionAddr.IsValid() || input.SRPolicy.Color == 0 || !input.SRPolicy.SrcAddr.IsValid() || !input.SRPolicy.DstAddr.IsValid() || len(input.SRPolicy.SegmentList) == 0 { sampleInput := "srPolicy:\n" + " pcepSessionAddr: 192.0.2.1\n" + " srcAddr: 192.0.2.1\n" + @@ -130,15 +128,15 @@ func addSRPolicyNoLinkState(input InputFormat) error { segmentList := []*pb.Segment{} for _, segment := range input.SRPolicy.SegmentList { pbSeg := &pb.Segment{ - Sid: segment.Sid, + Sid: segment.SID, LocalAddr: segment.LocalAddr, RemoteAddr: segment.RemoteAddr, - SidStructure: segment.SidStructure, + SidStructure: segment.SIDStructure, } segmentList = append(segmentList, pbSeg) } srPolicy := &pb.SRPolicy{ - PcepSessionAddr: input.SRPolicy.PcepSessionAddr.AsSlice(), + PcepSessionAddr: input.SRPolicy.PCEPSessionAddr.AsSlice(), SrcAddr: input.SRPolicy.SrcAddr.AsSlice(), DstAddr: input.SRPolicy.DstAddr.AsSlice(), SegmentList: segmentList, @@ -146,17 +144,17 @@ func addSRPolicyNoLinkState(input InputFormat) error { PolicyName: input.SRPolicy.Name, } - inputData := &pb.CreateSRPolicyInput{ - SRPolicy: srPolicy, + request := &pb.CreateSRPolicyRequest{ + SrPolicy: srPolicy, } - if err := grpc.CreateSRPolicyWithoutLinkState(client, inputData); err != nil { + if err := grpc.CreateSRPolicy(client, request); err != nil { return err } return nil } -func addSRPolicyLinkState(input InputFormat) error { +func addSRPolicyWithSIDValidation(input InputFormat) error { sampleInputDynamic := "#case: dynamic path\n" + "asn: 65000\n" + "srPolicy:\n" + @@ -179,12 +177,12 @@ func addSRPolicyLinkState(input InputFormat) error { " segmentList:\n" + " - sid: 16003\n" + " - sid: 16002\n" - if input.Asn == 0 || !input.SRPolicy.PcepSessionAddr.IsValid() || input.SRPolicy.Color == 0 || input.SRPolicy.SrcRouterID == "" || input.SRPolicy.DstRouterID == "" { + if input.ASN == 0 || !input.SRPolicy.PCEPSessionAddr.IsValid() || input.SRPolicy.Color == 0 || input.SRPolicy.SrcRouterID == "" || input.SRPolicy.DstRouterID == "" { errMsg := "invalid input\n" + "input example is below\n\n" + sampleInputDynamic + sampleInputExplicit + - "or, if create SR Policy without TED, then use `--no-link-state` flag\n" + "or, if create SR Policy without TED, then use `--no-sid-validate` flag\n" return errors.New(errMsg) } @@ -200,9 +198,9 @@ func addSRPolicyLinkState(input InputFormat) error { return errors.New(errMsg) } - srPolicyType = pb.SRPolicyType_EXPLICIT + srPolicyType = pb.SRPolicyType_SR_POLICY_TYPE_EXPLICIT for _, segment := range input.SRPolicy.SegmentList { - segmentList = append(segmentList, &pb.Segment{Sid: segment.Sid}) + segmentList = append(segmentList, &pb.Segment{Sid: segment.SID}) } case "dynamic": if input.SRPolicy.Metric == "" { @@ -211,14 +209,14 @@ func addSRPolicyLinkState(input InputFormat) error { sampleInputDynamic return errors.New(errMsg) } - srPolicyType = pb.SRPolicyType_DYNAMIC + srPolicyType = pb.SRPolicyType_SR_POLICY_TYPE_DYNAMIC switch input.SRPolicy.Metric { case "igp": - metric = pb.MetricType_IGP + metric = pb.MetricType_METRIC_TYPE_IGP case "delay": - metric = pb.MetricType_DELAY + metric = pb.MetricType_METRIC_TYPE_DELAY case "te": - metric = pb.MetricType_TE + metric = pb.MetricType_METRIC_TYPE_TE default: return fmt.Errorf("invalid input `metric`") } @@ -228,18 +226,18 @@ func addSRPolicyLinkState(input InputFormat) error { } srPolicy := &pb.SRPolicy{ - PcepSessionAddr: input.SRPolicy.PcepSessionAddr.AsSlice(), - SrcRouterID: input.SRPolicy.SrcRouterID, - DstRouterID: input.SRPolicy.DstRouterID, + PcepSessionAddr: input.SRPolicy.PCEPSessionAddr.AsSlice(), + SrcRouterId: input.SRPolicy.SrcRouterID, + DstRouterId: input.SRPolicy.DstRouterID, Color: input.SRPolicy.Color, PolicyName: input.SRPolicy.Name, Type: srPolicyType, SegmentList: segmentList, Metric: metric, } - inputData := &pb.CreateSRPolicyInput{ - SRPolicy: srPolicy, - Asn: input.Asn, + inputData := &pb.CreateSRPolicyRequest{ + SrPolicy: srPolicy, + Asn: input.ASN, } if err := grpc.CreateSRPolicy(client, inputData); err != nil { return fmt.Errorf("gRPC Server Error: %s", err.Error()) diff --git a/cmd/pola/sr_policy_delete.go b/cmd/pola/sr_policy_delete.go index a0389cf2..e5d86b2d 100644 --- a/cmd/pola/sr_policy_delete.go +++ b/cmd/pola/sr_policy_delete.go @@ -10,7 +10,7 @@ import ( "fmt" "os" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" "github.com/spf13/cobra" yaml "gopkg.in/yaml.v2" @@ -57,7 +57,7 @@ func newSRPolicyDeleteCmd() *cobra.Command { } func deleteSRPolicy(input InputFormat, jsonFlag bool) error { - if !input.SRPolicy.PcepSessionAddr.IsValid() || input.SRPolicy.Color == 0 || !input.SRPolicy.DstAddr.IsValid() || input.SRPolicy.Name == "" { + if !input.SRPolicy.PCEPSessionAddr.IsValid() || input.SRPolicy.Color == 0 || !input.SRPolicy.DstAddr.IsValid() || input.SRPolicy.Name == "" { sampleInput := "srPolicy:\n" + " pcepSessionAddr: 192.0.2.1\n" + " dstAddr: 192.0.2.2\n" + @@ -70,14 +70,14 @@ func deleteSRPolicy(input InputFormat, jsonFlag bool) error { } srPolicy := &pb.SRPolicy{ - PcepSessionAddr: input.SRPolicy.PcepSessionAddr.AsSlice(), + PcepSessionAddr: input.SRPolicy.PCEPSessionAddr.AsSlice(), DstAddr: input.SRPolicy.DstAddr.AsSlice(), Color: input.SRPolicy.Color, PolicyName: input.SRPolicy.Name, } - inputData := &pb.DeleteSRPolicyInput{ - SRPolicy: srPolicy, - Asn: input.Asn, + inputData := &pb.DeleteSRPolicyRequest{ + SrPolicy: srPolicy, + Asn: input.ASN, } if err := grpc.DeleteSRPolicy(client, inputData); err != nil { return fmt.Errorf("gRPC Server Error: %s", err.Error()) diff --git a/cmd/pola/ted.go b/cmd/pola/ted.go index d8a4c4cc..b254a24d 100644 --- a/cmd/pola/ted.go +++ b/cmd/pola/ted.go @@ -13,11 +13,11 @@ import ( "github.com/spf13/cobra" ) -func newTedCmd() *cobra.Command { +func newTEDCmd() *cobra.Command { return &cobra.Command{ Use: "ted", RunE: func(cmd *cobra.Command, args []string) error { - if err := print(jsonFmt); err != nil { + if err := printTED(jsonFmt); err != nil { return err } return nil @@ -25,8 +25,8 @@ func newTedCmd() *cobra.Command { } } -func print(jsonFlag bool) error { - ted, err := grpc.GetTed(client) +func printTED(jsonFlag bool) error { + ted, err := grpc.GetTED(client) if err != nil { return err } @@ -38,59 +38,83 @@ func print(jsonFlag bool) error { if jsonFlag { // Output JSON format - nodes := []map[string]interface{}{} + nodes := []map[string]any{} for _, as := range ted.Nodes { for _, node := range as { - tmpNode := map[string]interface{}{ // TODO: Fix format according to readme - "asn": node.Asn, + nodeMap := map[string]any{ // TODO: Fix format according to readme + "asn": node.ASN, "routerID": node.RouterID, "isisAreaID": node.IsisAreaID, "hostname": node.Hostname, "srgbBegin": node.SrgbBegin, "srgbEnd": node.SrgbEnd, - "prefixes": []map[string]interface{}{}, - "links": []map[string]interface{}{}, + "prefixes": []map[string]any{}, + "links": []map[string]any{}, } - links := []map[string]interface{}{} + links := []map[string]any{} for _, link := range node.Links { - metrics := []map[string]interface{}{} + metrics := []map[string]any{} for _, metric := range link.Metrics { - tmpMetric := map[string]interface{}{ + metricMap := map[string]any{ "type": metric.Type.String(), "value": metric.Value, } - metrics = append(metrics, tmpMetric) + metrics = append(metrics, metricMap) } - tmpLink := map[string]interface{}{ - "localIP": link.LocalIP.String(), - "remoteIP": link.RemoteIP.String(), + var localIP string + var remoteIP string + if link.LocalIP.IsValid() { + localIP = link.LocalIP.String() + } else { + localIP = "None" + } + if link.RemoteIP.IsValid() { + remoteIP = link.RemoteIP.String() + } else { + remoteIP = "None" + } + + linkMap := map[string]any{ + "localIP": localIP, + "remoteIP": remoteIP, "remoteNode": link.RemoteNode.RouterID, "metrics": metrics, "adjSid": link.AdjSid, } - links = append(links, tmpLink) + links = append(links, linkMap) } - tmpNode["links"] = links + nodeMap["links"] = links - prefixes := []map[string]interface{}{} + prefixes := []map[string]any{} for _, prefix := range node.Prefixes { - tmpPrefix := map[string]interface{}{ + prefixMap := map[string]any{ "prefix": prefix.Prefix.String(), } if prefix.SidIndex != 0 { - tmpPrefix["sidIndex"] = prefix.SidIndex + prefixMap["sidIndex"] = prefix.SidIndex + } + prefixes = append(prefixes, prefixMap) + } + nodeMap["prefixes"] = prefixes + + srv6SIDs := []map[string]any{} + for _, srv6SID := range node.SRv6SIDs { + srv6SIDMap := map[string]any{ + "sids": srv6SID.Sids, + "endpointBehavior": srv6SID.EndpointBehavior, + "multiTopoIDs": srv6SID.MultiTopoIDs, } - prefixes = append(prefixes, tmpPrefix) + srv6SIDs = append(srv6SIDs, srv6SIDMap) } - tmpNode["prefixes"] = prefixes + nodeMap["srv6SIDs"] = srv6SIDs - nodes = append(nodes, tmpNode) + nodes = append(nodes, nodeMap) } } - outputMap := map[string]interface{}{ + outputMap := map[string]any{ "ted": nodes, } diff --git a/cmd/polad/main.go b/cmd/polad/main.go index 96d4f162..537d86ba 100644 --- a/cmd/polad/main.go +++ b/cmd/polad/main.go @@ -22,7 +22,7 @@ import ( "github.com/nttcom/pola/pkg/server" ) -const TED_UPDATE_INTERVAL = 1 // (min) +const TEDUpdateInterval = 1 // (min) type flags struct { configFile string @@ -72,11 +72,11 @@ func main() { }() // Prepare TED update tools - var tedElemsChan chan []table.TedElem - if c.Global.Ted.Enable { - switch c.Global.Ted.Source { + var tedElemsChan chan []table.TEDElem + if c.Global.TED.Enable { + switch c.Global.TED.Source { case "gobgp": - tedElemsChan = startGobgpUpdate(&c, logger) + tedElemsChan = startGoBGPUpdate(&c, logger) if tedElemsChan == nil { logger.Panic("GoBGP update channel is nil") log.Panic("GoBGP update channel is nil") @@ -88,37 +88,37 @@ func main() { } // Start PCE server - o := &server.PceOptions{ - PcepAddr: c.Global.Pcep.Address, - PcepPort: c.Global.Pcep.Port, - GrpcAddr: c.Global.GrpcServer.Address, - GrpcPort: c.Global.GrpcServer.Port, - TedEnable: c.Global.Ted.Enable, + o := &server.PCEOptions{ + PCEPAddr: c.Global.PCEP.Address, + PCEPPort: c.Global.PCEP.Port, + GRPCAddr: c.Global.GRPCServer.Address, + GRPCPort: c.Global.GRPCServer.Port, + TEDEnable: c.Global.TED.Enable, USidMode: c.Global.USidMode, } - if serverErr := server.NewPce(o, logger, tedElemsChan); serverErr.Error != nil { + if serverErr := server.NewPCE(o, logger, tedElemsChan); serverErr.Error != nil { logger.Panic("Failed to start new server", zap.String("server", serverErr.Server), zap.Error(serverErr.Error)) log.Panicf("failed to start new server: %v", serverErr.Error) } } -func startGobgpUpdate(c *config.Config, logger *zap.Logger) chan []table.TedElem { - if c.Global.Ted == nil { +func startGoBGPUpdate(c *config.Config, logger *zap.Logger) chan []table.TEDElem { + if c.Global.TED == nil { logger.Error("TED does not exist") return nil } - tedElemsChan := make(chan []table.TedElem) + tedElemsChan := make(chan []table.TEDElem) go func() { for { - tedElems, err := gobgp.GetBgplsNlris(c.Global.Gobgp.GrpcClient.Address, c.Global.Gobgp.GrpcClient.Port) - logger.Debug("Request TED update", zap.String("source", "GoBGP"), zap.String("session", c.Global.Gobgp.GrpcClient.Address+":"+c.Global.Gobgp.GrpcClient.Port)) + tedElems, err := gobgp.GetBGPlsNLRIs(c.Global.GoBGP.GRPCClient.Address, c.Global.GoBGP.GRPCClient.Port) + logger.Debug("Request TED update", zap.String("source", "GoBGP"), zap.String("session", c.Global.GoBGP.GRPCClient.Address+":"+c.Global.GoBGP.GRPCClient.Port)) if err != nil { logger.Error("Failed session with GoBGP", zap.Error(err)) } else { tedElemsChan <- tedElems } - time.Sleep(TED_UPDATE_INTERVAL * time.Minute) + time.Sleep(TEDUpdateInterval * time.Minute) } }() diff --git a/configs/polad.yaml.sample b/configs/polad.yaml.sample index 66fa3d74..42b13f68 100644 --- a/configs/polad.yaml.sample +++ b/configs/polad.yaml.sample @@ -2,7 +2,7 @@ global: pcep: address: "127.0.0.1" port: 4189 - grpc-server: + grpcServer: address: "127.0.0.1" port: 50052 log: @@ -12,7 +12,7 @@ global: enable: true source: "gobgp" gobgp: - grpc-client: + grpcClient: address: "127.0.0.1" port: 50051 - usid-mode: true + usidMode: true diff --git a/docs/schemas/polad_config.json b/docs/schemas/polad_config.json index a499bb2d..676abb1e 100644 --- a/docs/schemas/polad_config.json +++ b/docs/schemas/polad_config.json @@ -28,7 +28,7 @@ "port" ] }, - "grpc-server": { + "grpcServer": { "type": "object", "properties": { "address": { @@ -89,7 +89,7 @@ "gobgp": { "type": "object", "properties": { - "grpc-client": { + "grpcClient": { "type": "object", "properties": { "address": { @@ -114,17 +114,17 @@ } }, "required": [ - "grpc-client" + "grpcClient" ] }, - "usid-mode": { + "usidMode": { "type": "boolean", "default": false } }, "required": [ "pcep", - "grpc-server", + "grpcServer", "log", "ted" ] diff --git a/docs/sources/getting-started.md b/docs/sources/getting-started.md index 8b691e5e..95c70a9f 100644 --- a/docs/sources/getting-started.md +++ b/docs/sources/getting-started.md @@ -7,18 +7,18 @@ This page explains how to use Pola PCE. ### From Go Package ```bash -$ go install github.com/nttcom/pola/cmd/polad@latest +go install github.com/nttcom/pola/cmd/polad@latest ``` ### From Source -**Getting the Source** +#### Getting the Source ```bash -$ git clone https://github.com/nttcom/pola.git +git clone https://github.com/nttcom/pola.git ``` -**Build & install** +#### Build & install ```bash $ cd pola @@ -46,7 +46,7 @@ global: pcep: address: "2001:0db8::254" port: 4189 - grpc-server: + grpcServer: address: "127.0.0.1" port: 50051 log: @@ -54,7 +54,7 @@ global: name: "polad.log" ted: enable: false - usid-mode: false + usidMode: false ``` ### case: TED enable @@ -72,7 +72,7 @@ global: pcep: address: "192.0.2.254" port: 4189 - grpc-server: + grpcServer: address: "127.0.0.1" port: 50052 log: @@ -82,7 +82,7 @@ global: enable: true source: "gobgp" gobgp: - grpc-client: + grpcClient: address: "127.0.0.1" port: 50051 ``` @@ -116,4 +116,5 @@ $ sudo polad -f polad.yaml 2022-06-05T22:57:59.823Z info PCEP listen {"listenInfo": "192.0.2.254:4189"} ``` -After Polad is running, use [pola cmd](../../cmd/pola/README.md) or the [gRCP client](../../api/grpc/) for daemon operations +After Polad is running, use [pola cmd](../../cmd/pola/README.md) or the +[gRCP client](../../api/grpc/) for daemon operations diff --git a/examples/containerlab/sr-mpls_pcep/README.md b/examples/containerlab/sr-mpls_pcep/README.md index 1e481175..bdb04c1f 100644 --- a/examples/containerlab/sr-mpls_pcep/README.md +++ b/examples/containerlab/sr-mpls_pcep/README.md @@ -1,19 +1,27 @@ # SR-MPLS + PCEP (IOS-XR/Junos/FRRouting) + Example topology powered by [Containerlab](https://containerlab.dev/) -![](./topo.png) +![Topology](./topo.png) + ## Requirements + * container host (Linux) * Cisco XRd image * Juniper vMX image + ## Usage + ### Install Containerlab & XRd/vMX + **[Install Containerlab](https://containerlab.dev/install/)** + ```bash -$ sudo bash -c "$(curl -sL https://get.containerlab.dev)" +sudo bash -c "$(curl -sL https://get.containerlab.dev)" ``` **Install Cisco XRd** Configure sysctl on host + ```bash $ vi /etc/sysctl.conf fs.inotify.max_user_instances=64000 @@ -27,17 +35,23 @@ net.core.wmem_max=67108864 net.ipv4.udp_mem=1124736 10000000 67108864 $ sysctl -p ``` -host-check (see: [link](https://xrdocs.io/virtual-routing/tutorials/2022-08-22-setting-up-host-environment-to-run-xrd/)) + +host-check (see: [Setting up the Host Environment to run XRd](https://xrdocs.io/virtual-routing/tutorials/2022-08-22-setting-up-host-environment-to-run-xrd/)) + ```bash git clone https://github.com/ios-xr/xrd-tools cd xrd-tools/scripts ./host-check --platform xrd-control-plane ``` + Load XRd container image + ```bash docker load -i .tar.gz ``` + Install Juniper vMX on Vrnetlab + ```bash $ sudo apt install make $ git clone https://github.com/hellt/vrnetlab && cd vrnetlab/vmx @@ -51,32 +65,44 @@ vrnetlab/vr-vmx 22.4R1.10 6d2704750cd7 3 minutes ago 10.8GB $ sudo rm -rf vrnetlab $ sudo docker builder prune -a ``` + ### Building a Lab Network + Create bridge + ```bash -$ sudo ip link add switch type bridge -$ sudo ip link set dev switch up +sudo ip link add switch type bridge +sudo ip link set dev switch up ``` + Enable MPLS kernel module -``` + +```bash sudo modprobe mpls_router sudo modprobe mpls_gso sudo modprobe mpls_iptunnel ``` + Start Containerlab network + ```bash -$ git clone https://github.com/nttcom/pola -$ cd pola/examples/containerlab/sr-mpls_pcep -$ sudo containerlab deploy +git clone https://github.com/nttcom/pola +cd pola/examples/containerlab/sr-mpls_pcep +sudo containerlab deploy ``` + Wait for starting vMX after execute `sudo containerlab deploy` (it takes some time). + ```bash $ docker logs clab-sr-mpls_pcep-pe02 -f 2023-02-20 15:03:26,233: launch INFO Startup complete in: 0:09:06.969773 ``` + ### Check PCEP Session + Connect to PCEP container, check PCEP session and SR policy + ```bash $ sudo docker exec -it clab-sr-mpls_pcep-pola-pce bash # polad -f polad.yaml > /dev/null 2>&1 & @@ -87,4 +113,5 @@ sessionAddr(2): 10.0.255.2 # pola sr-policy list no SR Policies ``` + Now the environment for PCEP verification is ready! diff --git a/examples/containerlab/sr-mpls_pcep/polad/polad.yaml b/examples/containerlab/sr-mpls_pcep/polad/polad.yaml index 2c83de01..993e1c17 100644 --- a/examples/containerlab/sr-mpls_pcep/polad/polad.yaml +++ b/examples/containerlab/sr-mpls_pcep/polad/polad.yaml @@ -2,7 +2,7 @@ global: pcep: address: "10.0.255.254" port: 4189 - grpc-server: + grpcServer: address: "127.0.0.1" port: 50051 log: diff --git a/examples/containerlab/srv6_te_l3vpn/README.md b/examples/containerlab/srv6_te_l3vpn/README.md index 7d25f91b..9a91903c 100644 --- a/examples/containerlab/srv6_te_l3vpn/README.md +++ b/examples/containerlab/srv6_te_l3vpn/README.md @@ -2,21 +2,25 @@ Example topology powered by [Containerlab](https://containerlab.dev/) -![](./topo.png) +![Topology](./topo.png) ## Requirements + * container host (Linux) * Juniper vMX image ## Usage ### Install Containerlab & Juniper vMX + [Install Containerlab](https://containerlab.dev/install/) + ```bash -$ sudo bash -c "$(curl -sL https://get.containerlab.dev)" +sudo bash -c "$(curl -sL https://get.containerlab.dev)" ``` Install Juniper vMX on [Vrnetlab](https://containerlab.dev/manual/vrnetlab/) + ```bash $ sudo apt install make $ git clone https://github.com/hellt/vrnetlab && cd vrnetlab/vmx @@ -34,21 +38,25 @@ $ sudo docker builder prune -a ``` ### Building a Lab Network + Create bridge + ```bash -$ sudo ip link add switch type bridge -$ sudo ip link set dev switch up +sudo ip link add switch type bridge +sudo ip link set dev switch up ``` Start Containerlab network + ```bash -$ git clone https://github.com/nttcom/pola -$ cd pola/examples/containerlab/srv6_te_l3vpn +git clone https://github.com/nttcom/pola +cd pola/examples/containerlab/srv6_te_l3vpn -$ sudo containerlab deploy +sudo containerlab deploy ``` Wait for starting vMX after execute `sudo containerlab deploy` (it takes some time). + ```bash $ docker logs clab-srv6_te_l3vpn-pe01 -f @@ -56,7 +64,9 @@ $ docker logs clab-srv6_te_l3vpn-pe01 -f ``` ### Apply SR Policy + Connect to PCEP container, check PCEP session and SR policy + ```bash $ sudo docker exec -it clab-srv6_te_l3vpn-pola-pce bash @@ -71,10 +81,11 @@ no SR Policies ``` Apply and check SR Policy + ```bash -# pola sr-policy add -f pe01-policy1.yaml --no-link-state +# pola sr-policy add -f pe01-policy1.yaml --no-sid-validate success! -# pola sr-policy add -f pe02-policy1.yaml --no-link-state +# pola sr-policy add -f pe02-policy1.yaml --no-sid-validate success! # pola sr-policy list @@ -96,8 +107,10 @@ Session: fd00::2 ``` Enter container pe01 and check SR Policy + * user: admin * pass: admin@123 + ```bash # exit $ ssh clab-srv6_te_l3vpn-pe01 -l admin @@ -151,6 +164,7 @@ fd00:a2::/64 *[BGP/170] 00:32:08, localpref 100, from fd00:ffff::2 Enter container host01 and check SRv6-TE * ping over VPN + ```bash admin@pe01> exit @@ -170,6 +184,7 @@ PING fd00:a2::1(fd00:a2::1) 56 data bytes ``` * Capture on containerlab host + ```bash $ sudo ip netns exec clab-srv6_te_l3vpn-pe01 tcpdump -nni eth1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode @@ -182,7 +197,8 @@ listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes 01:05:34.067531 IP6 fd00:ffff::2 > fd00:ffff:1:0:4:a::: srcrt (len=4, type=4, segleft=0[|srcrt] ``` -Also, you can analyze with Wireshark on your Local PC ([ref: Packet capture & Wireshark](https://containerlab.dev/manual/wireshark/)). +Also, you can analyze with Wireshark on your Local PC +([ref: Packet capture & Wireshark](https://containerlab.dev/manual/wireshark/)). ```bash ssh $clab_host "sudo -S ip netns exec clab-srv6_te_l3vpn-pe01 tcpdump -U -nni eth1 -w -" | wireshark -k -i - diff --git a/examples/containerlab/srv6_te_l3vpn/polad/polad.yaml b/examples/containerlab/srv6_te_l3vpn/polad/polad.yaml index d638913a..bb2b48f4 100644 --- a/examples/containerlab/srv6_te_l3vpn/polad/polad.yaml +++ b/examples/containerlab/srv6_te_l3vpn/polad/polad.yaml @@ -2,7 +2,7 @@ global: pcep: address: "[fd00::ffff]" port: 4189 - grpc-server: + grpcServer: address: "127.0.0.1" port: 50051 log: diff --git a/examples/containerlab/srv6_usid_dynamic-path/README.md b/examples/containerlab/srv6_usid_dynamic-path/README.md new file mode 100644 index 00000000..0365c8f0 --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/README.md @@ -0,0 +1,145 @@ +# SRv6 uSID Dynamic Path + +Example topology powered by [Containerlab](https://containerlab.dev/) + +![Topology](./topo.png) + +## Requirements + +* container host (Linux) +* vJunos image + +## Usage + +### Install Containerlab & vJunos-router + +[Install Containerlab](https://containerlab.dev/install/) + +```bash +sudo bash -c "$(curl -sL https://get.containerlab.dev)" +``` + +Install vJunos on [Vrnetlab](https://containerlab.dev/manual/vrnetlab/) + +### Building a Lab Network + +Create bridge + +```bash +sudo ip link add switch type bridge +sudo ip link set dev switch up +``` + +Copy Pola PCE & GoBGP to bin + +* GoBGP: v4.0.0 or later +* Pola PCE: [commit 7a72c02](https://github.com/nttcom/pola/commit/7a72c02085d72d9b6a0dc1a887745fd9ec25fe60) or later + +Start Containerlab network + +```bash +git clone https://github.com/nttcom/pola +cd pola/examples/containerlab/srv6_usid_dynamic-path + +sudo containerlab deploy +``` + +### Starting Daemons + +```bash +$ sudo docker exec -it clab-dynamic-path-gobgp bash +# gobgpd -f /gobgpd.yml +``` + +```bash +$ sudo docker exec -it clab-dynamic-path-pola bash +# polad -f /polad.yaml +``` + +### Show TED + +```bash +$ sudo docker exec -it clab-dynamic-path-pola bash +# pola -p 50052 ted +``` + +### Apply SR Policy + +Connect to PCEP container, check PCEP session and SR policy + +```bash +$ sudo docker exec -it clab-dynamic-path-pola bash + +# pola session -p 50052 +sessionAddr(0): fd00::2 + +# pola sr-policy list -p 50052 +No SR Policies found. +``` + +Apply and check SR Policy + +```bash +# pola sr-policy add -f /pe02-policy1.yaml -p 50052 +success! + +# pola sr-policy list -p 50052 +Session: fd00::2 + PolicyName: DYNAMIC-POLICY + SrcAddr: fd00:ffff::2 + DstAddr: fd00:ffff::1 + Color: 100 + Preference: 0 + SegmentList: fcbb:bb00:1004:: -> fcbb:bb00:1003:: -> fcbb:bb00:1001:: +``` + +Enter container pe02 and check SR Policy + +* user: admin +* pass: admin@123 + +```text +$ ssh clab-dynamic-path-pe02 -l admin + +admin@pe02> show spring-traffic-engineering lsp brief +To State LSPname +fd00:ffff::1-100 Up DYNAMIC-POLICY + + +Total displayed LSPs: 1 (Up: 1, Down: 0, Initializing: 0) + +admin@pe02> show spring-traffic-engineering lsp name DYNAMIC-POLICY detail +E = Entropy-label Capability + +Name: DYNAMIC-POLICY + Tunnel-source: Path computation element protocol(PCEP) + Tunnel Forward Type: SRV6 + To: fd00:ffff::1-100 + From: fd00:ffff::2 + State: Up + Path Status: NA + Outgoing interface: NA + Delegation compute constraints info: + Actual-Bandwidth from PCUpdate: 0 + Bandwidth-Requested from PCUpdate: 0 + Setup-Priority: 0 + Reservation-Priority: 0 + Auto-translate status: Disabled Auto-translate result: N/A + BFD status: N/A BFD name: N/A + BFD remote-discriminator: N/A + Segment ID : 129 + ERO Valid: true + SR-ERO hop count: 3 + Hop 1 (Strict): + NAI: IPv6 Node ID, Node address: fcbb:bb00:1004:: + SID type: srv6-sid, Value: fcbb:bb00:1004:: + Hop 2 (Strict): + NAI: IPv6 Node ID, Node address: fcbb:bb00:1003:: + SID type: srv6-sid, Value: fcbb:bb00:1003:: + Hop 3 (Strict): + NAI: IPv6 Node ID, Node address: fcbb:bb00:1001:: + SID type: srv6-sid, Value: fcbb:bb00:1001:: + + +Total displayed LSPs: 1 (Up: 1, Down: 0, Initializing: 0) +``` diff --git a/examples/containerlab/srv6_usid_dynamic-path/bin/.gitkeep b/examples/containerlab/srv6_usid_dynamic-path/bin/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/examples/containerlab/srv6_usid_dynamic-path/gobgpd/gobgpd.yml b/examples/containerlab/srv6_usid_dynamic-path/gobgpd/gobgpd.yml new file mode 100644 index 00000000..37a1af5b --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/gobgpd/gobgpd.yml @@ -0,0 +1,11 @@ +global: + config: + as: 65000 + router-id: "10.255.0.255" +neighbors: + - config: + peer-as: 65000 + neighbor-address: "fd00::1" + afi-safis: + - config: + afi-safi-name: ls diff --git a/examples/containerlab/srv6_usid_dynamic-path/polad/polad.yaml b/examples/containerlab/srv6_usid_dynamic-path/polad/polad.yaml new file mode 100644 index 00000000..da35d9bc --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/polad/polad.yaml @@ -0,0 +1,18 @@ +global: + pcep: + address: "fd00::3" + port: 4189 + grpcServer: + address: "127.0.0.1" + port: 50052 + log: + path: "/var/log/pola/" + debug: true + name: "polad.log" + ted: + enable: true + source: "gobgp" + gobgp: + grpcClient: + address: "10.0.0.4" + port: 50051 diff --git a/examples/containerlab/srv6_usid_dynamic-path/sr-policies/pe02-policy1.yaml b/examples/containerlab/srv6_usid_dynamic-path/sr-policies/pe02-policy1.yaml new file mode 100644 index 00000000..2d926641 --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/sr-policies/pe02-policy1.yaml @@ -0,0 +1,9 @@ +asn: 65000 +srPolicy: + pcepSessionAddr: "fd00::2" + srcRouterID: "0000.0001.0002" + dstRouterID: "0000.0001.0001" + name: "DYNAMIC-POLICY" + color: 100 + type: dynamic + metric: igp diff --git a/examples/containerlab/srv6_usid_dynamic-path/startup-configs/p01.cfg b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/p01.cfg new file mode 100644 index 00000000..5d004516 --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/p01.cfg @@ -0,0 +1,106 @@ +hostname p01 +username admin + group root-lr + group cisco-support + secret 10 $6$MTEbC5od1RuC....$xvQt1LVtwS9akjpzHYOZyj6ZMLZwJ5R9PvRCMaqjrR9iqeoPXisq.rXiiJZPoPE6Gi5XL1yjIlzAY4dfWC6Gr1 +! +grpc + vrf MGMT + no-tls + address-family dual +! +vrf MGMT + address-family ipv4 unicast + ! + address-family ipv6 unicast + ! +! +line default + transport input ssh +! +call-home + service active + contact smart-licensing + profile CiscoTAC-1 + active + destination transport-method email disable + destination transport-method http + ! +! +netconf-yang agent + ssh +! +interface Loopback0 + ipv6 address fd00:ffff::3/128 +! +interface GigabitEthernet0/0/0/0 + description to:pe01 + ipv6 enable +! +interface GigabitEthernet0/0/0/1 + description to:pe02 + ipv6 enable +! +interface GigabitEthernet0/0/0/2 + description to:p02 + ipv6 enable +! +router isis 1 + is-type level-2-only + net 49.0000.0000.0001.0003.00 + address-family ipv6 unicast + metric-style wide + router-id Loopback0 + segment-routing srv6 + locator uSID + level 2 + ! + ! + ! + interface Loopback0 + passive + address-family ipv6 unicast + ! + ! + interface GigabitEthernet0/0/0/0 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 10 level 2 + ! + ! + interface GigabitEthernet0/0/0/1 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 100 level 2 + ! + ! + interface GigabitEthernet0/0/0/2 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 10 level 2 + ! + ! +! +mpls oam +! +segment-routing + srv6 + logging locator status + locators + locator uSID + micro-segment behavior unode psp-usd + prefix fcbb:bb00:1003::/48 + ! + ! + ! +! +ssh server v2 +ssh server vrf MGMT +ssh server netconf vrf MGMT +end diff --git a/examples/containerlab/srv6_usid_dynamic-path/startup-configs/p02.cfg b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/p02.cfg new file mode 100644 index 00000000..db3b3e43 --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/p02.cfg @@ -0,0 +1,106 @@ +hostname p02 +username admin + group root-lr + group cisco-support + secret 10 $6$MTEbC5od1RuC....$xvQt1LVtwS9akjpzHYOZyj6ZMLZwJ5R9PvRCMaqjrR9iqeoPXisq.rXiiJZPoPE6Gi5XL1yjIlzAY4dfWC6Gr1 +! +grpc + vrf MGMT + no-tls + address-family dual +! +vrf MGMT + address-family ipv4 unicast + ! + address-family ipv6 unicast + ! +! +line default + transport input ssh +! +call-home + service active + contact smart-licensing + profile CiscoTAC-1 + active + destination transport-method email disable + destination transport-method http + ! +! +netconf-yang agent + ssh +! +interface Loopback0 + ipv6 address fd00:ffff::4/128 +! +interface GigabitEthernet0/0/0/0 + description to:pe01 + ipv6 enable +! +interface GigabitEthernet0/0/0/1 + description to:pe02 + ipv6 enable +! +interface GigabitEthernet0/0/0/2 + description to:p01 + ipv6 enable +! +router isis 1 + is-type level-2-only + net 49.0000.0000.0001.0004.00 + address-family ipv6 unicast + metric-style wide + router-id Loopback0 + segment-routing srv6 + locator uSID + level 2 + ! + ! + ! + interface Loopback0 + passive + address-family ipv6 unicast + ! + ! + interface GigabitEthernet0/0/0/0 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 100 level 2 + ! + ! + interface GigabitEthernet0/0/0/1 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 10 level 2 + ! + ! + interface GigabitEthernet0/0/0/2 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 10 level 2 + ! + ! +! +mpls oam +! +segment-routing + srv6 + logging locator status + locators + locator uSID + micro-segment behavior unode psp-usd + prefix fcbb:bb00:1004::/48 + ! + ! + ! +! +ssh server v2 +ssh server vrf MGMT +ssh server netconf vrf MGMT +end diff --git a/examples/containerlab/srv6_usid_dynamic-path/startup-configs/pe01.cfg b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/pe01.cfg new file mode 100644 index 00000000..815f3672 --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/pe01.cfg @@ -0,0 +1,124 @@ +hostname pe01 +username admin + group root-lr + group cisco-support + secret admin@123 +! +grpc + vrf MGMT + port 9339 + no-tls + address-family dual +! +vrf MGMT + address-family ipv4 unicast + ! + address-family ipv6 unicast + ! +! +line default + transport input ssh +! +call-home + service active + contact smart-licensing + profile CiscoTAC-1 + active + destination transport-method email disable + destination transport-method http + ! +! +netconf-yang agent + ssh +! +interface Loopback0 + ipv6 address fd00:ffff::1/128 +! +interface GigabitEthernet0/0/0/0 + description to:p01 + ipv6 enable +! +interface GigabitEthernet0/0/0/1 + description to:p02 + ipv6 enable +! +interface GigabitEthernet0/0/0/2 + description to:pce + ipv6 address fd00::1/64 +! +router isis 1 + is-type level-2-only + net 49.0000.0000.0001.0001.00 + distribute link-state level 2 + address-family ipv6 unicast + metric-style wide + router-id Loopback0 + segment-routing srv6 + locator uSID + level 2 + ! + ! + ! + interface Loopback0 + passive + address-family ipv6 unicast + ! + ! + interface GigabitEthernet0/0/0/0 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 10 level 2 + ! + ! + interface GigabitEthernet0/0/0/1 + circuit-type level-2-only + point-to-point + hello-interval 1 + address-family ipv6 unicast + metric 100 level 2 + ! + ! +! +router bgp 65000 + bgp router-id 10.255.0.1 + address-family link-state link-state + ! + neighbor fd00::4 + remote-as 65000 + update-source GigabitEthernet0/0/0/2 + address-family link-state link-state + ! + ! +! +mpls oam +! +segment-routing + traffic-eng + candidate-paths + pcep + ! + ! + pcc + pce address ipv6 fd00::3 + ! + ! + ! + srv6 + logging locator status + micro-segment + merge-overlay-underlay-sids + ! + locators + locator uSID + micro-segment behavior unode psp-usd + prefix fcbb:bb00:1001::/48 + ! + ! + ! +! +ssh server v2 +ssh server vrf MGMT +ssh server netconf vrf MGMT +end diff --git a/examples/containerlab/srv6_usid_dynamic-path/startup-configs/pe02.cfg b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/pe02.cfg new file mode 100644 index 00000000..2eea3283 --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/startup-configs/pe02.cfg @@ -0,0 +1,134 @@ +chassis { + network-services enhanced-ip; +} + +interfaces { + ge-0/0/0 { + description "to:p01"; + unit 0 { + family iso; + family inet6; + } + } + ge-0/0/1 { + description "to:p02"; + unit 0 { + family iso; + family inet6; + } + } + ge-0/0/2 { + description "POLA-PCE"; + unit 0 { + family inet6 { + address fd00::2/64; + } + } + } + lo0 { + unit 0 { + family iso { + address 49.0000.0000.0001.0002.00; + } + family inet6 { + address fd00:ffff::2/128; + } + } + } +} + +routing-options { + router-id 10.255.0.2; + autonomous-system 65000; + forwarding-table { + srv6-chain-merge; + } + source-packet-routing { + srv6 { + no-reduced-srh; + block usid-block { + fcbb:bb00::/32; + local-micro-sid { + maximum-static-sids 1000; + } + } + locator loc-pe02 { + fcbb:bb00:1002::/48; + micro-sid { + block-name usid-block; + flavor psp; + flavor usd; + } + } + } + } +} + +protocols { + isis { + level 1 disable; + level 2 { + wide-metrics-only; + } + no-ipv4-routing; + topologies { + ipv6-unicast; + } + net 49.0000.0000.0001.0002.00; + interface ge-0/0/0.0 { + point-to-point; + level 2 { + ipv6-unicast-metric 100; + srv6-adjacency-segment { + unprotected { + locator loc-pe02 { + micro-adjacency-sid; + } + } + } + } + } + interface ge-0/0/1.0 { + point-to-point; + level 2 { + ipv6-unicast-metric 10; + srv6-adjacency-segment { + unprotected { + locator loc-pe02 { + micro-adjacency-sid; + } + } + } + } + } + interface lo0.0 { + passive; + } + source-packet-routing { + srv6 { + locator loc-pe02 { + micro-node-sid; + } + } + } + } + mpls { + lsp-external-controller pccd; + } + source-packet-routing { + lsp-external-controller pccd; + srv6; + preserve-nexthop-hierarchy; + } + pcep { + pce POLA-PCE { + local-ipv6-address fd00::2; + destination-ipv6-address fd00::3; + pce-type active; + pce-type stateful; + lsp-provisioning; + spring-capability; + srv6-capability; + } + } +} diff --git a/examples/containerlab/srv6_usid_dynamic-path/topo.clab.yml b/examples/containerlab/srv6_usid_dynamic-path/topo.clab.yml new file mode 100644 index 00000000..61217159 --- /dev/null +++ b/examples/containerlab/srv6_usid_dynamic-path/topo.clab.yml @@ -0,0 +1,59 @@ +name: dynamic-path +topology: + kinds: + xrd: + image: ios-xr/xrd-control-plane:7.8.1 + juniper_vjunosrouter: + image: vrnetlab/juniper_vjunos-router:24.2R1-S2.5 + nodes: + pe01: + kind: xrd + startup-config: startup-configs/pe01.cfg + pe02: + kind: juniper_vjunosrouter + startup-config: startup-configs/pe02.cfg + p01: + kind: xrd + startup-config: startup-configs/p01.cfg + p02: + kind: xrd + startup-config: startup-configs/p02.cfg + pola: + kind: linux + image: golang:1.24.1 + binds: + - bin/polad:/bin/polad + - bin/pola:/bin/pola + - polad/polad.yaml:/polad.yaml + - sr-policies/pe02-policy1.yaml:/pe02-policy1.yaml + exec: + - apt update + - apt install iproute2 -y + - ip addr add 10.0.0.3/24 dev eth1 + - ip -6 addr add fd00::3/64 dev eth1 + gobgp: + kind: linux + image: golang:1.24.1 + binds: + - bin/gobgpd:/bin/gobgpd + - bin/gobgp:/bin/gobgp + - gobgpd/gobgpd.yml:/gobgpd.yml + exec: + - apt update + - apt install iproute2 -y + - ip addr add 10.0.0.4/24 dev eth1 + - ip -6 addr add fd00::4/64 dev eth1 + switch: + kind: bridge + links: + # SRv6 domain + - endpoints: ["pe01:Gi0-0-0-0", "p01:Gi0-0-0-0"] + - endpoints: ["pe01:Gi0-0-0-1", "p02:Gi0-0-0-0"] + - endpoints: ["pe02:eth1", "p01:Gi0-0-0-1"] + - endpoints: ["pe02:eth2", "p02:Gi0-0-0-1"] + - endpoints: ["p01:Gi0-0-0-2", "p02:Gi0-0-0-2"] + # Switch + - endpoints: ["pe01:Gi0-0-0-2", "switch:eth1"] + - endpoints: ["pe02:eth3", "switch:eth2"] + - endpoints: ["pola:eth1", "switch:eth3"] + - endpoints: ["gobgp:eth1", "switch:eth4"] diff --git a/examples/containerlab/srv6_usid_dynamic-path/topo.png b/examples/containerlab/srv6_usid_dynamic-path/topo.png new file mode 100644 index 00000000..4a458b62 Binary files /dev/null and b/examples/containerlab/srv6_usid_dynamic-path/topo.png differ diff --git a/examples/tinet/sr-mpls_te_l3vpn/README.md b/examples/tinet/sr-mpls_te_l3vpn/README.md index ea1c3d30..e372b472 100644 --- a/examples/tinet/sr-mpls_te_l3vpn/README.md +++ b/examples/tinet/sr-mpls_te_l3vpn/README.md @@ -2,37 +2,43 @@ Example topology powered by [Tinet](https://github.com/tinynetwork/tinet) -![](./topo.png) +![Topology](./topo.png) ## Usage ### Install Tinet + Install Open vSwitch + ```bash -$ sudo apt update -$ sudo apt install openvswitch-switch openvswitch-common +sudo apt update +sudo apt install openvswitch-switch openvswitch-common ``` Install Tinet + ```bash -$ curl -Lo /usr/bin/tinet https://github.com/tinynetwork/tinet/releases/download/v0.0.2/tinet -$ chmod +x /usr/bin/tinet -$ tinet --version +curl -Lo /usr/bin/tinet https://github.com/tinynetwork/tinet/releases/download/v0.0.2/tinet +chmod +x /usr/bin/tinet +tinet --version ``` ### Building a Lab Network + Get spec.yaml, and start Docker network + ```bash -$ git clone https://github.com/nttcom/pola -$ cd pola/examples/tinet/sr-mpls_te_l3vpn +git clone https://github.com/nttcom/pola +cd pola/examples/tinet/sr-mpls_te_l3vpn -$ tinet upconf | sudo sh -x -$ docker ps +tinet upconf | sudo sh -x +docker ps ``` Connect to PCEP container, check PCEP session and SR policy + ```bash -$ docker exec -it pola /bin/bash +docker exec -it pola /bin/bash # pola session peerAddr(0): 10.0.255.1 @@ -40,10 +46,13 @@ peerAddr(0): 10.0.255.1 ``` ### Apply SR Policy + Create policy1.yaml (Explicit SR Policy: Segment List 16002/16004/16003 to pe01) + ```bash # vi policy1.yaml ``` + ```yaml srPolicy: name: policy1 @@ -61,13 +70,14 @@ srPolicy: ``` Apply and check SR Policy + ```bash -# pola sr-policy add -f policy1.yaml --no-link-state +# pola sr-policy add -f policy1.yaml --no-sid-validate success! # pola sr-policy list LSP(0): - PcepSessionAddr: 10.0.255.1 + PCEPSessionAddr: 10.0.255.1 PolicyName: policy1 SrcAddr: 10.0.255.1 DstAddr: 10.255.0.3 @@ -79,9 +89,10 @@ LSP(0): ``` Enter container pe01 and check SR Policy + ```bash # exit -$ docker exec -it pe01 /bin/bash +docker exec -it pe01 /bin/bash root@pe01:/# vtysh Hello, this is FRRouting (version 8.2.2). @@ -105,12 +116,14 @@ Endpoint: 10.255.0.3 Color: 1 Name: name BSID: - Status: Active ``` Add Color setting + ```bash -$ docker exec -it pe01 /bin/bash -$ vtysh -c 'conf t' -c 'router bgp 65000' -c 'address-family ipv4 vpn' -c 'neighbor 10.255.0.3 route-map color1 in' +docker exec -it pe01 /bin/bash +vtysh -c 'conf t' -c 'router bgp 65000' -c 'address-family ipv4 vpn' -c 'neighbor 10.255.0.3 route-map color1 in' ``` Check SR header with tcpdump + ```bash root@host01:/# ping 192.168.1.2 PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data. diff --git a/examples/tinet/sr-mpls_te_l3vpn/polad/polad.yaml b/examples/tinet/sr-mpls_te_l3vpn/polad/polad.yaml index bedd729d..3a8302f4 100644 --- a/examples/tinet/sr-mpls_te_l3vpn/polad/polad.yaml +++ b/examples/tinet/sr-mpls_te_l3vpn/polad/polad.yaml @@ -2,7 +2,7 @@ global: pcep: address: "10.0.255.254" port: 4189 - grpc-server: + grpcServer: address: "127.0.0.1" port: 50051 log: diff --git a/go.mod b/go.mod index 64f5c189..954ac177 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/nttcom/pola -go 1.24.2 +go 1.25.3 require ( - github.com/golang/protobuf v1.5.4 - github.com/osrg/gobgp/v3 v3.37.0 + github.com/osrg/gobgp/v4 v4.0.0-20251020140220-f6bf251a9a7f github.com/spf13/cobra v1.10.1 + github.com/stretchr/testify v1.11.1 go.uber.org/zap v1.27.0 google.golang.org/grpc v1.76.0 google.golang.org/protobuf v1.36.10 @@ -14,7 +14,9 @@ require ( ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.9 // indirect go.uber.org/multierr v1.10.0 // indirect golang.org/x/net v0.42.0 // indirect diff --git a/go.sum b/go.sum index 303dd379..5f0e0b81 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/osrg/gobgp/v3 v3.37.0 h1:+ObuOdvj7G7nxrT0fKFta+EAupdWf/q1WzbXydr8IOY= -github.com/osrg/gobgp/v3 v3.37.0/go.mod h1:kVHVFy1/fyZHJ8P32+ctvPeJogn9qKwa1YCeMRXXrP0= +github.com/osrg/gobgp/v4 v4.0.0-20251020140220-f6bf251a9a7f h1:tDfeX3Q8obMQrArGzU9K/LDzht1LGhk/OeoDxWJVxAs= +github.com/osrg/gobgp/v4 v4.0.0-20251020140220-f6bf251a9a7f/go.mod h1:1a0YiXMuyRPqcCX+fkXZ2UUtcOnUxAWynFunUOSZepk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -22,8 +22,8 @@ github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= diff --git a/internal/config/config.go b/internal/config/config.go index 263f118e..bd993afc 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,17 +12,17 @@ import ( "gopkg.in/yaml.v3" ) -type Pcep struct { +type PCEP struct { Address string `yaml:"address"` Port string `yaml:"port"` } -type GrpcServer struct { +type GRPCServer struct { Address string `yaml:"address"` Port string `yaml:"port"` } -type GrpcClient struct { +type GRPCClient struct { Address string `yaml:"address"` Port string `yaml:"port"` } @@ -33,22 +33,22 @@ type Log struct { Debug bool `yaml:"debug"` } -type Gobgp struct { - GrpcClient GrpcClient `yaml:"grpc-client"` +type GoBGP struct { + GRPCClient GRPCClient `yaml:"grpcClient"` } -type Ted struct { +type TED struct { Enable bool `yaml:"enable"` Source string `yaml:"source"` } type Global struct { - Pcep Pcep `yaml:"pcep"` - GrpcServer GrpcServer `yaml:"grpc-server"` + PCEP PCEP `yaml:"pcep"` + GRPCServer GRPCServer `yaml:"grpcServer"` Log Log `yaml:"log"` - Ted *Ted `yaml:"ted"` - Gobgp Gobgp `yaml:"gobgp"` - USidMode bool `yaml:"usid-mode"` + TED *TED `yaml:"ted"` + GoBGP GoBGP `yaml:"gobgp"` + USidMode bool `yaml:"usidMode"` } type Config struct { diff --git a/internal/pkg/cspf/cspf.go b/internal/pkg/cspf/cspf.go index 3709a038..88ac1d4d 100644 --- a/internal/pkg/cspf/cspf.go +++ b/internal/pkg/cspf/cspf.go @@ -27,7 +27,7 @@ func newNode(id string, cost uint32, nodeSeg table.Segment) *node { } } -func Cspf(srcRouterID string, dstRouterID string, as uint32, metric table.MetricType, ted *table.LsTed) ([]table.Segment, error) { +func Cspf(srcRouterID string, dstRouterID string, as uint32, metric table.MetricType, ted *table.LsTED) ([]table.Segment, error) { network := ted.Nodes[as] // TODO: update network information according to constraints segmentList, err := spf(srcRouterID, dstRouterID, metric, network) diff --git a/internal/pkg/gobgp/interface.go b/internal/pkg/gobgp/interface.go index 3867dbff..f9754972 100644 --- a/internal/pkg/gobgp/interface.go +++ b/internal/pkg/gobgp/interface.go @@ -16,261 +16,391 @@ import ( "strings" "github.com/nttcom/pola/internal/pkg/table" - api "github.com/osrg/gobgp/v3/api" + api "github.com/osrg/gobgp/v4/api" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "google.golang.org/protobuf/types/known/anypb" ) -type GobgpOptions struct { - GobgpAddr string - GobgpPort string -} - -func GetBgplsNlris(serverAddr string, serverPort string) ([]table.TedElem, error) { - gobgpAddress := serverAddr + ":" + serverPort +func GetBGPlsNLRIs(serverAddr string, serverPort string) ([]table.TEDElem, error) { + gobgpAddress := fmt.Sprintf("%s:%s", serverAddr, serverPort) - // Get connection + // Establish gRPC connection cc, err := grpc.NewClient( gobgpAddress, grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { - return nil, fmt.Errorf("failed to create gRPC client: %v", err) + return nil, fmt.Errorf("failed to create gRPC client (address: %s): %w", gobgpAddress, err) } defer func() { if err := cc.Close(); err != nil { - fmt.Fprintf(os.Stderr, "warning: failed to close gRPC client connection: %v\n", err) + fmt.Fprintf(os.Stderr, "failed to close gRPC client connection: %v\n", err) } }() // Create gRPC client - client := api.NewGobgpApiClient(cc) - ctx := context.Background() + client := api.NewGoBgpServiceClient(cc) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() req := &api.ListPathRequest{ - TableType: api.TableType_GLOBAL, + TableType: api.TableType_TABLE_TYPE_GLOBAL, Family: &api.Family{ Afi: api.Family_AFI_LS, Safi: api.Family_SAFI_LS, }, Name: "", - SortType: api.ListPathRequest_PREFIX, + SortType: api.ListPathRequest_SORT_TYPE_PREFIX, } stream, err := client.ListPath(ctx, req) if err != nil { - return nil, fmt.Errorf("failed to retrieve paths: %v", err) + return nil, fmt.Errorf("failed to retrieve paths from gRPC server: %w", err) } - var tedElems []table.TedElem + var tedElems []table.TEDElem for { r, err := stream.Recv() if err != nil { if err == io.EOF { break } - return nil, fmt.Errorf("error receiving stream data: %v", err) + return nil, fmt.Errorf("error receiving stream data: %w", err) } - convertedElems, err := ConvertToTedElem(r.Destination) + convertedElems, err := ConvertToTEDElem(r.Destination) if err != nil { - return nil, fmt.Errorf("failed to convert path to TED element: %v", err) + return nil, fmt.Errorf("failed to convert path to TED element (destination: %v): %w", r.Destination, err) } tedElems = append(tedElems, convertedElems...) } + return tedElems, nil } -func ConvertToTedElem(dst *api.Destination) ([]table.TedElem, error) { +// ConvertToTEDElem converts a single api.Destination to TEDElem(s) with low cyclomatic complexity. +func ConvertToTEDElem(dst *api.Destination) ([]table.TEDElem, error) { if len(dst.GetPaths()) != 1 { return nil, errors.New("invalid path length: expected 1 path") } path := dst.GetPaths()[0] - nlri, err := path.GetNlri().UnmarshalNew() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal NLRI: %v", err) + nlri := path.GetNlri() + if nlri == nil { + return nil, errors.New("NLRI is nil") } - switch nlri := nlri.(type) { - case *api.LsAddrPrefix: - linkStateNlri, err := nlri.GetNlri().UnmarshalNew() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal LS Address Prefix: %v", err) - } + lsAddrPrefix := nlri.GetLsAddrPrefix() + if lsAddrPrefix == nil { + return nil, errors.New("LSAddrPrefix is nil") + } - switch linkStateNlri := linkStateNlri.(type) { - case *api.LsNodeNLRI: - lsNode, err := getLsNodeNLRI(linkStateNlri, path.GetPattrs()) - if err != nil { - return nil, fmt.Errorf("failed to process LS Node NLRI: %v", err) - } - return []table.TedElem{lsNode}, nil - case *api.LsLinkNLRI: - lsLink, err := getLsLinkNLRI(linkStateNlri, path.GetPattrs()) - if err != nil { - return nil, fmt.Errorf("failed to process LS Link NLRI: %v", err) - } - return []table.TedElem{lsLink}, nil - case *api.LsPrefixV4NLRI: - lsPrefixV4List, err := getLsPrefixV4List(path.GetPattrs()) - if err != nil { - return nil, fmt.Errorf("failed to process LS Prefix V4 NLRI: %v", err) - } - return lsPrefixV4List, nil - default: - return nil, errors.New("invalid LS Link State NLRI type") + lsAttr := findLsAttribute(path) + if lsAttr == nil { + // BGP-LS Attribute not found, return empty + return nil, nil + } + + return convertByNlriType(lsAddrPrefix, lsAttr, path) +} + +// findLsAttribute extracts the BGP-LS attribute from a path. +func findLsAttribute(path *api.Path) *api.Attribute_Ls { + for _, pathAttr := range path.GetPattrs() { + if lsAttr, ok := pathAttr.Attr.(*api.Attribute_Ls); ok { + return lsAttr } + } + return nil +} + +// convertByNlriType dispatches NLRI processing based on its type. +func convertByNlriType(nlri *api.LsAddrPrefix, lsAttr *api.Attribute_Ls, path *api.Path) ([]table.TEDElem, error) { + switch nlri.GetType() { + case api.LsNLRIType_LS_NLRI_TYPE_NODE: + return convertNode(nlri, lsAttr) + case api.LsNLRIType_LS_NLRI_TYPE_LINK: + return convertLink(nlri, lsAttr) + case api.LsNLRIType_LS_NLRI_TYPE_PREFIX_V4, api.LsNLRIType_LS_NLRI_TYPE_PREFIX_V6: + return convertPrefix(nlri, lsAttr, path) + case api.LsNLRIType_LS_NLRI_TYPE_SRV6_SID: + return convertSrv6SID(nlri, lsAttr, path) default: - return nil, errors.New("invalid NLRI type") + return nil, fmt.Errorf("invalid LS NLRI type: %s", nlri.GetType().String()) } } -func getLsNodeNLRI(typedLinkStateNlri *api.LsNodeNLRI, pathAttrs []*anypb.Any) (*table.LsNode, error) { - asn := typedLinkStateNlri.GetLocalNode().GetAsn() - routerID := typedLinkStateNlri.GetLocalNode().GetIgpRouterId() +// convertNode handles LS Node NLRI. +func convertNode(nlri *api.LsAddrPrefix, lsAttr *api.Attribute_Ls) ([]table.TEDElem, error) { + nodeAttr := lsAttr.Ls.GetNode() + if nodeAttr == nil { + return nil, fmt.Errorf("LS Node Attribute is nil") + } + lsNode, err := getLsNode(nlri, nodeAttr) + if err != nil { + return nil, fmt.Errorf("failed to process LS Node NLRI: %w", err) + } + return []table.TEDElem{lsNode}, nil +} - lsNode := table.NewLsNode(asn, routerID) +// convertLink handles LS Link NLRI. +func convertLink(nlri *api.LsAddrPrefix, lsAttr *api.Attribute_Ls) ([]table.TEDElem, error) { + linkAttr := lsAttr.Ls.GetLink() + if linkAttr == nil { + return nil, fmt.Errorf("LS Link Attribute is nil") + } + lsLink, err := getLsLink(nlri, linkAttr) + if err != nil { + return nil, fmt.Errorf("failed to process LS Link NLRI: %w", err) + } + return []table.TEDElem{lsLink}, nil +} - for _, pathAttr := range pathAttrs { - typedPathAttr, err := pathAttr.UnmarshalNew() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal path attribute: %v", err) - } +// convertPrefix handles LS Prefix V4/V6 NLRI. +func convertPrefix(nlri *api.LsAddrPrefix, lsAttr *api.Attribute_Ls, path *api.Path) ([]table.TEDElem, error) { + prefixAttr := lsAttr.Ls.GetPrefix() + if prefixAttr == nil { + return nil, fmt.Errorf("LS Prefix Attribute is nil") + } + + mpReach := findMpReach(path) + if mpReach == nil { + return nil, errors.New("MP-REACH NLRI Attribute is nil") + } + + lsPrefixList, err := getLsPrefixList(mpReach.GetNlris(), prefixAttr) + if err != nil { + return nil, fmt.Errorf("failed to process LS Prefix NLRI: %w", err) + } + + return lsPrefixList, nil +} + +// convertSrv6SID handles LS SRv6 SID NLRI. +func convertSrv6SID(nlri *api.LsAddrPrefix, lsAttr *api.Attribute_Ls, path *api.Path) ([]table.TEDElem, error) { + srv6Attr := lsAttr.Ls.GetSrv6Sid() + if srv6Attr == nil { + return nil, fmt.Errorf("LS SRv6 SID Attribute is nil") + } - bgplsAttr, ok := typedPathAttr.(*api.LsAttribute) - if !ok { - continue + mpReach := findMpReach(path) + if mpReach == nil { + return nil, errors.New("MP-REACH NLRI Attribute is nil") + } + + lsSrv6List, err := getLsSrv6SIDList(mpReach.GetNlris(), srv6Attr) + if err != nil { + return nil, fmt.Errorf("failed to process LS SRv6 SID NLRI: %w", err) + } + + return lsSrv6List, nil +} + +// findMpReach searches for MP-REACH NLRI attribute in path. +func findMpReach(path *api.Path) *api.MpReachNLRIAttribute { + for _, attr := range path.GetPattrs() { + if mp := attr.GetMpReach(); mp != nil { + return mp } + } + return nil +} - isisArea := bgplsAttr.GetNode().GetIsisArea() - tmpIsisArea := hex.EncodeToString(isisArea) - strIsisArea := "" - for i, s := range strings.Split(tmpIsisArea, "") { - if (len(tmpIsisArea)-i)%4 == 0 { - strIsisArea += "." - } - strIsisArea += s +// formatIsisAreaID formats the ISIS Area ID into a human-readable string. +func formatIsisAreaID(isisArea []byte) string { + tmpIsisArea := hex.EncodeToString(isisArea) + var strIsisArea strings.Builder + for i, s := range strings.Split(tmpIsisArea, "") { + if (len(tmpIsisArea)-i)%4 == 0 && i != 0 { + strIsisArea.WriteString(".") } - lsNode.IsisAreaID = strIsisArea - lsNode.Hostname = bgplsAttr.GetNode().GetName() + strIsisArea.WriteString(s) + } + return strIsisArea.String() +} + +func getLsNode(typedLinkStateNLRI *api.LsAddrPrefix, lsAttrNode *api.LsAttributeNode) (*table.LsNode, error) { + localNode := typedLinkStateNLRI.Nlri.GetNode().GetLocalNode() + lsNode := table.NewLsNode(localNode.GetAsn(), localNode.GetIgpRouterId()) + + lsNode.IsisAreaID = formatIsisAreaID(lsAttrNode.GetIsisArea()) + lsNode.Hostname = lsAttrNode.GetName() - srCapabilities := bgplsAttr.GetNode().GetSrCapabilities().GetRanges() + if lsAttrNode.GetSrCapabilities() != nil { + srCapabilities := lsAttrNode.GetSrCapabilities().GetRanges() if len(srCapabilities) != 1 { - return nil, errors.New("invalid SR Capability TLV") + return nil, fmt.Errorf("expected 1 SR Capability TLV, got: %d", len(srCapabilities)) } lsNode.SrgbBegin = srCapabilities[0].GetBegin() lsNode.SrgbEnd = srCapabilities[0].GetEnd() } - return lsNode, nil } -func getLsLinkNLRI(typedLinkStateNlri *api.LsLinkNLRI, pathAttrs []*anypb.Any) (*table.LsLink, error) { - localNode := table.NewLsNode(typedLinkStateNlri.GetLocalNode().GetAsn(), typedLinkStateNlri.GetLocalNode().GetIgpRouterId()) - remoteNode := table.NewLsNode(typedLinkStateNlri.GetRemoteNode().GetAsn(), typedLinkStateNlri.GetRemoteNode().GetIgpRouterId()) +func getLsLink(typedLinkStateNLRI *api.LsAddrPrefix, lsAttrLink *api.LsAttributeLink) (*table.LsLink, error) { + lsLinkNLRI := typedLinkStateNLRI.Nlri.GetLink() + localNode := table.NewLsNode(lsLinkNLRI.GetLocalNode().GetAsn(), lsLinkNLRI.GetLocalNode().GetIgpRouterId()) + remoteNode := table.NewLsNode(lsLinkNLRI.GetRemoteNode().GetAsn(), lsLinkNLRI.GetRemoteNode().GetIgpRouterId()) - localIP, err := netip.ParseAddr(typedLinkStateNlri.GetLinkDescriptor().GetInterfaceAddrIpv4()) - if err != nil { - return nil, fmt.Errorf("failed to parse local IP address: %v", err) + var err error + var localIP netip.Addr + if lsLinkNLRI.GetLinkDescriptor().GetInterfaceAddrIpv4() != "" { + localIP, err = netip.ParseAddr(lsLinkNLRI.GetLinkDescriptor().GetInterfaceAddrIpv4()) + if err != nil { + return nil, fmt.Errorf("failed to parse local IPv4 address: %v", err) + } + } else if lsLinkNLRI.GetLinkDescriptor().GetInterfaceAddrIpv6() != "" { + localIP, err = netip.ParseAddr(lsLinkNLRI.GetLinkDescriptor().GetInterfaceAddrIpv6()) + if err != nil { + return nil, fmt.Errorf("failed to parse local IPv6 address: %v", err) + } + } else { + localIP = netip.Addr{} } - remoteIP, err := netip.ParseAddr(typedLinkStateNlri.GetLinkDescriptor().GetNeighborAddrIpv4()) - if err != nil { - return nil, fmt.Errorf("failed to parse remote IP address: %v", err) + var remoteIP netip.Addr + if lsLinkNLRI.GetLinkDescriptor().GetNeighborAddrIpv4() != "" { + remoteIP, err = netip.ParseAddr(lsLinkNLRI.GetLinkDescriptor().GetNeighborAddrIpv4()) + if err != nil { + return nil, fmt.Errorf("failed to parse remote IPv4 address: %v", err) + } + } else if lsLinkNLRI.GetLinkDescriptor().GetNeighborAddrIpv6() != "" { + remoteIP, err = netip.ParseAddr(lsLinkNLRI.GetLinkDescriptor().GetNeighborAddrIpv6()) + if err != nil { + return nil, fmt.Errorf("failed to parse remote IPv6 address: %v", err) + } + } else { + remoteIP = netip.Addr{} } lsLink := table.NewLsLink(localNode, remoteNode) lsLink.LocalIP = localIP lsLink.RemoteIP = remoteIP - for _, pathAttr := range pathAttrs { - typedPathAttr, err := pathAttr.UnmarshalNew() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal path attribute: %v", err) - } - - bgplsAttr, ok := typedPathAttr.(*api.LsAttribute) - if !ok { - continue - } + lsLink.Metrics = append(lsLink.Metrics, table.NewMetric(table.MetricType(table.IGPMetric), lsAttrLink.GetIgpMetric())) - lsLink.Metrics = append(lsLink.Metrics, table.NewMetric(table.MetricType(table.IGP_METRIC), bgplsAttr.GetLink().GetIgpMetric())) + teMetric := lsAttrLink.GetDefaultTeMetric() + if teMetric != 0 { + lsLink.Metrics = append(lsLink.Metrics, table.NewMetric(table.MetricType(table.TEMetric), teMetric)) + } - teMetric := bgplsAttr.GetLink().GetDefaultTeMetric() - if teMetric != 0 { - lsLink.Metrics = append(lsLink.Metrics, table.NewMetric(table.MetricType(table.TE_METRIC), teMetric)) + lsLink.AdjSid = lsAttrLink.GetSrAdjacencySid() + + // handle SRv6 SID TLV + srv6EndXSID := lsAttrLink.GetSrv6EndXSid() + if srv6EndXSID != nil { + lsLink.Srv6EndXSID = &table.Srv6EndXSID{ + EndpointBehavior: uint16(srv6EndXSID.EndpointBehavior), + Sids: srv6EndXSID.Sids, + Srv6SIDStructure: table.SIDStructure{ + LocalBlock: uint8(srv6EndXSID.Srv6SidStructure.GetLocalBlock()), + LocalNode: uint8(srv6EndXSID.Srv6SidStructure.GetLocalNode()), + LocalFunc: uint8(srv6EndXSID.Srv6SidStructure.GetLocalFunc()), + LocalArg: uint8(srv6EndXSID.Srv6SidStructure.GetLocalArg()), + }, } - - lsLink.AdjSid = bgplsAttr.GetLink().GetSrAdjacencySid() } return lsLink, nil } -func getLsPrefixV4List(pathAttrs []*anypb.Any) ([]table.TedElem, error) { - var lsPrefixV4List []table.TedElem - var sidIndex uint32 +func getLsPrefixList(nlris []*api.NLRI, lsAttrPrefix *api.LsAttributePrefix) ([]table.TEDElem, error) { + var lsPrefixList []table.TEDElem - for _, pathAttr := range pathAttrs { - typedPathAttr, err := pathAttr.UnmarshalNew() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal path attribute: %v", err) - } + for _, nlri := range nlris { + lsAddrPrefix := nlri.GetLsAddrPrefix() - switch typedPathAttr := typedPathAttr.(type) { - case *api.LsAttribute: - sidIndex = typedPathAttr.GetPrefix().GetSrPrefixSid() - - case *api.MpReachNLRIAttribute: - for _, nlri := range typedPathAttr.GetNlris() { - typedNlri, err := nlri.UnmarshalNew() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal NLRI: %v", err) - } - - if lsNlri, ok := typedNlri.(*api.LsAddrPrefix); ok { - lsPrefixV4, err := getLsPrefixV4(lsNlri, sidIndex) - if err != nil { - return nil, fmt.Errorf("failed to get LS Prefix V4: %v", err) - } - lsPrefixV4List = append(lsPrefixV4List, lsPrefixV4) - } - } + lsPrefix, err := getLsPrefix(lsAddrPrefix, lsAttrPrefix) + if err != nil { + return nil, fmt.Errorf("failed to get LS Prefix: %v", err) } + lsPrefixList = append(lsPrefixList, lsPrefix) } - - return lsPrefixV4List, nil + return lsPrefixList, nil } -func getLsPrefixV4(lsNlri *api.LsAddrPrefix, sidIndex uint32) (*table.LsPrefixV4, error) { - prefNlri, err := lsNlri.GetNlri().UnmarshalNew() - if err != nil { - return nil, fmt.Errorf("failed to unmarshal LS Prefix V4: %v", err) - } - prefv4Nlri, ok := prefNlri.(*api.LsPrefixV4NLRI) - if !ok { - return nil, errors.New("invalid LS prefix v4 NLRI type") +func getLsPrefix(typedLinkStateNLRI *api.LsAddrPrefix, lsAttrPrefix *api.LsAttributePrefix) (*table.LsPrefix, error) { + var localNodeID string + var localNodeAsn uint32 + var prefix []string + var sidIndex uint32 + + if lsAttrPrefix.GetSrPrefixSid() != 0 { + sidIndex = lsAttrPrefix.GetSrPrefixSid() + } else { + sidIndex = 0 } - localNodeID := prefv4Nlri.GetLocalNode().GetIgpRouterId() - localNodeAsn := prefv4Nlri.GetLocalNode().GetAsn() - prefixV4 := prefv4Nlri.GetPrefixDescriptor().GetIpReachability() + switch prefNLRI := typedLinkStateNLRI.Nlri.Nlri.(type) { + case *api.LsAddrPrefix_LsNLRI_PrefixV4: + localNodeID = prefNLRI.PrefixV4.GetLocalNode().GetIgpRouterId() + localNodeAsn = prefNLRI.PrefixV4.GetLocalNode().GetAsn() + prefix = prefNLRI.PrefixV4.GetPrefixDescriptor().GetIpReachability() + case *api.LsAddrPrefix_LsNLRI_PrefixV6: + localNodeID = prefNLRI.PrefixV6.GetLocalNode().GetIgpRouterId() + localNodeAsn = prefNLRI.PrefixV6.GetLocalNode().GetAsn() + prefix = prefNLRI.PrefixV6.GetPrefixDescriptor().GetIpReachability() + default: + return nil, errors.New("invalid LS prefix NLRI type") + } localNode := table.NewLsNode(localNodeAsn, localNodeID) - lsPrefixV4 := table.NewLsPrefixV4(localNode) - lsPrefixV4.SidIndex = sidIndex + lsPrefix := table.NewLsPrefix(localNode) + lsPrefix.SidIndex = sidIndex - if len(prefixV4) != 1 { + if len(prefix) != 1 { return nil, errors.New("invalid prefix length: expected 1 prefix") } - lsPrefixV4.Prefix, err = netip.ParsePrefix(prefixV4[0]) + var err error + lsPrefix.Prefix, err = netip.ParsePrefix(prefix[0]) if err != nil { return nil, fmt.Errorf("failed to parse prefix: %v", err) } - return lsPrefixV4, nil + return lsPrefix, nil +} + +func getLsSrv6SIDList(nlris []*api.NLRI, lsAttrSrv6SID *api.LsAttributeSrv6SID) ([]table.TEDElem, error) { + var lsSrv6SIDList []table.TEDElem + + for _, nlri := range nlris { + lsAddrPrefix := nlri.GetLsAddrPrefix() + + lsPrefix, err := getLsSrv6SID(lsAddrPrefix, lsAttrSrv6SID) + if err != nil { + return nil, fmt.Errorf("failed to get LS Prefix: %v", err) + } + lsSrv6SIDList = append(lsSrv6SIDList, lsPrefix) + } + + return lsSrv6SIDList, nil +} + +// getLsSrv6SID processes the LS SRv6 SID NLRI and returns a corresponding LsSrv6SID. +func getLsSrv6SID(typedLinkStateNLRI *api.LsAddrPrefix, lsAttrSrv6SID *api.LsAttributeSrv6SID) (*table.LsSrv6SID, error) { + + srv6SIDStructure := lsAttrSrv6SID.GetSrv6SidStructure() + endpointBehavior := lsAttrSrv6SID.GetSrv6EndpointBehavior() + srv6SIDNLRI := typedLinkStateNLRI.Nlri.GetSrv6Sid() + + localNodeID := srv6SIDNLRI.GetLocalNode().GetIgpRouterId() + localNodeASN := srv6SIDNLRI.GetLocalNode().GetAsn() + srv6SIDs := srv6SIDNLRI.GetSrv6SidInformation().GetSids() + multiTopoIDs := srv6SIDNLRI.GetMultiTopoId().GetMultiTopoIds() + + localNode := table.NewLsNode(localNodeASN, localNodeID) + lsSrv6SID := table.NewLsSrv6SID(localNode) + lsSrv6SID.SIDStructure.LocalBlock = uint8(srv6SIDStructure.GetLocalBlock()) + lsSrv6SID.SIDStructure.LocalNode = uint8(srv6SIDStructure.GetLocalNode()) + lsSrv6SID.SIDStructure.LocalFunc = uint8(srv6SIDStructure.GetLocalFunc()) + lsSrv6SID.SIDStructure.LocalArg = uint8(srv6SIDStructure.GetLocalArg()) + lsSrv6SID.EndpointBehavior.Behavior = uint16(endpointBehavior.GetEndpointBehavior()) + lsSrv6SID.EndpointBehavior.Flags = uint8(endpointBehavior.GetFlags()) + lsSrv6SID.EndpointBehavior.Algorithm = uint8(endpointBehavior.GetAlgorithm()) + lsSrv6SID.Sids = srv6SIDs + lsSrv6SID.MultiTopoIDs = multiTopoIDs + + return lsSrv6SID, nil } diff --git a/internal/pkg/table/sr_policy.go b/internal/pkg/table/sr_policy.go index dd02a3c1..c183abc5 100644 --- a/internal/pkg/table/sr_policy.go +++ b/internal/pkg/table/sr_policy.go @@ -15,10 +15,10 @@ import ( type PolicyState string const ( - POLICY_DOWN = PolicyState("down") - POLICY_UP = PolicyState("up") - POLICY_ACTIVE = PolicyState("active") - POLICY_UNKNOWN = PolicyState("unknown") + PolicyDown = PolicyState("down") + PolicyUp = PolicyState("up") + PolicyActive = PolicyState("active") + PolicyUnknown = PolicyState("unknown") ) type SRPolicy struct { @@ -29,12 +29,12 @@ type SRPolicy struct { DstAddr netip.Addr Color uint32 Preference uint32 - LspID uint16 + LSPID uint16 State PolicyState } func NewSRPolicy( - plspId uint32, + plspID uint32, name string, segmentList []Segment, srcAddr netip.Addr, @@ -45,14 +45,14 @@ func NewSRPolicy( state PolicyState, ) *SRPolicy { p := &SRPolicy{ - PlspID: plspId, + PlspID: plspID, Name: name, SegmentList: segmentList, SrcAddr: srcAddr, DstAddr: dstAddr, Color: color, Preference: preference, - LspID: lspID, + LSPID: lspID, State: state, } @@ -65,13 +65,13 @@ type PolicyDiff struct { Color *uint32 Preference *uint32 SegmentList []Segment - LspID uint16 + LSPID uint16 State PolicyState } func (p *SRPolicy) Update(df PolicyDiff) { p.State = df.State - p.LspID = df.LspID + p.LSPID = df.LSPID if df.Name != nil { p.Name = *df.Name } @@ -86,7 +86,7 @@ func (p *SRPolicy) Update(df PolicyDiff) { } } -const SRV6_SID_BIT_LENGTH = 128 +const SRv6SIDBitLength = 128 type Segment interface { SidString() string @@ -107,13 +107,32 @@ func NewSegment(sid string) (Segment, error) { } const ( - BEHAVIOR_RESERVED uint16 = 0x0000 - BEHAVIOR_END uint16 = 0x0001 - BEHAVIOR_END_X uint16 = 0x0005 - BEHAVIOR_UN uint16 = 0x0030 - BEHAVIOR_UA uint16 = 0x0039 + BehaviorReserved uint16 = 0x0000 + BehaviorEND uint16 = 0x0001 + BehaviorENDX uint16 = 0x0005 + BehaviorUN uint16 = 0x0030 + BehaviorUA uint16 = 0x0039 ) +func BehaviorToString(behavior uint16) string { + switch behavior { + case BehaviorReserved: + return "RESERVED" + case BehaviorEND: + return "END" + case BehaviorENDX: + return "ENDX" + case BehaviorUN: + return "UN" + case BehaviorUA: + return "UA" + default: + return "UNKNOWN" + } +} + +const FirstSIDIndex = 0 // Index for first SID in Sids array + type SegmentSRv6 struct { Sid netip.Addr LocalAddr netip.Addr @@ -126,24 +145,20 @@ func (seg SegmentSRv6) SidString() string { return seg.Sid.String() } -func (seg SegmentSRv6) Behavior() uint16 { - if seg.LocalAddr.IsValid() { - if seg.USid { - if seg.RemoteAddr.IsValid() { - return BEHAVIOR_UA - } else { - return BEHAVIOR_UN - } - } else { - if seg.RemoteAddr.IsValid() { - return BEHAVIOR_END_X - } else { - return BEHAVIOR_END - } +func (seg SegmentSRv6) Behavior() (uint16, error) { + if !seg.LocalAddr.IsValid() { + return 0, errors.New("SegmentSRv6: LocalAddr is invalid") + } + if seg.USid { + if seg.RemoteAddr.IsValid() { + return BehaviorUA, nil } - } else { - return BEHAVIOR_RESERVED + return BehaviorUN, nil + } + if seg.RemoteAddr.IsValid() { + return BehaviorENDX, nil } + return BehaviorEND, nil } func NewSegmentSRv6(sid netip.Addr) SegmentSRv6 { @@ -152,6 +167,41 @@ func NewSegmentSRv6(sid netip.Addr) SegmentSRv6 { } } +func NewSegmentSRv6WithNodeInfo(sid netip.Addr, n *LsNode) (SegmentSRv6, error) { + seg := SegmentSRv6{ + Sid: sid, + } + + var found bool + for _, srv6SID := range n.SRv6SIDs { + if len(srv6SID.Sids) > 0 { + addr, err := netip.ParseAddr(srv6SID.Sids[FirstSIDIndex]) + if err != nil { + return seg, err + } + seg.LocalAddr = addr + seg.Structure = []uint8{ + srv6SID.SIDStructure.LocalBlock, + srv6SID.SIDStructure.LocalNode, + srv6SID.SIDStructure.LocalFunc, + srv6SID.SIDStructure.LocalArg, + } + switch srv6SID.EndpointBehavior.Behavior { + case BehaviorUN, BehaviorUA: + seg.USid = true + default: + seg.USid = false + } + found = true + break + } + } + if !found { + return seg, errors.New("no SRv6 SIDs available") + } + return seg, nil +} + type SegmentSRMPLS struct { Sid uint32 } diff --git a/internal/pkg/table/ted.go b/internal/pkg/table/ted.go index da278ea8..8e68fc0c 100644 --- a/internal/pkg/table/ted.go +++ b/internal/pkg/table/ted.go @@ -12,68 +12,173 @@ import ( "strconv" ) -type LsTed struct { +type LsTED struct { ID int Nodes map[uint32]map[string]*LsNode // { ASN1: {"NodeID1": node1, "NodeID2": node2}, ASN2: {"NodeID3": node3, "NodeID4": node4}} } -func (ted *LsTed) Update(tedElems []TedElem) { +func (ted *LsTED) Update(tedElems []TEDElem) { for _, tedElem := range tedElems { - tedElem.UpdateTed(ted) + tedElem.UpdateTED(ted) } } -func (ted *LsTed) Print() { +// Print outputs the TED in a structured way with low cyclomatic complexity. +func (ted *LsTED) Print() { + if ted == nil || ted.Nodes == nil { + fmt.Println("TED is empty") + return + } + for _, nodes := range ted.Nodes { - nodeCnt := 1 - for nodeID, node := range nodes { - fmt.Printf("Node: %d\n", nodeCnt) - fmt.Printf(" %s\n", nodeID) - fmt.Printf(" Hostname: %s\n", node.Hostname) - fmt.Printf(" ISIS Area ID: %s\n", node.IsisAreaID) - fmt.Printf(" SRGB: %d - %d\n", node.SrgbBegin, node.SrgbEnd) - fmt.Printf(" Prefixes:\n") - for _, prefix := range node.Prefixes { - fmt.Printf(" %s\n", prefix.Prefix.String()) - if prefix.SidIndex != 0 { - fmt.Printf(" index: %d\n", prefix.SidIndex) - } - } + if nodes == nil { + continue + } + printNodes(nodes) + } +} + +// printNodes iterates over each node in the map and prints its details. +func printNodes(nodes map[string]*LsNode) { + nodeCnt := 1 + for nodeID, node := range nodes { + if node == nil { + continue + } + fmt.Printf("Node: %d\n", nodeCnt) + printNodeBasic(nodeID, node) + printNodePrefixes(node) + printNodeLinks(node) + printNodeSRv6SIDs(node) + fmt.Println() + nodeCnt++ + } +} + +// printNodeBasic prints the basic information of a node. +func printNodeBasic(nodeID string, node *LsNode) { + fmt.Printf(" %s\n", nodeID) + fmt.Printf(" Hostname: %s\n", node.Hostname) + fmt.Printf(" ISIS Area ID: %s\n", node.IsisAreaID) + fmt.Printf(" SRGB: %d - %d\n", node.SrgbBegin, node.SrgbEnd) +} + +// printNodePrefixes prints the prefixes associated with a node. +func printNodePrefixes(node *LsNode) { + fmt.Println(" Prefixes:") + if node.Prefixes == nil { + return + } + for _, prefix := range node.Prefixes { + if prefix == nil { + continue + } + fmt.Printf(" %s\n", prefix.Prefix.String()) + if prefix.SidIndex != 0 { + fmt.Printf(" index: %d\n", prefix.SidIndex) + } + } +} + +// printNodeLinks prints the links associated with a node. +func printNodeLinks(node *LsNode) { + fmt.Println(" Links:") + if node.Links == nil { + return + } + for _, link := range node.Links { + if link == nil { + continue + } + printLink(link) + } +} + +// printLink prints the details of a single link. +func printLink(link *LsLink) { + localIP := "None" + remoteIP := "None" + if link.LocalIP.IsValid() { + localIP = link.LocalIP.String() + } + if link.RemoteIP.IsValid() { + remoteIP = link.RemoteIP.String() + } + fmt.Printf(" Local: %s Remote: %s\n", localIP, remoteIP) - fmt.Printf(" Links:\n") - for _, link := range node.Links { - fmt.Printf(" Local: %s Remote: %s\n", link.LocalIP.String(), link.RemoteIP.String()) - fmt.Printf(" RemoteNode: %s\n", link.RemoteNode.RouterID) - fmt.Printf(" Metrics:\n") - for _, metric := range link.Metrics { - fmt.Printf(" %s: %d\n", metric.Type.String(), metric.Value) - } - fmt.Printf(" Adj-SID: %d\n", link.AdjSid) + remoteNodeID := "None" + if link.RemoteNode != nil { + remoteNodeID = link.RemoteNode.RouterID + } + fmt.Printf(" RemoteNode: %s\n", remoteNodeID) + + fmt.Println(" Metrics:") + if link.Metrics != nil { + for _, metric := range link.Metrics { + if metric == nil { + continue } - nodeCnt++ - fmt.Printf("\n") + fmt.Printf(" %s: %d\n", metric.Type.String(), metric.Value) + } + } + + fmt.Printf(" Adj-SID: %d\n", link.AdjSid) + + if link.Srv6EndXSID != nil { + fmt.Println(" SRv6 End.X SID:") + fmt.Printf(" EndpointBehavior: %s\n", BehaviorToString(link.Srv6EndXSID.EndpointBehavior)) + fmt.Printf(" SIDs: %v\n", link.Srv6EndXSID.Sids) + fmt.Printf(" SID Structure: Block: %d, Node: %d, Func: %d, Arg: %d\n", + link.Srv6EndXSID.Srv6SIDStructure.LocalBlock, + link.Srv6EndXSID.Srv6SIDStructure.LocalNode, + link.Srv6EndXSID.Srv6SIDStructure.LocalFunc, + link.Srv6EndXSID.Srv6SIDStructure.LocalArg) + } +} + +// printNodeSRv6SIDs prints the SRv6 SIDs associated with a node. +func printNodeSRv6SIDs(node *LsNode) { + fmt.Println(" SRv6 SIDs:") + if node.SRv6SIDs == nil { + return + } + for _, srv6SID := range node.SRv6SIDs { + if srv6SID == nil { + continue } + fmt.Printf(" SIDs: %v\n", srv6SID.Sids) + fmt.Printf(" Block: %d, Node: %d, Func: %d, Arg: %d\n", + srv6SID.SIDStructure.LocalBlock, + srv6SID.SIDStructure.LocalNode, + srv6SID.SIDStructure.LocalFunc, + srv6SID.SIDStructure.LocalArg) + fmt.Printf(" EndpointBehavior: %s, Flags: %d, Algorithm: %d\n", + BehaviorToString(srv6SID.EndpointBehavior.Behavior), + srv6SID.EndpointBehavior.Flags, + srv6SID.EndpointBehavior.Algorithm) + fmt.Printf(" MultiTopoIDs: %v\n", srv6SID.MultiTopoIDs) } } -type TedElem interface { - UpdateTed(ted *LsTed) +type TEDElem interface { + UpdateTED(ted *LsTED) } type LsNode struct { - Asn uint32 // primary key, in MP_REACH_NLRI Attr + ASN uint32 // primary key, in MP_REACH_NLRI Attr RouterID string // primary key, in MP_REACH_NLRI Attr IsisAreaID string // in BGP-LS Attr Hostname string // in BGP-LS Attr SrgbBegin uint32 // in BGP-LS Attr SrgbEnd uint32 // in BGP-LS Attr Links []*LsLink - Prefixes []*LsPrefixV4 + Prefixes []*LsPrefix + SRv6SIDs []*LsSrv6SID } func NewLsNode(asn uint32, nodeID string) *LsNode { return &LsNode{ - Asn: asn, + ASN: asn, RouterID: nodeID, } } @@ -81,7 +186,7 @@ func NewLsNode(asn uint32, nodeID string) *LsNode { func (n *LsNode) NodeSegment() (Segment, error) { // for SR-MPLS Segment for _, prefix := range n.Prefixes { - if prefix.SidIndex != 0 { + if prefix.SidIndex > FirstSIDIndex { sid := strconv.Itoa(int(n.SrgbBegin + prefix.SidIndex)) seg, err := NewSegment(sid) if err != nil { @@ -90,23 +195,42 @@ func (n *LsNode) NodeSegment() (Segment, error) { return seg, nil } } - // TODO: for SRv6 Segment + // for SRv6 Segment + for _, srv6SID := range n.SRv6SIDs { + if len(srv6SID.Sids) > FirstSIDIndex { + addr, err := netip.ParseAddr(srv6SID.Sids[FirstSIDIndex]) + if err != nil { + return nil, err + } + seg, err := NewSegmentSRv6WithNodeInfo(addr, n) + if err != nil { + return nil, err + } + return seg, nil + } + } return nil, errors.New("node doesn't have a Node SID") } func (n *LsNode) LoopbackAddr() (netip.Addr, error) { for _, prefix := range n.Prefixes { - if prefix.SidIndex != 0 { - return prefix.Prefix.Addr(), nil + if prefix.Prefix.Addr().Is4() { + if prefix.Prefix.Bits() == 32 { + return prefix.Prefix.Addr(), nil + } + } else if prefix.Prefix.Addr().Is6() { + if prefix.Prefix.Bits() == 128 { + return prefix.Prefix.Addr(), nil + } } } return netip.Addr{}, errors.New("node doesn't have a loopback address") } -func (n *LsNode) UpdateTed(ted *LsTed) { - nodes, asn := ted.Nodes, n.Asn +func (n *LsNode) UpdateTED(ted *LsTED) { + nodes, asn := ted.Nodes, n.ASN if _, ok := nodes[asn]; !ok { nodes[asn] = make(map[string]*LsNode) @@ -127,12 +251,13 @@ func (n *LsNode) AddLink(link *LsLink) { } type LsLink struct { - LocalNode *LsNode // Primary key, in MP_REACH_NLRI Attr - RemoteNode *LsNode // Primary key, in MP_REACH_NLRI Attr - LocalIP netip.Addr // In MP_REACH_NLRI Attr - RemoteIP netip.Addr // In MP_REACH_NLRI Attr - Metrics []*Metric // In BGP-LS Attr - AdjSid uint32 // In BGP-LS Attr + LocalNode *LsNode // Primary key, in MP_REACH_NLRI Attr + RemoteNode *LsNode // Primary key, in MP_REACH_NLRI Attr + LocalIP netip.Addr // In MP_REACH_NLRI Attr + RemoteIP netip.Addr // In MP_REACH_NLRI Attr + Metrics []*Metric // In BGP-LS Attr + AdjSid uint32 // In BGP-LS Attr + Srv6EndXSID *Srv6EndXSID // In BGP-LS Attr } func NewLsLink(localNode *LsNode, remoteNode *LsNode) *LsLink { @@ -152,47 +277,47 @@ func (l *LsLink) Metric(metricType MetricType) (uint32, error) { return 0, fmt.Errorf("metric %s not defined", metricType) } -func (l *LsLink) UpdateTed(ted *LsTed) { - nodes, asn := ted.Nodes, l.LocalNode.Asn +func (l *LsLink) UpdateTED(ted *LsTED) { + nodes, asn := ted.Nodes, l.LocalNode.ASN if _, ok := nodes[asn]; !ok { nodes[asn] = make(map[string]*LsNode) } if _, ok := nodes[asn][l.LocalNode.RouterID]; !ok { - nodes[asn][l.LocalNode.RouterID] = NewLsNode(l.LocalNode.Asn, l.LocalNode.RouterID) + nodes[asn][l.LocalNode.RouterID] = NewLsNode(l.LocalNode.ASN, l.LocalNode.RouterID) } - if _, ok := nodes[l.RemoteNode.Asn][l.RemoteNode.RouterID]; !ok { - nodes[l.RemoteNode.Asn][l.RemoteNode.RouterID] = NewLsNode(l.RemoteNode.Asn, l.RemoteNode.RouterID) + if _, ok := nodes[l.RemoteNode.ASN][l.RemoteNode.RouterID]; !ok { + nodes[l.RemoteNode.ASN][l.RemoteNode.RouterID] = NewLsNode(l.RemoteNode.ASN, l.RemoteNode.RouterID) } - l.LocalNode, l.RemoteNode = nodes[asn][l.LocalNode.RouterID], nodes[l.RemoteNode.Asn][l.RemoteNode.RouterID] + l.LocalNode, l.RemoteNode = nodes[asn][l.LocalNode.RouterID], nodes[l.RemoteNode.ASN][l.RemoteNode.RouterID] l.LocalNode.AddLink(l) } -type LsPrefixV4 struct { +type LsPrefix struct { LocalNode *LsNode // primary key, in MP_REACH_NLRI Attr Prefix netip.Prefix // in MP_REACH_NLRI Attr SidIndex uint32 // in BGP-LS Attr (only for Lo Address Prefix) } -func NewLsPrefixV4(localNode *LsNode) *LsPrefixV4 { - return &LsPrefixV4{ +func NewLsPrefix(localNode *LsNode) *LsPrefix { + return &LsPrefix{ LocalNode: localNode, } } -func (lp *LsPrefixV4) UpdateTed(ted *LsTed) { - nodes, asn := ted.Nodes, lp.LocalNode.Asn +func (lp *LsPrefix) UpdateTED(ted *LsTED) { + nodes, asn := ted.Nodes, lp.LocalNode.ASN if _, ok := nodes[asn]; !ok { nodes[asn] = make(map[string]*LsNode) } if _, ok := nodes[asn][lp.LocalNode.RouterID]; !ok { - nodes[asn][lp.LocalNode.RouterID] = NewLsNode(lp.LocalNode.Asn, lp.LocalNode.RouterID) + nodes[asn][lp.LocalNode.RouterID] = NewLsNode(lp.LocalNode.ASN, lp.LocalNode.RouterID) } localNode := nodes[asn][lp.LocalNode.RouterID] @@ -205,6 +330,53 @@ func (lp *LsPrefixV4) UpdateTed(ted *LsTed) { localNode.Prefixes = append(localNode.Prefixes, lp) } +type SIDStructure struct { + LocalBlock uint8 + LocalNode uint8 + LocalFunc uint8 + LocalArg uint8 +} + +type EndpointBehavior struct { + Behavior uint16 + Flags uint8 + Algorithm uint8 +} + +type LsSrv6SID struct { + LocalNode *LsNode // primary key, in MP_REACH_NLRI Attr + Sids []string // in LsSrv6SID Attr + EndpointBehavior EndpointBehavior // in BGP-LS Attr + SIDStructure SIDStructure // in BGP-LS Attr + MultiTopoIDs []uint32 // in LsSrv6SID Attr +} + +func NewLsSrv6SID(node *LsNode) *LsSrv6SID { + return &LsSrv6SID{ + LocalNode: node, + } +} + +func (s *LsSrv6SID) UpdateTED(ted *LsTED) { + nodes, asn := ted.Nodes, s.LocalNode.ASN + + if _, ok := nodes[asn]; !ok { + nodes[asn] = make(map[string]*LsNode) + } + + if _, ok := nodes[asn][s.LocalNode.RouterID]; !ok { + nodes[asn][s.LocalNode.RouterID] = NewLsNode(s.LocalNode.ASN, s.LocalNode.RouterID) + } + + s.LocalNode = nodes[asn][s.LocalNode.RouterID] + + s.LocalNode.AddSrv6SID(s) +} + +func (n *LsNode) AddSrv6SID(s *LsSrv6SID) { + n.SRv6SIDs = append(n.SRv6SIDs, s) +} + type Metric struct { Type MetricType Value uint32 @@ -220,23 +392,29 @@ func NewMetric(metricType MetricType, value uint32) *Metric { type MetricType int const ( - IGP_METRIC MetricType = iota - TE_METRIC - DELAY_METRIC - HOPCOUNT_METRIC + IGPMetric MetricType = iota + TEMetric + DelayMetric + HopcountMetric ) func (m MetricType) String() string { switch m { - case IGP_METRIC: - return "IGP" - case TE_METRIC: - return "TE" - case DELAY_METRIC: - return "DELAY" - case HOPCOUNT_METRIC: - return "HOPCOUNT" + case IGPMetric: + return "METRIC_TYPE_IGP" + case TEMetric: + return "METRIC_TYPE_TE" + case DelayMetric: + return "METRIC_TYPE_DELAY" + case HopcountMetric: + return "METRIC_TYPE_HOPCOUNT" default: - return "Unknown" + return "METRIC_TYPE_UNSPECIFIED" } } + +type Srv6EndXSID struct { + EndpointBehavior uint16 + Sids []string + Srv6SIDStructure SIDStructure +} diff --git a/internal/pkg/version/version.go b/internal/pkg/version/version.go index 4cf922ea..f88dc4be 100644 --- a/internal/pkg/version/version.go +++ b/internal/pkg/version/version.go @@ -7,10 +7,10 @@ package version import "fmt" -const MAJOR uint = 1 -const MINOR uint = 3 -const PATCH uint = 0 +const Major uint = 1 +const Minor uint = 3 +const Patch uint = 0 func Version() string { - return fmt.Sprintf("%d.%d.%d", MAJOR, MINOR, PATCH) + return fmt.Sprintf("%d.%d.%d", Major, Minor, Patch) } diff --git a/pkg/packet/pcep/capability.go b/pkg/packet/pcep/capability.go index aad3ffd4..3bdc89b2 100644 --- a/pkg/packet/pcep/capability.go +++ b/pkg/packet/pcep/capability.go @@ -14,19 +14,19 @@ func PolaCapability(caps []CapabilityInterface) []CapabilityInterface { polaCaps := []CapabilityInterface{} for _, cap := range caps { switch tlv := cap.(type) { - case *StatefulPceCapability: - tlv = &StatefulPceCapability{ - LspUpdateCapability: true, + case *StatefulPCECapability: + tlv = &StatefulPCECapability{ + LSPUpdateCapability: true, IncludeDBVersion: false, - LspInstantiationCapability: true, + LSPInstantiationCapability: true, TriggeredResync: false, - DeltaLspSyncCapability: false, + DeltaLSPSyncCapability: false, TriggeredInitialSync: false, P2mpCapability: false, - P2mpLspUpdateCapability: false, - P2mpLspInstantiationCapability: false, - LspSchedulingCapability: false, - PdLspCapability: false, + P2mpLSPUpdateCapability: false, + P2mpLSPInstantiationCapability: false, + LSPSchedulingCapability: false, + PdLSPCapability: false, ColorCapability: true, PathRecomputationCapability: false, StrictPathCapability: false, diff --git a/pkg/packet/pcep/capability_test.go b/pkg/packet/pcep/capability_test.go new file mode 100644 index 00000000..505acfa9 --- /dev/null +++ b/pkg/packet/pcep/capability_test.go @@ -0,0 +1,97 @@ +// Copyright (c) 2022 NTT Communications Corporation +// +// This software is released under the MIT License. +// see https://github.com/nttcom/pola/blob/main/LICENSE + +package pcep + +import ( + "reflect" + "testing" +) + +func TestPolaCapability(t *testing.T) { + tests := []struct { + name string + input []CapabilityInterface + expected []CapabilityInterface + }{ + { + name: "Basic Capability Test", + input: []CapabilityInterface{ + &StatefulPCECapability{ + LSPUpdateCapability: false, + IncludeDBVersion: true, + LSPInstantiationCapability: false, + TriggeredResync: true, + DeltaLSPSyncCapability: true, + TriggeredInitialSync: true, + }, + &PathSetupTypeCapability{ + PathSetupTypes: Psts{PathSetupTypeRSVPTE, PathSetupTypeSRTE, PathSetupTypeSRv6TE}, + SubTLVs: []TLVInterface{ + &SRPCECapability{ + HasUnlimitedMaxSIDDepth: false, + IsNAISupported: false, + MaximumSidDepth: uint8(16), + }, + }, + }, + &SRPCECapability{ + HasUnlimitedMaxSIDDepth: false, + IsNAISupported: false, + MaximumSidDepth: uint8(16), + }, + &AssocTypeList{ + AssocTypes: []AssocType{AssocTypePathProtectionAssociation, AssocTypeSRPolicyAssociation}, + }, + }, + expected: []CapabilityInterface{ + &StatefulPCECapability{ + LSPUpdateCapability: true, + IncludeDBVersion: false, + LSPInstantiationCapability: true, + TriggeredResync: false, + DeltaLSPSyncCapability: false, + TriggeredInitialSync: false, + P2mpCapability: false, + P2mpLSPUpdateCapability: false, + P2mpLSPInstantiationCapability: false, + LSPSchedulingCapability: false, + PdLSPCapability: false, + ColorCapability: true, + PathRecomputationCapability: false, + StrictPathCapability: false, + Relax: false, + }, + &PathSetupTypeCapability{ + PathSetupTypes: Psts{PathSetupTypeRSVPTE, PathSetupTypeSRTE, PathSetupTypeSRv6TE}, + SubTLVs: []TLVInterface{ + &SRPCECapability{ + HasUnlimitedMaxSIDDepth: false, + IsNAISupported: false, + MaximumSidDepth: uint8(16), + }, + }, + }, + &SRPCECapability{ + HasUnlimitedMaxSIDDepth: false, + IsNAISupported: false, + MaximumSidDepth: uint8(16), + }, + &AssocTypeList{ + AssocTypes: []AssocType{AssocTypePathProtectionAssociation, AssocTypeSRPolicyAssociation}, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := PolaCapability(tt.input) + if !reflect.DeepEqual(result, tt.expected) { + t.Fatalf("%s: expected %+v, got %+v", tt.name, tt.expected, result) + } + }) + } +} diff --git a/pkg/packet/pcep/message.go b/pkg/packet/pcep/message.go index 21efd114..55269972 100644 --- a/pkg/packet/pcep/message.go +++ b/pkg/packet/pcep/message.go @@ -14,37 +14,72 @@ import ( "github.com/nttcom/pola/internal/pkg/table" ) -const COMMON_HEADER_LENGTH uint16 = 4 - -const ( // PCEP Message-Type (1byte) - MT_RESERVED uint8 = 0x00 // RFC5440 - MT_OPEN uint8 = 0x01 // RFC5440 - MT_KEEPALIVE uint8 = 0x02 // RFC5440 - MT_PCREQ uint8 = 0x03 // RFC5440 - MT_PCREP uint8 = 0x04 // RFC5440 - MT_NOTIFICATION uint8 = 0x05 // RFC5440 - MT_ERROR uint8 = 0x06 // RFC5440 - MT_CLOSE uint8 = 0x07 // RFC5440 - MT_PCMONREQ uint8 = 0x08 // RFC5886 - MT_PCMONREP uint8 = 0x09 // RFC5886 - MT_REPORT uint8 = 0x0a // RFC8231 - MT_UPDATE uint8 = 0x0b // RFC8281 - MT_LSPINITREQ uint8 = 0x0c // RFC8281 - MT_STARTTLS uint8 = 0x0d // RFC8253 +const CommonHeaderLength uint16 = 4 + +// PCEP Message-Type (1 byte) +type MessageType uint8 + +const ( + MessageTypeOpen MessageType = 0x01 + MessageTypeKeepalive MessageType = 0x02 + MessageTypePcreq MessageType = 0x03 + MessageTypePcrep MessageType = 0x04 + MessageTypeNotification MessageType = 0x05 + MessageTypeError MessageType = 0x06 + MessageTypeClose MessageType = 0x07 + MessageTypePcmReq MessageType = 0x08 + MessageTypePcmRep MessageType = 0x09 + MessageTypeReport MessageType = 0x0a + MessageTypeUpdate MessageType = 0x0b + MessageTypeLSPInitReq MessageType = 0x0c + MessageTypeStartTLS MessageType = 0x0d ) +var messageTypeDescriptions = map[MessageType]struct { + Description string + Reference string +}{ + MessageTypeOpen: {"Open", "RFC5440"}, + MessageTypeKeepalive: {"Keepalive", "RFC5440"}, + MessageTypePcreq: {"Path Computation Request", "RFC5440"}, + MessageTypePcrep: {"Path Computation Reply", "RFC5440"}, + MessageTypeNotification: {"Notification", "RFC5440"}, + MessageTypeError: {"Error", "RFC5440"}, + MessageTypeClose: {"Close", "RFC5440"}, + MessageTypePcmReq: {"Path Computation Monitoring Request", "RFC5886"}, + MessageTypePcmRep: {"Path Computation Monitoring Reply", "RFC5886"}, + MessageTypeReport: {"Report", "RFC8231"}, + MessageTypeUpdate: {"Update", "RFC8281"}, + MessageTypeLSPInitReq: {"LSP Initiate Request", "RFC8281"}, + MessageTypeStartTLS: {"StartTLS", "RFC8253"}, +} + +func (t MessageType) String() string { + if desc, ok := messageTypeDescriptions[t]; ok { + return fmt.Sprintf("%s (0x%02x)", desc.Description, uint8(t)) + } + return fmt.Sprintf("Unknown MessageType (0x%02x)", uint8(t)) +} + +func (t MessageType) StringWithReference() string { + if desc, ok := messageTypeDescriptions[t]; ok { + return fmt.Sprintf("%s (0x%02x) [%s]", desc.Description, uint8(t), desc.Reference) + } + return fmt.Sprintf("Unknown MessageType (0x%02x)", uint8(t)) +} + // Common header of PCEP Message type CommonHeader struct { // RFC5440 6.1 Version uint8 // Current version is 1 Flag uint8 - MessageType uint8 + MessageType MessageType MessageLength uint16 } func (h *CommonHeader) DecodeFromBytes(header []uint8) error { h.Version = uint8(header[0] >> 5) h.Flag = uint8(header[0] & 0x1f) - h.MessageType = uint8(header[1]) + h.MessageType = MessageType(header[1]) h.MessageLength = binary.BigEndian.Uint16(header[2:4]) return nil } @@ -53,14 +88,12 @@ func (h *CommonHeader) Serialize() []uint8 { buf := make([]uint8, 0, 4) verFlag := uint8(h.Version<<5 | h.Flag) buf = append(buf, verFlag) - buf = append(buf, h.MessageType) - messageLength := make([]uint8, 2) - binary.BigEndian.PutUint16(messageLength, h.MessageLength) - buf = append(buf, messageLength...) + buf = append(buf, uint8(h.MessageType)) + buf = append(buf, Uint16ToByteSlice(h.MessageLength)...) return buf } -func NewCommonHeader(messageType uint8, messageLength uint16) *CommonHeader { +func NewCommonHeader(messageType MessageType, messageLength uint16) *CommonHeader { h := &CommonHeader{ Version: uint8(1), Flag: uint8(0), @@ -82,20 +115,19 @@ type OpenMessage struct { func (m *OpenMessage) DecodeFromBytes(messageBody []uint8) error { var commonObjectHeader CommonObjectHeader if err := commonObjectHeader.DecodeFromBytes(messageBody); err != nil { - return err + return fmt.Errorf("failed to decode common object header: %w", err) } - if commonObjectHeader.ObjectClass != OC_OPEN { + if commonObjectHeader.ObjectClass != ObjectClassOpen { return fmt.Errorf("unsupported ObjectClass: %d", commonObjectHeader.ObjectClass) } - if commonObjectHeader.ObjectType != OT_OPEN_OPEN { + if commonObjectHeader.ObjectType != ObjectTypeOpenOpen { return fmt.Errorf("unsupported ObjectType: %d", commonObjectHeader.ObjectType) } openObject := &OpenObject{} - err := openObject.DecodeFromBytes(commonObjectHeader.ObjectType, messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]) - if err != nil { - return err + if err := openObject.DecodeFromBytes(commonObjectHeader.ObjectType, messageBody[commonObjectHeaderLength:commonObjectHeader.ObjectLength]); err != nil { + return fmt.Errorf("failed to decode OpenObject: %w", err) } m.OpenObject = openObject @@ -104,8 +136,8 @@ func (m *OpenMessage) DecodeFromBytes(messageBody []uint8) error { func (m *OpenMessage) Serialize() ([]uint8, error) { byteOpenObject := m.OpenObject.Serialize() - openMessageLength := COMMON_HEADER_LENGTH + m.OpenObject.Len() - openHeader := NewCommonHeader(MT_OPEN, openMessageLength) + openMessageLength := CommonHeaderLength + m.OpenObject.Len() + openHeader := NewCommonHeader(MessageTypeOpen, openMessageLength) byteOpenHeader := openHeader.Serialize() byteOpenMessage := AppendByteSlices(byteOpenHeader, byteOpenObject) return byteOpenMessage, nil @@ -127,8 +159,8 @@ type KeepaliveMessage struct { } func (m *KeepaliveMessage) Serialize() ([]uint8, error) { - keepaliveMessageLength := COMMON_HEADER_LENGTH - keepaliveHeader := NewCommonHeader(MT_KEEPALIVE, keepaliveMessageLength) + keepaliveMessageLength := CommonHeaderLength + keepaliveHeader := NewCommonHeader(MessageTypeKeepalive, keepaliveMessageLength) byteKeepaliveHeader := keepaliveHeader.Serialize() byteKeepaliveMessage := byteKeepaliveHeader return byteKeepaliveMessage, nil @@ -141,7 +173,7 @@ func NewKeepaliveMessage() (*KeepaliveMessage, error) { // PCErr Message type PCErrMessage struct { - PcepErrorObject *PcepErrorObject + PCEPErrorObject *PCEPErrorObject } func (m *PCErrMessage) DecodeFromBytes(messageBody []uint8) error { @@ -149,30 +181,30 @@ func (m *PCErrMessage) DecodeFromBytes(messageBody []uint8) error { if err := commonObjectHeader.DecodeFromBytes(messageBody); err != nil { return err } - pcepErrorObject := &PcepErrorObject{} - if err := pcepErrorObject.DecodeFromBytes(commonObjectHeader.ObjectType, messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil { + pcepErrorObject := &PCEPErrorObject{} + if err := pcepErrorObject.DecodeFromBytes(commonObjectHeader.ObjectType, messageBody[commonObjectHeaderLength:commonObjectHeader.ObjectLength]); err != nil { return err } - m.PcepErrorObject = pcepErrorObject + m.PCEPErrorObject = pcepErrorObject return nil } func (m *PCErrMessage) Serialize() []uint8 { - pcerrMessageLength := COMMON_HEADER_LENGTH + m.PcepErrorObject.Len() - pcerrHeader := NewCommonHeader(MT_ERROR, pcerrMessageLength) + pcerrMessageLength := CommonHeaderLength + m.PCEPErrorObject.Len() + pcerrHeader := NewCommonHeader(MessageTypeError, pcerrMessageLength) bytePCErrHeader := pcerrHeader.Serialize() - bytePcepErrorObject := m.PcepErrorObject.Serialize() - bytePCErrMessage := AppendByteSlices(bytePCErrHeader, bytePcepErrorObject) + bytePCEPErrorObject := m.PCEPErrorObject.Serialize() + bytePCErrMessage := AppendByteSlices(bytePCErrHeader, bytePCEPErrorObject) return bytePCErrMessage } func NewPCErrMessage(errorType uint8, errorValue uint8, tlvs []TLVInterface) (*PCErrMessage, error) { - o, err := NewPcepErrorObject(errorType, errorValue, tlvs) + o, err := NewPCEPErrorObject(errorType, errorValue, tlvs) if err != nil { return nil, err } m := &PCErrMessage{ - PcepErrorObject: o, + PCEPErrorObject: o, } return m, nil } @@ -188,7 +220,7 @@ func (m *CloseMessage) DecodeFromBytes(messageBody []uint8) error { return err } closeObject := &CloseObject{} - if err := closeObject.DecodeFromBytes(commonObjectHeader.ObjectType, messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil { + if err := closeObject.DecodeFromBytes(commonObjectHeader.ObjectType, messageBody[commonObjectHeaderLength:commonObjectHeader.ObjectLength]); err != nil { return err } m.CloseObject = closeObject @@ -196,15 +228,15 @@ func (m *CloseMessage) DecodeFromBytes(messageBody []uint8) error { } func (m *CloseMessage) Serialize() []uint8 { - closeMessageLength := COMMON_HEADER_LENGTH + m.CloseObject.Len() - closeHeader := NewCommonHeader(MT_CLOSE, closeMessageLength) + closeMessageLength := CommonHeaderLength + m.CloseObject.Len() + closeHeader := NewCommonHeader(MessageTypeClose, closeMessageLength) byteCloseHeader := closeHeader.Serialize() byteCloseObject := m.CloseObject.Serialize() byteCloseMessage := AppendByteSlices(byteCloseHeader, byteCloseObject) return byteCloseMessage } -func NewCloseMessage(reason uint8) (*CloseMessage, error) { +func NewCloseMessage(reason CloseReason) (*CloseMessage, error) { o, err := NewCloseObject(reason) if err != nil { return nil, err @@ -217,9 +249,9 @@ func NewCloseMessage(reason uint8) (*CloseMessage, error) { type StateReport struct { SrpObject *SrpObject - LspObject *LspObject + LSPObject *LSPObject EroObject *EroObject - LspaObject *LspaObject + LSPAObject *LSPAObject MetricObjects []*MetricObject BandwidthObjects []*BandwidthObject AssociationObject *AssociationObject @@ -229,9 +261,9 @@ type StateReport struct { func NewStateReport() (*StateReport, error) { sr := &StateReport{ SrpObject: &SrpObject{}, - LspObject: &LspObject{}, + LSPObject: &LSPObject{}, EroObject: &EroObject{}, - LspaObject: &LspaObject{}, + LSPAObject: &LSPAObject{}, MetricObjects: []*MetricObject{}, BandwidthObjects: []*BandwidthObject{}, AssociationObject: &AssociationObject{}, @@ -240,7 +272,7 @@ func NewStateReport() (*StateReport, error) { return sr, nil } -func (r *StateReport) decodeBandwidthObject(objectType uint8, objectBody []uint8) error { +func (r *StateReport) decodeBandwidthObject(objectType ObjectType, objectBody []uint8) error { bandwidthObject := &BandwidthObject{} if err := bandwidthObject.DecodeFromBytes(objectType, objectBody); err != nil { return err @@ -249,7 +281,7 @@ func (r *StateReport) decodeBandwidthObject(objectType uint8, objectBody []uint8 return nil } -func (r *StateReport) decodeMetricObject(objectType uint8, objectBody []uint8) error { +func (r *StateReport) decodeMetricObject(objectType ObjectType, objectBody []uint8) error { metricObject := &MetricObject{} if err := metricObject.DecodeFromBytes(objectType, objectBody); err != nil { return err @@ -258,19 +290,19 @@ func (r *StateReport) decodeMetricObject(objectType uint8, objectBody []uint8) e return nil } -func (r *StateReport) decodeEroObject(objectType uint8, objectBody []uint8) error { +func (r *StateReport) decodeEroObject(objectType ObjectType, objectBody []uint8) error { return r.EroObject.DecodeFromBytes(objectType, objectBody) } -func (r *StateReport) decodeLspaObject(objectType uint8, objectBody []uint8) error { - return r.LspaObject.DecodeFromBytes(objectType, objectBody) +func (r *StateReport) decodeLSPAObject(objectType ObjectType, objectBody []uint8) error { + return r.LSPAObject.DecodeFromBytes(objectType, objectBody) } -func (r *StateReport) decodeLspObject(objectType uint8, objectBody []uint8) error { - return r.LspObject.DecodeFromBytes(objectType, objectBody) +func (r *StateReport) decodeLSPObject(objectType ObjectType, objectBody []uint8) error { + return r.LSPObject.DecodeFromBytes(objectType, objectBody) } -func (r *StateReport) decodeSrpObject(objectType uint8, objectBody []uint8) error { +func (r *StateReport) decodeSrpObject(objectType ObjectType, objectBody []uint8) error { srpObject := &SrpObject{} if err := srpObject.DecodeFromBytes(objectType, objectBody); err != nil { return err @@ -279,11 +311,11 @@ func (r *StateReport) decodeSrpObject(objectType uint8, objectBody []uint8) erro return nil } -func (r *StateReport) decodeAssociationObject(objectType uint8, objectBody []uint8) error { +func (r *StateReport) decodeAssociationObject(objectType ObjectType, objectBody []uint8) error { return r.AssociationObject.DecodeFromBytes(objectType, objectBody) } -func (r *StateReport) decodeVendorInformationObject(objectType uint8, objectBody []uint8) error { +func (r *StateReport) decodeVendorInformationObject(objectType ObjectType, objectBody []uint8) error { return r.VendorInformationObject.DecodeFromBytes(objectType, objectBody) } @@ -292,20 +324,20 @@ type PCRptMessage struct { StateReports []*StateReport } -var decodeFuncs = map[uint8]func(*StateReport, uint8, []uint8) error{ - OC_BANDWIDTH: (*StateReport).decodeBandwidthObject, - OC_METRIC: (*StateReport).decodeMetricObject, - OC_ERO: (*StateReport).decodeEroObject, - OC_LSPA: (*StateReport).decodeLspaObject, - OC_LSP: (*StateReport).decodeLspObject, - OC_SRP: (*StateReport).decodeSrpObject, - OC_ASSOCIATION: (*StateReport).decodeAssociationObject, - OC_VENDOR_INFORMATION: (*StateReport).decodeVendorInformationObject, +var decodeFuncs = map[ObjectClass]func(*StateReport, ObjectType, []uint8) error{ + ObjectClassBandwidth: (*StateReport).decodeBandwidthObject, + ObjectClassMetric: (*StateReport).decodeMetricObject, + ObjectClassERO: (*StateReport).decodeEroObject, + ObjectClassLSPA: (*StateReport).decodeLSPAObject, + ObjectClassLSP: (*StateReport).decodeLSPObject, + ObjectClassSRP: (*StateReport).decodeSrpObject, + ObjectClassAssociation: (*StateReport).decodeAssociationObject, + ObjectClassVendorInformation: (*StateReport).decodeVendorInformationObject, } func (m *PCRptMessage) DecodeFromBytes(messageBody []uint8) error { - // previousOC: To determine the delimitation of StateReports from the order of object classes - var previousOC uint8 + // previousObjectClass: To track the object class and handle the delimitation of StateReports + var previousObjectClass ObjectClass var sr *StateReport for len(messageBody) > 0 { var commonObjectHeader CommonObjectHeader @@ -314,30 +346,31 @@ func (m *PCRptMessage) DecodeFromBytes(messageBody []uint8) error { } decodeFunc, ok := decodeFuncs[commonObjectHeader.ObjectClass] if !ok { - // Skip if object class not registered in decodeFunc + // Skip the current object if the object class is not registered in decodeFuncs messageBody = messageBody[commonObjectHeader.ObjectLength:] continue } - if (previousOC != OC_SRP && commonObjectHeader.ObjectClass == OC_LSP) || commonObjectHeader.ObjectClass == OC_SRP { - // If sr is not zero value, this StateReport is already updated. - var err error + if (previousObjectClass != ObjectClassSRP && commonObjectHeader.ObjectClass == ObjectClassLSP) || commonObjectHeader.ObjectClass == ObjectClassSRP { if sr != nil { m.StateReports = append(m.StateReports, sr) } + + var err error sr, err = NewStateReport() if err != nil { return err } } - if err := decodeFunc(sr, commonObjectHeader.ObjectType, messageBody[COMMON_OBJECT_HEADER_LENGTH:commonObjectHeader.ObjectLength]); err != nil { + if err := decodeFunc(sr, commonObjectHeader.ObjectType, messageBody[commonObjectHeaderLength:commonObjectHeader.ObjectLength]); err != nil { return err } - previousOC = commonObjectHeader.ObjectClass + previousObjectClass = commonObjectHeader.ObjectClass messageBody = messageBody[commonObjectHeader.ObjectLength:] } if sr != nil { m.StateReports = append(m.StateReports, sr) } + return nil } @@ -350,7 +383,7 @@ func NewPCRptMessage() *PCRptMessage { // PCInitiate Message type PCInitiateMessage struct { SrpObject *SrpObject - LspObject *LspObject + LSPObject *LSPObject EndpointsObject *EndpointsObject EroObject *EroObject AssociationObject *AssociationObject @@ -374,14 +407,14 @@ func (m *PCInitiateMessage) Serialize() ([]uint8, error) { return nil, err } } - pcinitiateMessageLength := COMMON_HEADER_LENGTH + + pcinitiateMessageLength := CommonHeaderLength + m.SrpObject.Len() + - m.LspObject.Len() + + m.LSPObject.Len() + endpointsObjectLength + eroObjectLength byteSrpObject := m.SrpObject.Serialize() - byteLspObject := m.LspObject.Serialize() + byteLSPObject := m.LSPObject.Serialize() byteEndpointsObject := []uint8{} if m.EndpointsObject != nil { @@ -417,17 +450,17 @@ func (m *PCInitiateMessage) Serialize() ([]uint8, error) { pcinitiateMessageLength += m.VendorInformationObject.Len() } - pcinitiateHeader := NewCommonHeader(MT_LSPINITREQ, pcinitiateMessageLength) + pcinitiateHeader := NewCommonHeader(MessageTypeLSPInitReq, pcinitiateMessageLength) bytePCInitiateHeader := pcinitiateHeader.Serialize() bytePCInitiateMessage := AppendByteSlices( - bytePCInitiateHeader, byteSrpObject, byteLspObject, byteEndpointsObject, byteEroObject, byteAssociationObject, byteVendorInformationObject, + bytePCInitiateHeader, byteSrpObject, byteLSPObject, byteEndpointsObject, byteEroObject, byteAssociationObject, byteVendorInformationObject, ) return bytePCInitiateMessage, nil } func NewPCInitiateMessage(srpID uint32, lspName string, lspDelete bool, plspID uint32, segmentList []table.Segment, color uint32, preference uint32, srcAddr netip.Addr, dstAddr netip.Addr, opt ...Opt) (*PCInitiateMessage, error) { opts := optParams{ - pccType: RFC_COMPLIANT, + pccType: RFCCompliant, } for _, o := range opt { @@ -436,21 +469,21 @@ func NewPCInitiateMessage(srpID uint32, lspName string, lspDelete bool, plspID u m := &PCInitiateMessage{} var err error + if m.SrpObject, err = NewSrpObject(segmentList, srpID, lspDelete); err != nil { return nil, err } if lspDelete { - if m.LspObject, err = NewLspObject(lspName, &color, plspID); err != nil { + if m.LSPObject, err = NewLSPObject(lspName, &color, plspID); err != nil { return nil, err } return m, nil - } else { - if m.LspObject, err = NewLspObject(lspName, &color, 0); err != nil { - return nil, err - } } + if m.LSPObject, err = NewLSPObject(lspName, &color, 0); err != nil { + return nil, err + } if m.EndpointsObject, err = NewEndpointsObject(dstAddr, srcAddr); err != nil { return nil, err } @@ -459,20 +492,20 @@ func NewPCInitiateMessage(srpID uint32, lspName string, lspDelete bool, plspID u } switch opts.pccType { - case JUNIPER_LEGACY: + case JuniperLegacy: if m.AssociationObject, err = NewAssociationObject(srcAddr, dstAddr, color, preference, VendorSpecific(opts.pccType)); err != nil { return nil, err } - case CISCO_LEGACY: - if m.VendorInformationObject, err = NewVendorInformationObject(CISCO_LEGACY, color, preference); err != nil { + case CiscoLegacy: + if m.VendorInformationObject, err = NewVendorInformationObject(CiscoLegacy, color, preference); err != nil { return nil, err } - case RFC_COMPLIANT: + case RFCCompliant: if m.AssociationObject, err = NewAssociationObject(srcAddr, dstAddr, color, preference); err != nil { return nil, err } // FRRouting is considered RFC compliant - if m.VendorInformationObject, err = NewVendorInformationObject(CISCO_LEGACY, color, preference); err != nil { + if m.VendorInformationObject, err = NewVendorInformationObject(CiscoLegacy, color, preference); err != nil { return nil, err } default: @@ -485,13 +518,13 @@ func NewPCInitiateMessage(srpID uint32, lspName string, lspDelete bool, plspID u // PCUpdate Message type PCUpdMessage struct { SrpObject *SrpObject - LspObject *LspObject + LSPObject *LSPObject EroObject *EroObject } func (m *PCUpdMessage) Serialize() ([]uint8, error) { byteSrpObject := m.SrpObject.Serialize() - byteLspObject := m.LspObject.Serialize() + byteLSPObject := m.LSPObject.Serialize() byteEroObject, err := m.EroObject.Serialize() if err != nil { return nil, err @@ -501,10 +534,10 @@ func (m *PCUpdMessage) Serialize() ([]uint8, error) { if err != nil { return nil, err } - pcupdMessageLength := COMMON_HEADER_LENGTH + m.SrpObject.Len() + m.LspObject.Len() + eroObjectLength - pcupdHeader := NewCommonHeader(MT_UPDATE, pcupdMessageLength) + pcupdMessageLength := CommonHeaderLength + m.SrpObject.Len() + m.LSPObject.Len() + eroObjectLength + pcupdHeader := NewCommonHeader(MessageTypeUpdate, pcupdMessageLength) bytePCUpdHeader := pcupdHeader.Serialize() - bytePCUpdMessage := AppendByteSlices(bytePCUpdHeader, byteSrpObject, byteLspObject, byteEroObject) + bytePCUpdMessage := AppendByteSlices(bytePCUpdHeader, byteSrpObject, byteLSPObject, byteEroObject) return bytePCUpdMessage, err } @@ -515,7 +548,7 @@ func NewPCUpdMessage(srpID uint32, lspName string, plspID uint32, segmentList [] if m.SrpObject, err = NewSrpObject(segmentList, srpID, false); err != nil { return nil, err } - if m.LspObject, err = NewLspObject(lspName, nil, plspID); err != nil { + if m.LSPObject, err = NewLSPObject(lspName, nil, plspID); err != nil { return nil, err } if m.EroObject, err = NewEroObject(segmentList); err != nil { diff --git a/pkg/packet/pcep/object.go b/pkg/packet/pcep/object.go index ea6e9e43..b78bec49 100644 --- a/pkg/packet/pcep/object.go +++ b/pkg/packet/pcep/object.go @@ -8,6 +8,7 @@ package pcep import ( "encoding/binary" "errors" + "fmt" "math" "net/netip" @@ -16,119 +17,173 @@ import ( type PccType int +const commonObjectHeaderLength uint16 = 4 + +// PCEP Object-Class (1 byte) Ref: https://www.iana.org/assignments/pcep/pcep.xhtml#pcep-objects +type ObjectClass uint8 +type ObjectType uint8 +type SubObjectType uint8 + const ( - CISCO_LEGACY PccType = iota - JUNIPER_LEGACY - RFC_COMPLIANT + ObjectClassOpen ObjectClass = 0x01 + ObjectClassRP ObjectClass = 0x02 + ObjectClassNoPath ObjectClass = 0x03 + ObjectClassEndpoints ObjectClass = 0x04 + ObjectClassBandwidth ObjectClass = 0x05 + ObjectClassMetric ObjectClass = 0x06 + ObjectClassERO ObjectClass = 0x07 + ObjectClassRRO ObjectClass = 0x08 + ObjectClassLSPA ObjectClass = 0x09 + ObjectClassIRO ObjectClass = 0x0a + ObjectClassSVEC ObjectClass = 0x0b + ObjectClassNotification ObjectClass = 0x0c + ObjectClassPCEPError ObjectClass = 0x0d + ObjectClassLoadBalancing ObjectClass = 0x0e + ObjectClassClose ObjectClass = 0x0f + ObjectClassPathKey ObjectClass = 0x10 + ObjectClassXRO ObjectClass = 0x11 + ObjectClassMonitoring ObjectClass = 0x13 + ObjectClassPCCReqID ObjectClass = 0x14 + ObjectClassOF ObjectClass = 0x15 + ObjectClassClassType ObjectClass = 0x16 + ObjectClassGlobalConstraints ObjectClass = 0x18 + ObjectClassPCEID ObjectClass = 0x19 + ObjectClassProcTime ObjectClass = 0x1a + ObjectClassOverload ObjectClass = 0x1b + ObjectClassUnreachDestination ObjectClass = 0x1c + ObjectClassSERO ObjectClass = 0x1d + ObjectClassSRRO ObjectClass = 0x1e + ObjectClassBNC ObjectClass = 0x1f + ObjectClassLSP ObjectClass = 0x20 + ObjectClassSRP ObjectClass = 0x21 + ObjectClassVendorInformation ObjectClass = 0x22 + ObjectClassBU ObjectClass = 0x23 + ObjectClassInterLayer ObjectClass = 0x24 + ObjectClassSwitchLayer ObjectClass = 0x25 + ObjectClassReqAdapCap ObjectClass = 0x26 + ObjectClassServerIndication ObjectClass = 0x27 + ObjectClassAssociation ObjectClass = 0x28 + ObjectClassS2LS ObjectClass = 0x29 + ObjectClassWA ObjectClass = 0x2a + ObjectClassFlowSpec ObjectClass = 0x2b + ObjectClassCCIObjectType ObjectClass = 0x2c + ObjectClassPathAttrib ObjectClass = 0x2d + ObjectClassBGPPeerInfoObjectType ObjectClass = 0x2e + ObjectClassExplicitPeerRouteObjectType ObjectClass = 0x2f + ObjectClassPeerPrefixAdvertisementObjectType ObjectClass = 0x30 ) -// Determine PCC type from capability -func DeterminePccType(caps []CapabilityInterface) (pccType PccType) { - pccType = RFC_COMPLIANT - for _, cap := range caps { - if t, ok := cap.(*AssocTypeList); ok { - for _, v := range t.AssocTypes { - if v == AssocType(20) { // Cisco specific Assoc-Type - pccType = CISCO_LEGACY - } else if v == AssocType(65505) { // Juniper specific Assoc-Type - pccType = JUNIPER_LEGACY - break - } - } - } - } - return +var objectClassDescriptions = map[ObjectClass]struct { + Description string + Reference string +}{ + ObjectClassOpen: {"Open", "RFC5440"}, + ObjectClassRP: {"RP", "RFC5440"}, + ObjectClassNoPath: {"NO-PATH", "RFC5440"}, + ObjectClassEndpoints: {"END-POINTS", "RFC5440"}, + ObjectClassBandwidth: {"BANDWIDTH", "RFC5440"}, + ObjectClassMetric: {"METRIC", "RFC5440"}, + ObjectClassERO: {"ERO", "RFC5440"}, + ObjectClassRRO: {"RRO", "RFC5440"}, + ObjectClassLSPA: {"LSPA", "RFC5440"}, + ObjectClassIRO: {"IRO", "RFC5440"}, + ObjectClassSVEC: {"SVEC", "RFC5440"}, + ObjectClassNotification: {"NOTIFICATION", "RFC5440"}, + ObjectClassPCEPError: {"PCEP-ERROR", "RFC5440"}, + ObjectClassLoadBalancing: {"LOAD-BALANCING", "RFC5440"}, + ObjectClassClose: {"CLOSE", "RFC5440"}, + ObjectClassPathKey: {"PATH-KEY", "RFC5520"}, + ObjectClassXRO: {"XRO", "RFC5521"}, + ObjectClassMonitoring: {"MONITORING", "RFC5886"}, + ObjectClassPCCReqID: {"PCC-REQ-ID", "RFC5886"}, + ObjectClassOF: {"OF", "RFC5541"}, + ObjectClassClassType: {"CLASSTYPE", "RFC5455"}, + ObjectClassGlobalConstraints: {"GLOBAL-CONSTRAINTS", "RFC5557"}, + ObjectClassPCEID: {"PCE-ID", "RFC5886"}, + ObjectClassProcTime: {"PROC-TIME", "RFC5886"}, + ObjectClassOverload: {"OVERLOAD", "RFC5886"}, + ObjectClassUnreachDestination: {"UNREACH-DESTINATION", "RFC8306"}, + ObjectClassSERO: {"SERO", "RFC8306"}, + ObjectClassSRRO: {"SRRO", "RFC8306"}, + ObjectClassBNC: {"BNC", "RFC8306"}, + ObjectClassLSP: {"LSP", "RFC8231"}, + ObjectClassSRP: {"SRP", "RFC8231"}, + ObjectClassVendorInformation: {"VENDOR-INFORMATION", "RFC7470"}, + ObjectClassBU: {"BU", "RFC8233"}, + ObjectClassInterLayer: {"INTER-LAYER", "RFC8282"}, + ObjectClassSwitchLayer: {"SWITCH-LAYER", "RFC8282"}, + ObjectClassReqAdapCap: {"REQ-ADAP-CAP", "RFC8282"}, + ObjectClassServerIndication: {"SERVER-INDICATION", "RFC8282"}, + ObjectClassAssociation: {"ASSOCIATION", "RFC8697"}, + ObjectClassS2LS: {"S2LS", "RFC8623"}, + ObjectClassWA: {"WA", "RFC8780"}, + ObjectClassFlowSpec: {"FLOWSPEC", "RFC9168"}, + ObjectClassCCIObjectType: {"CCI", "RFC9050"}, + ObjectClassPathAttrib: {"PATH-ATTRIB", "draft-ietf-pce-multipath-07"}, + ObjectClassBGPPeerInfoObjectType: {"BGP-PEER-INFO", "RFC9757"}, + ObjectClassExplicitPeerRouteObjectType: {"EXPLICIT-PEER-ROUTE", "RFC9757"}, + ObjectClassPeerPrefixAdvertisementObjectType: {"PEER-PREFIX-ADVERTISEMENT", "RFC9757"}, +} + +func (c ObjectClass) String() string { + if desc, ok := objectClassDescriptions[c]; ok { + return fmt.Sprintf("%s (0x%02x)", desc.Description, uint8(c)) + } + return fmt.Sprintf("Unknown Object Class (0x%02x)", uint8(c)) +} + +func (c ObjectClass) StringWithReference() string { + if desc, ok := objectClassDescriptions[c]; ok { + return fmt.Sprintf("%s (0x%02x) [%s]", desc.Description, c, desc.Reference) + } + return fmt.Sprintf("Unknown Object Class (0x%02x)", uint8(c)) } -const COMMON_OBJECT_HEADER_LENGTH uint16 = 4 - -const ( // PCEP Object-Class (1 byte) Ref: https://www.iana.org/assignments/pcep/pcep.xhtml#pcep-objects - OC_RESERVED uint8 = 0x00 // RFC5440 - OC_OPEN uint8 = 0x01 // RFC5440 - OC_RP uint8 = 0x02 // RFC5440 - OC_NO_PATH uint8 = 0x03 // RFC5440 - OC_END_POINTS uint8 = 0x04 // RFC5440 - OC_BANDWIDTH uint8 = 0x05 // RFC5440 - OC_METRIC uint8 = 0x06 // RFC5440 - OC_ERO uint8 = 0x07 // RFC5440 - OC_RRO uint8 = 0x08 // RFC5440 - OC_LSPA uint8 = 0x09 // RFC5440 - OC_IRO uint8 = 0x0a // RFC5440 - OC_SVRC uint8 = 0x0b // RFC5440 - OC_NOTIFICATION uint8 = 0x0c // RFC5440 - OC_PCEP_ERROR uint8 = 0x0d // RFC5440 - OC_LOAD_BALANCING uint8 = 0x0e // RFC5440 - OC_CLOSE uint8 = 0x0f // RFC5440 - OC_PATH_KEY uint8 = 0x10 // RFC5520 - OC_XRO uint8 = 0x11 // RFC5521 - OC_MONITORING uint8 = 0x13 // RFC5886 - OC_PCC_REQ_ID uint8 = 0x14 // RFC5886 - OC_OF uint8 = 0x15 // RFC5541 - OC_CLASSTYPE uint8 = 0x16 // RFC5455 - OC_GLOBAL_CONSTRAINTS uint8 = 0x18 // RFC5557 - OC_PCE_ID uint8 = 0x19 // RFC5886 - OC_PROC_TIME uint8 = 0x1a // RFC5886 - OC_OVERLOAD uint8 = 0x1b // RFC5886 - OC_UNREACH_DESTINATION uint8 = 0x1c // RFC8306 - OC_SERO uint8 = 0x1d // RFC8306 - OC_SRRO uint8 = 0x1e // RFC8306 - OC_BNC uint8 = 0x1f // RFC8306 - OC_LSP uint8 = 0x20 // RFC8231 - OC_SRP uint8 = 0x21 // RFC8231 - OC_VENDOR_INFORMATION uint8 = 0x22 // RFC7470 - OC_BU uint8 = 0x23 // RFC8233 - OC_INTER_LAYER uint8 = 0x24 // RFC8282 - OC_SWITCH_LAYER uint8 = 0x25 // RFC8282 - OC_REQ_ADAP_CAP uint8 = 0x26 // RFC8282 - OC_SERVER_INDICATION uint8 = 0x27 // RFC8282 - OC_ASSOCIATION uint8 = 0x28 // RFC8697 - OC_S2LS uint8 = 0x29 // RFC8623 - OC_WA uint8 = 0x2a // RFC8780 - OC_FLOWSPEC uint8 = 0x2b // RFC9168 - OC_CCI_OBJECT_TYPE uint8 = 0x2c // RFC9050 - OC_PATH_ATTRIB uint8 = 0x2d // draft-ietf-pce-multipath-07 - OC_BGP_PEER_INFO_OBJECT_TYPE uint8 = 0x2c // RFC9757 - OC_EXPLICIT_PEER_ROUTE_OBJECT_TYPE uint8 = 0x2d // RFC9757 - OC_PEER_PREFIX_ADVERTISEMENT_OBJECT_TYPE uint8 = 0x2e // RFC9757 -) - type CommonObjectHeader struct { // RFC5440 7.2 - ObjectClass uint8 - ObjectType uint8 + ObjectClass ObjectClass + ObjectType ObjectType ResFlags uint8 // MUST be set to zero PFlag bool // 0: optional, 1: MUST IFlag bool // 0: processed, 1: ignored ObjectLength uint16 } +const ( + IFlagMask uint8 = 0x01 + PFlagMask uint8 = 0x02 +) + func (h *CommonObjectHeader) DecodeFromBytes(objectHeader []uint8) error { - h.ObjectClass = uint8(objectHeader[0]) - h.ObjectType = uint8(objectHeader[1] & 0xf0 >> 4) - h.ResFlags = uint8(objectHeader[1] & 0x0c >> 2) - h.PFlag = (objectHeader[1] & 0x02) != 0 - h.IFlag = (objectHeader[1] & 0x01) != 0 + if len(objectHeader) < int(commonObjectHeaderLength) { + return fmt.Errorf("object header too short: got %d bytes, need at least %d", len(objectHeader), commonObjectHeaderLength) + + } + + h.ObjectClass = ObjectClass(objectHeader[0]) + h.ObjectType = ObjectType((objectHeader[1] & 0xf0) >> 4) + h.ResFlags = uint8((objectHeader[1] & 0x0c) >> 2) + h.PFlag = (objectHeader[1] & PFlagMask) != 0 + h.IFlag = (objectHeader[1] & IFlagMask) != 0 h.ObjectLength = binary.BigEndian.Uint16(objectHeader[2:4]) return nil } func (h *CommonObjectHeader) Serialize() []uint8 { buf := make([]uint8, 0, 4) - buf = append(buf, h.ObjectClass) - otFlags := uint8(h.ObjectType<<4 | h.ResFlags<<2) + buf = append(buf, uint8(h.ObjectClass)) + Flagbyte := uint8(h.ObjectType)<<4 | uint8(h.ResFlags)<<2 if h.PFlag { - otFlags = otFlags | 0x02 + Flagbyte = Flagbyte | PFlagMask } if h.IFlag { - otFlags = otFlags | 0x01 + Flagbyte = Flagbyte | IFlagMask } - buf = append(buf, otFlags) - objectLength := make([]uint8, 2) - binary.BigEndian.PutUint16(objectLength, h.ObjectLength) - buf = append(buf, objectLength...) + buf = append(buf, Flagbyte) + buf = append(buf, Uint16ToByteSlice(h.ObjectLength)...) return buf } -func NewCommonObjectHeader(objectClass uint8, objectType uint8, messageLength uint16) *CommonObjectHeader { +func NewCommonObjectHeader(objectClass ObjectClass, objectType ObjectType, messageLength uint16) *CommonObjectHeader { h := &CommonObjectHeader{ ObjectClass: objectClass, ObjectType: objectType, @@ -140,25 +195,13 @@ func NewCommonObjectHeader(objectClass uint8, objectType uint8, messageLength ui return h } -type optParams struct { - pccType PccType -} - -type Opt func(*optParams) - -func VendorSpecific(pt PccType) Opt { - return func(op *optParams) { - op.pccType = pt - } -} - // OPEN Object (RFC5440 7.3) const ( - OT_OPEN_OPEN uint8 = 0x01 + ObjectTypeOpenOpen ObjectType = 0x01 ) type OpenObject struct { - ObjectType uint8 + ObjectType ObjectType Version uint8 Flag uint8 Keepalive uint8 @@ -167,7 +210,7 @@ type OpenObject struct { Caps []CapabilityInterface } -func (o *OpenObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *OpenObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.Version = uint8(objectBody[0] >> 5) o.Flag = uint8(objectBody[0] & 0x1f) @@ -188,7 +231,7 @@ func (o *OpenObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { } func (o *OpenObject) Serialize() []uint8 { - openObjectHeader := NewCommonObjectHeader(OC_OPEN, o.ObjectType, o.Len()) + openObjectHeader := NewCommonObjectHeader(ObjectClassOpen, o.ObjectType, o.Len()) byteOpenObjectHeader := openObjectHeader.Serialize() buf := make([]uint8, 4) buf[0] = o.Version << 5 @@ -212,12 +255,12 @@ func (o *OpenObject) Len() uint16 { } // TODO: Calculate TLV length and record in open_object_length // CommonObjectHeader(4byte) + openObject(4byte) + tlvslength(valiable) - return COMMON_OBJECT_HEADER_LENGTH + 4 + tlvsByteLength + return commonObjectHeaderLength + 4 + tlvsByteLength } func NewOpenObject(sessionID uint8, keepalive uint8, capabilities []CapabilityInterface) (*OpenObject, error) { o := &OpenObject{ - ObjectType: OT_OPEN_OPEN, + ObjectType: ObjectTypeOpenOpen, Version: uint8(1), // PCEP version. Current version is 1 Flag: uint8(0), Keepalive: keepalive, @@ -230,26 +273,26 @@ func NewOpenObject(sessionID uint8, keepalive uint8, capabilities []CapabilityIn // BANDWIDTH Object (RFC5440 7.7) type BandwidthObject struct { - ObjectType uint8 + ObjectType ObjectType Bandwidth uint32 } -func (o *BandwidthObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { - o.ObjectType = typ +func (o *BandwidthObject) DecodeFromBytes(objectType ObjectType, objectBody []uint8) error { + o.ObjectType = objectType o.Bandwidth = binary.BigEndian.Uint32(objectBody[:]) return nil } // METRIC Object (RFC5440 7.8) type MetricObject struct { - ObjectType uint8 + ObjectType ObjectType CFlag bool BFlag bool MetricType uint8 MetricValue uint32 } -func (o *MetricObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *MetricObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.CFlag = (objectBody[2] & 0x02) != 0 o.BFlag = (objectBody[2] & 0x01) != 0 @@ -259,7 +302,7 @@ func (o *MetricObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { } func (o *MetricObject) Serialize() []uint8 { - metricObjectHeader := NewCommonObjectHeader(OC_METRIC, o.ObjectType, o.Len()) + metricObjectHeader := NewCommonObjectHeader(ObjectClassMetric, o.ObjectType, o.Len()) byteMetricObjectHeader := metricObjectHeader.Serialize() buf := make([]uint8, 8) @@ -278,12 +321,12 @@ func (o *MetricObject) Serialize() []uint8 { func (o *MetricObject) Len() uint16 { // CommonObjectHeader(4byte) + Flags, SRP-ID(8byte) - return COMMON_OBJECT_HEADER_LENGTH + 8 + return commonObjectHeaderLength + 8 } func NewMetricObject() (*MetricObject, error) { o := &MetricObject{ - ObjectType: uint8(1), + ObjectType: ObjectType(1), MetricType: uint8(2), MetricValue: uint32(30), } @@ -291,8 +334,8 @@ func NewMetricObject() (*MetricObject, error) { } // LSPA Object (RFC5440 7.11) -type LspaObject struct { - ObjectType uint8 +type LSPAObject struct { + ObjectType ObjectType ExcludeAny uint32 IncludeAny uint32 IncludeAll uint32 @@ -301,7 +344,7 @@ type LspaObject struct { LFlag bool } -func (o *LspaObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *LSPAObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.ExcludeAny = binary.BigEndian.Uint32(objectBody[0:4]) o.IncludeAny = binary.BigEndian.Uint32(objectBody[4:8]) @@ -312,9 +355,9 @@ func (o *LspaObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { return nil } -func (o *LspaObject) Serialize() []uint8 { - lspaObjectHeader := NewCommonObjectHeader(OC_LSPA, o.ObjectType, o.Len()) - byteLspaObjectHeader := lspaObjectHeader.Serialize() +func (o *LSPAObject) Serialize() []uint8 { + lspaObjectHeader := NewCommonObjectHeader(ObjectClassLSPA, o.ObjectType, o.Len()) + byteLSPAObjectHeader := lspaObjectHeader.Serialize() buf := make([]uint8, 16) binary.BigEndian.PutUint32(buf[0:4], o.ExcludeAny) @@ -326,18 +369,18 @@ func (o *LspaObject) Serialize() []uint8 { buf[14] = buf[14] | 0x01 } - byteLspaObject := AppendByteSlices(byteLspaObjectHeader, buf) - return byteLspaObject + byteLSPAObject := AppendByteSlices(byteLSPAObjectHeader, buf) + return byteLSPAObject } -func (o *LspaObject) Len() uint16 { +func (o *LSPAObject) Len() uint16 { // CommonObjectHeader(4byte) + Flags, SRP-ID(8byte) - return COMMON_OBJECT_HEADER_LENGTH + 16 + return commonObjectHeaderLength + 16 } -func NewLspaObject() (*LspaObject, error) { - o := &LspaObject{ - ObjectType: uint8(1), +func NewLSPAObject() (*LSPAObject, error) { + o := &LSPAObject{ + ObjectType: ObjectType(1), SetupPriority: uint8(7), HoldingPriority: uint8(7), LFlag: true, @@ -347,17 +390,17 @@ func NewLspaObject() (*LspaObject, error) { // PCEP Error Object (RFC5440 7.15) const ( - OT_ERROR_ERROR uint8 = 0x01 + ObjectTypeErrorError ObjectType = 0x01 ) -type PcepErrorObject struct { - ObjectType uint8 +type PCEPErrorObject struct { + ObjectType ObjectType ErrorType uint8 ErrorValue uint8 Tlvs []TLVInterface } -func (o *PcepErrorObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *PCEPErrorObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.ErrorType = objectBody[2] o.ErrorValue = objectBody[3] @@ -371,30 +414,30 @@ func (o *PcepErrorObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { return nil } -func (o *PcepErrorObject) Serialize() []uint8 { - pcepErrorObjectHeader := NewCommonObjectHeader(OC_PCEP_ERROR, o.ObjectType, o.Len()) - bytePcepErrorObjectHeader := pcepErrorObjectHeader.Serialize() +func (o *PCEPErrorObject) Serialize() []uint8 { + pcepErrorObjectHeader := NewCommonObjectHeader(ObjectClassPCEPError, o.ObjectType, o.Len()) + bytePCEPErrorObjectHeader := pcepErrorObjectHeader.Serialize() buf := make([]uint8, 4) buf[2] = o.ErrorType buf[3] = o.ErrorValue - bytePcepErrorObject := AppendByteSlices(bytePcepErrorObjectHeader, buf) - return bytePcepErrorObject + bytePCEPErrorObject := AppendByteSlices(bytePCEPErrorObjectHeader, buf) + return bytePCEPErrorObject } -func (o *PcepErrorObject) Len() uint16 { +func (o *PCEPErrorObject) Len() uint16 { tlvsByteLength := uint16(0) for _, tlv := range o.Tlvs { tlvsByteLength += tlv.Len() } // CommonObjectHeader(4byte) + Flags,Error-Type,Error-value(4byte) + tlvslength(valiable) - return COMMON_OBJECT_HEADER_LENGTH + 4 + tlvsByteLength + return commonObjectHeaderLength + 4 + tlvsByteLength } -func NewPcepErrorObject(errorType uint8, errorValue uint8, tlvs []TLVInterface) (*PcepErrorObject, error) { - o := &PcepErrorObject{ - ObjectType: OT_ERROR_ERROR, +func NewPCEPErrorObject(errorType uint8, errorValue uint8, tlvs []TLVInterface) (*PCEPErrorObject, error) { + o := &PCEPErrorObject{ + ObjectType: ObjectTypeErrorError, ErrorType: errorType, ErrorValue: errorValue, Tlvs: tlvs, @@ -404,45 +447,74 @@ func NewPcepErrorObject(errorType uint8, errorValue uint8, tlvs []TLVInterface) // Close Object (RFC5440 7.17) const ( - OT_CLOSE_CLOSE uint8 = 0x01 + ObjectTypeCloseClose ObjectType = 0x01 ) +type CloseReason uint8 + const ( - R_NO_EXPLANATION_PROVIDED uint8 = 0x01 - R_DEADTIMER_EXPIRED uint8 = 0x02 - R_RECEPTION_OF_A_MALFORMED_PCEP_MESSAGE uint8 = 0x03 + CloseReasonNoExplanationProvided CloseReason = 0x01 + CloseReasonDeadTimerExpired CloseReason = 0x02 + CloseReasonMalformedPCEPMessage CloseReason = 0x03 + CloseReasonTooManyUnknownRequestsReplies CloseReason = 0x04 + CloseReasonTooManyUnrecognizedPCEPMessages CloseReason = 0x05 ) +var closeReasonDescriptions = map[CloseReason]struct { + Description string + Reference string +}{ + CloseReasonNoExplanationProvided: {"No explanation provided", "RFC5440"}, + CloseReasonDeadTimerExpired: {"DeadTimer expired", "RFC5440"}, + CloseReasonMalformedPCEPMessage: {"Reception of a malformed PCEP message", "RFC5440"}, + CloseReasonTooManyUnknownRequestsReplies: {"Reception of an unacceptable number of unknown requests/replies", "RFC5440"}, + CloseReasonTooManyUnrecognizedPCEPMessages: {"Reception of an unacceptable number of unrecognized PCEP messages", "RFC5440"}, +} + +func (r CloseReason) String() string { + if desc, ok := closeReasonDescriptions[r]; ok { + return fmt.Sprintf("%s (0x%02x)", desc.Description, uint8(r)) + } + return fmt.Sprintf("Unknown Close Reason (0x%02x)", uint8(r)) +} + +func (r CloseReason) StringWithReference() string { + if desc, ok := closeReasonDescriptions[r]; ok { + return fmt.Sprintf("%s (0x%02x) [%s]", desc.Description, r, desc.Reference) + } + return fmt.Sprintf("Unknown Close Reason (0x%02x)", uint8(r)) +} + type CloseObject struct { - ObjectType uint8 - Reason uint8 + ObjectType ObjectType + Reason CloseReason } -func (o *CloseObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *CloseObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ - o.Reason = objectBody[3] + o.Reason = CloseReason(objectBody[3]) return nil } func (o *CloseObject) Serialize() []uint8 { - closeObjectHeader := NewCommonObjectHeader(OC_CLOSE, o.ObjectType, o.Len()) + closeObjectHeader := NewCommonObjectHeader(ObjectClassClose, o.ObjectType, o.Len()) byteCloseObjectHeader := closeObjectHeader.Serialize() buf := make([]uint8, 4) - buf[3] = o.Reason + buf[3] = uint8(o.Reason) byteCloseObject := AppendByteSlices(byteCloseObjectHeader, buf) return byteCloseObject } func (o *CloseObject) Len() uint16 { // CommonObjectHeader(4byte) + CloseObjectBody(4byte) - return COMMON_OBJECT_HEADER_LENGTH + 4 + return commonObjectHeaderLength + 4 } -func NewCloseObject(reason uint8) (*CloseObject, error) { +func NewCloseObject(reason CloseReason) (*CloseObject, error) { o := &CloseObject{ - ObjectType: OT_CLOSE_CLOSE, + ObjectType: ObjectTypeCloseClose, Reason: reason, } return o, nil @@ -450,17 +522,17 @@ func NewCloseObject(reason uint8) (*CloseObject, error) { // SRP Object (RFC8231 7.2) const ( - OT_SRP_SRP uint8 = 0x01 + ObjectTypeSRPSRP ObjectType = 0x01 ) type SrpObject struct { - ObjectType uint8 + ObjectType ObjectType RFlag bool SrpID uint32 // 0x00000000 and 0xFFFFFFFF are reserved. TLVs []TLVInterface } -func (o *SrpObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *SrpObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.RFlag = (objectBody[3] & 0x01) != 0 o.SrpID = binary.BigEndian.Uint32(objectBody[4:8]) @@ -468,7 +540,7 @@ func (o *SrpObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { } func (o *SrpObject) Serialize() []uint8 { - srpObjectHeader := NewCommonObjectHeader(OC_SRP, o.ObjectType, o.Len()) + srpObjectHeader := NewCommonObjectHeader(ObjectClassSRP, o.ObjectType, o.Len()) byteSrpObjectHeader := srpObjectHeader.Serialize() byteFlags := make([]uint8, 4) @@ -492,12 +564,12 @@ func (o *SrpObject) Len() uint16 { tlvsByteLength += tlv.Len() } // CommonObjectHeader(4byte) + Flags, SRP-ID(8byte) - return COMMON_OBJECT_HEADER_LENGTH + 8 + tlvsByteLength + return commonObjectHeaderLength + 8 + tlvsByteLength } func NewSrpObject(segs []table.Segment, srpID uint32, isRemove bool) (*SrpObject, error) { o := &SrpObject{ - ObjectType: OT_SRP_SRP, + ObjectType: ObjectTypeSRPSRP, RFlag: isRemove, // RFC8281 5.2 SrpID: srpID, TLVs: []TLVInterface{}, @@ -506,9 +578,9 @@ func NewSrpObject(segs []table.Segment, srpID uint32, isRemove bool) (*SrpObject return o, nil } if _, ok := segs[0].(table.SegmentSRMPLS); ok { - o.TLVs = append(o.TLVs, &PathSetupType{PathSetupType: PST_SR_TE}) + o.TLVs = append(o.TLVs, &PathSetupType{PathSetupType: PathSetupTypeSRTE}) } else if _, ok := segs[0].(table.SegmentSRv6); ok { - o.TLVs = append(o.TLVs, &PathSetupType{PathSetupType: PST_SRV6_TE}) + o.TLVs = append(o.TLVs, &PathSetupType{PathSetupType: PathSetupTypeSRv6TE}) } else { return nil, errors.New("invalid Segment type") } @@ -517,16 +589,16 @@ func NewSrpObject(segs []table.Segment, srpID uint32, isRemove bool) (*SrpObject // LSP Object (RFC8281 5.3.1) const ( - OT_LSP_LSP uint8 = 0x01 + ObjectTypeLSPLSP ObjectType = 0x01 ) -type LspObject struct { - ObjectType uint8 +type LSPObject struct { + ObjectType ObjectType Name string SrcAddr netip.Addr DstAddr netip.Addr PlspID uint32 - LspID uint16 + LSPID uint16 CFlag bool OFlag uint8 AFlag bool @@ -536,7 +608,7 @@ type LspObject struct { TLVs []TLVInterface } -func (o *LspObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *LSPObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.PlspID = uint32(binary.BigEndian.Uint32(objectBody[0:4]) >> 12) // 20 bits from top o.OFlag = uint8(objectBody[3] & 0x0070 >> 4) @@ -556,24 +628,24 @@ func (o *LspObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { if t, ok := tlv.(*SymbolicPathName); ok { o.Name = t.Name } - if t, ok := tlv.(*IPv4LspIdentifiers); ok { + if t, ok := tlv.(*IPv4LSPIdentifiers); ok { o.SrcAddr = t.IPv4TunnelSenderAddress o.DstAddr = t.IPv4TunnelEndpointAddress - o.LspID = t.LspID + o.LSPID = t.LSPID } - if t, ok := tlv.(*IPv6LspIdentifiers); ok { + if t, ok := tlv.(*IPv6LSPIdentifiers); ok { o.SrcAddr = t.IPv6TunnelSenderAddress o.DstAddr = t.IPv6TunnelEndpointAddress - o.LspID = t.LspID + o.LSPID = t.LSPID } } } return nil } -func (o *LspObject) Serialize() []uint8 { - lspObjectHeader := NewCommonObjectHeader(OC_LSP, o.ObjectType, o.Len()) - byteLspObjectHeader := lspObjectHeader.Serialize() +func (o *LSPObject) Serialize() []uint8 { + lspObjectHeader := NewCommonObjectHeader(ObjectClassLSP, o.ObjectType, o.Len()) + byteLSPObjectHeader := lspObjectHeader.Serialize() buf := make([]uint8, 4) binary.BigEndian.PutUint32(buf, uint32(o.PlspID<<12)+uint32(o.OFlag<<4)) @@ -597,11 +669,11 @@ func (o *LspObject) Serialize() []uint8 { byteTLVs = AppendByteSlices(byteTLVs, tlv.Serialize()) } - byteLspObject := AppendByteSlices(byteLspObjectHeader, buf, byteTLVs) - return byteLspObject + byteLSPObject := AppendByteSlices(byteLSPObjectHeader, buf, byteTLVs) + return byteLSPObject } -func (o *LspObject) Len() uint16 { +func (o *LSPObject) Len() uint16 { tlvsByteLength := uint16(0) for _, tlv := range o.TLVs { tlvsByteLength += tlv.Len() @@ -609,12 +681,12 @@ func (o *LspObject) Len() uint16 { // Flags, SRP-ID (4byte) lspObjectBodyLength := uint16(4) + tlvsByteLength // CommonObjectHeader(4byte) + Flags, SRP-ID - return uint16(COMMON_OBJECT_HEADER_LENGTH) + lspObjectBodyLength + return uint16(commonObjectHeaderLength) + lspObjectBodyLength } -func NewLspObject(lspName string, color *uint32, plspID uint32) (*LspObject, error) { - o := &LspObject{ - ObjectType: OT_LSP_LSP, +func NewLSPObject(lspName string, color *uint32, plspID uint32) (*LSPObject, error) { + o := &LSPObject{ + ObjectType: ObjectTypeLSPLSP, Name: lspName, PlspID: plspID, CFlag: true, // (RFC8281 5.3.1) @@ -644,7 +716,7 @@ func NewLspObject(lspName string, color *uint32, plspID uint32) (*LspObject, err } // (I.D.draft-ietf-pce-pcep-color-12) -func (o *LspObject) Color() uint32 { +func (o *LSPObject) Color() uint32 { for _, tlv := range o.TLVs { if t, ok := tlv.(*Color); ok { return t.Color @@ -656,25 +728,25 @@ func (o *LspObject) Color() uint32 { // ERO Object (RFC5440 7.9) const ( - OT_ERO_EXPLICIT_ROUTE uint8 = 0x01 + ObjectTypeEROExplicitRoute ObjectType = 0x01 ) type EroObject struct { - ObjectType uint8 + ObjectType ObjectType EroSubobjects []EroSubobject } -func (o *EroObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *EroObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ if len(objectBody) == 0 { return nil } for { var eroSubobj EroSubobject - switch objectBody[0] & 0x7f { - case OT_ERO_SR: + switch SubObjectType(objectBody[0] & 0x7f) { + case SubObjectTypeEROSR: eroSubobj = &SREroSubobject{} - case OT_ERO_SRV6: + case SubObjectTypeEROSRv6: eroSubobj = &SRv6EroSubobject{} default: return errors.New("invalid Subobject type") @@ -701,12 +773,15 @@ func (o EroObject) Serialize() ([]uint8, error) { if err != nil { return nil, err } - eroObjectHeader := NewCommonObjectHeader(OC_ERO, o.ObjectType, eroObjectLength) + eroObjectHeader := NewCommonObjectHeader(ObjectClassERO, o.ObjectType, eroObjectLength) byteEroObjectHeader := eroObjectHeader.Serialize() byteEroObject := byteEroObjectHeader for _, eroSubobject := range o.EroSubobjects { - buf := eroSubobject.Serialize() + buf, err := eroSubobject.Serialize() + if err != nil { + return nil, fmt.Errorf("failed to serialize subobject: %w", err) + } byteEroObject = append(byteEroObject, buf...) } return byteEroObject, nil @@ -722,12 +797,12 @@ func (o EroObject) Len() (uint16, error) { eroSubobjByteLength += objByteLength } // CommonObjectHeader(4byte) + eroSubobjects(valiable) - return uint16(COMMON_OBJECT_HEADER_LENGTH) + eroSubobjByteLength, nil + return uint16(commonObjectHeaderLength) + eroSubobjByteLength, nil } func NewEroObject(segmentList []table.Segment) (*EroObject, error) { o := &EroObject{ - ObjectType: OT_ERO_EXPLICIT_ROUTE, + ObjectType: ObjectTypeEROExplicitRoute, EroSubobjects: []EroSubobject{}, } err := o.AddEroSubobjects(segmentList) @@ -762,7 +837,7 @@ func (o *EroObject) ToSegmentList() []table.Segment { type EroSubobject interface { DecodeFromBytes([]uint8) error Len() (uint16, error) - Serialize() []uint8 + Serialize() ([]uint8, error) ToSegment() table.Segment } @@ -779,94 +854,124 @@ func NewEroSubobject(seg table.Segment) (EroSubobject, error) { return nil, err } return subo, nil - } else { - return nil, errors.New("invalid Segment type") } + return nil, errors.New("invalid Segment type") } // SR-ERO Subobject (RFC8664 4.3.1) const ( - OT_ERO_SR uint8 = 0x24 + SubObjectTypeEROSR SubObjectType = 0x24 ) +type NAITypeSR uint8 + const ( - NT_ABSENT uint8 = 0x00 // RFC 8664 4.3.1 - NT_IPV4_NODE uint8 = 0x01 // RFC 8664 4.3.1 - NT_IPV6_NODE uint8 = 0x02 // RFC 8664 4.3.1 - NT_IPV4_ADJACENCY uint8 = 0x03 // RFC 8664 4.3.1 - NT_IPV6_ADJACENCY_GLOBAL uint8 = 0x04 // RFC 8664 4.3.1 - NT_UNNUMBERED_ADJACENCY uint8 = 0x05 // RFC 8664 4.3.1 - NT_IPV6_ADJACENCY_LINKLOCAL uint8 = 0x06 // RFC 8664 4.3.1 + NAITypeSRAbsent NAITypeSR = 0x00 + NAITypeSRIPv4Node NAITypeSR = 0x01 + NAITypeSRIPv6Node NAITypeSR = 0x02 + NAITypeSRIPv4Adjacency NAITypeSR = 0x03 + NAITypeSRIPv6AdjacencyGlobal NAITypeSR = 0x04 + NAITypeSRUnnumberedAdjacency NAITypeSR = 0x05 + NAITypeSRIPv6AdjacencyLinkLocal NAITypeSR = 0x06 ) +var naiTypeSRDescriptions = map[NAITypeSR]struct { + Description string + Reference string +}{ + NAITypeSRAbsent: {"NAI is absent", "RFC8664"}, + NAITypeSRIPv4Node: {"NAI is an IPv4 node ID", "RFC8664"}, + NAITypeSRIPv6Node: {"NAI is an IPv6 node ID", "RFC8664"}, + NAITypeSRIPv4Adjacency: {"NAI is an IPv4 adjacency", "RFC8664"}, + NAITypeSRIPv6AdjacencyGlobal: {"NAI is an IPv6 adjacency with global IPv6 addresses", "RFC8664"}, + NAITypeSRUnnumberedAdjacency: {"NAI is an unnumbered adjacency with IPv4 node IDs", "RFC8664"}, + NAITypeSRIPv6AdjacencyLinkLocal: {"NAI is an IPv6 adjacency with link-local IPv6 addresses", "RFC8664"}, +} + +func (nt NAITypeSR) String() string { + if desc, ok := naiTypeSRDescriptions[nt]; ok { + return fmt.Sprintf("%s (0x%02x)", desc.Description, uint8(nt)) + } + return fmt.Sprintf("Unknown NAI Type (0x%02x)", uint8(nt)) +} + +func (nt NAITypeSR) StringWithReference() string { + if desc, ok := naiTypeSRDescriptions[nt]; ok { + return fmt.Sprintf("%s (0x%02x) [%s]", desc.Description, uint8(nt), desc.Reference) + } + return fmt.Sprintf("Unknown NAI Type (0x%02x)", uint8(nt)) +} + type SREroSubobject struct { LFlag bool - SubobjectType uint8 + SubobjectType SubObjectType Length uint8 - NaiType uint8 + NAIType NAITypeSR FFlag bool SFlag bool CFlag bool MFlag bool Segment table.SegmentSRMPLS - Nai netip.Addr + NAI netip.Addr } -func (o *SREroSubobject) DecodeFromBytes(subObj []uint8) error { - o.LFlag = (subObj[0] & 0x80) != 0 - o.SubobjectType = subObj[0] & 0x7f - o.Length = subObj[1] - o.NaiType = subObj[2] >> 4 - o.FFlag = (subObj[3] & 0x08) != 0 - o.SFlag = (subObj[3] & 0x04) != 0 - o.CFlag = (subObj[3] & 0x02) != 0 - o.MFlag = (subObj[3] & 0x01) != 0 +func (o *SREroSubobject) DecodeFromBytes(subObject []uint8) error { + o.LFlag = (subObject[0] & 0x80) != 0 + o.SubobjectType = SubObjectType(subObject[0] & 0x7f) + o.Length = subObject[1] + o.NAIType = NAITypeSR(subObject[2] >> 4) + o.FFlag = (subObject[3] & 0x08) != 0 + o.SFlag = (subObject[3] & 0x04) != 0 + o.CFlag = (subObject[3] & 0x02) != 0 + o.MFlag = (subObject[3] & 0x01) != 0 - sid := binary.BigEndian.Uint32(subObj[4:8]) >> 12 + sid := binary.BigEndian.Uint32(subObject[4:8]) >> 12 o.Segment = table.NewSegmentSRMPLS(sid) - if o.NaiType == 1 { - o.Nai, _ = netip.AddrFromSlice(subObj[8:12]) + if o.NAIType == NAITypeSRIPv4Node { + o.NAI, _ = netip.AddrFromSlice(subObject[8:12]) } return nil } -func (o *SREroSubobject) Serialize() []uint8 { +func (o *SREroSubobject) Serialize() ([]uint8, error) { buf := make([]uint8, 4) - buf[0] = o.SubobjectType + buf[0] = uint8(o.SubobjectType) if o.LFlag { - buf[0] = buf[0] | 0x80 + buf[0] |= 0x80 } buf[1] = o.Length - buf[2] = o.NaiType * 16 + buf[2] = uint8(o.NAIType) * 16 if o.FFlag { - buf[3] = buf[3] | 0x08 + buf[3] |= 0x08 } if o.SFlag { - buf[3] = buf[3] | 0x04 + buf[3] |= 0x04 } if o.CFlag { - buf[3] = buf[3] | 0x02 + buf[3] |= 0x02 } if o.MFlag { - buf[3] = buf[3] | 0x01 + buf[3] |= 0x01 } + byteSid := make([]uint8, 4) binary.BigEndian.PutUint32(byteSid, o.Segment.Sid<<12) byteSREroSubobject := AppendByteSlices(buf, byteSid) - return byteSREroSubobject + + return byteSREroSubobject, nil } func (o *SREroSubobject) Len() (uint16, error) { - switch o.NaiType { - case NT_ABSENT: + switch o.NAIType { + case NAITypeSRAbsent: // Type, Length, Flags (4byte) + SID (4byte) return uint16(8), nil - case NT_IPV4_NODE: - // Type, Length, Flags (4byte) + SID (4byte) + Nai (4byte) + case NAITypeSRIPv4Node: + // Type, Length, Flags (4byte) + SID (4byte) + NAI (4byte) return uint16(12), nil - case NT_IPV6_NODE: - // Type, Length, Flags (4byte) + SID (4byte) + Nai (16byte) + case NAITypeSRIPv6Node: + // Type, Length, Flags (4byte) + SID (4byte) + NAI (16byte) return uint16(24), nil default: return uint16(0), errors.New("unsupported naitype") @@ -876,9 +981,9 @@ func (o *SREroSubobject) Len() (uint16, error) { func NewSREroSubObject(seg table.SegmentSRMPLS) (*SREroSubobject, error) { subo := &SREroSubobject{ LFlag: false, - SubobjectType: OT_ERO_SR, - NaiType: NT_ABSENT, - FFlag: true, // Nai is absent + SubobjectType: SubObjectTypeEROSR, + NAIType: NAITypeSRAbsent, + FFlag: true, // NAI is absent SFlag: false, CFlag: false, MFlag: true, // TODO: Determine either MPLS label or index @@ -898,21 +1003,47 @@ func (o *SREroSubobject) ToSegment() table.Segment { // SRv6-ERO Subobject (RFC9603 4.3.1) const ( - OT_ERO_SRV6 uint8 = 0x28 + SubObjectTypeEROSRv6 SubObjectType = 0x28 ) +type NAITypeSRv6 uint8 + const ( - NT_MUST_NOT_BE_INCLUDED uint8 = 0x00 // draft-ietf-pce-segment-routing-ipv6 4.3.1 - NT_SRV6_NODE uint8 = 0x02 // draft-ietf-pce-segment-routing-ipv6 4.3.1 - NT_SRV6_ADJACENCY_GLOBAL uint8 = 0x04 // draft-ietf-pce-segment-routing-ipv6 4.3.1 - NT_SRV6_ADJACENCY_LINKLOCAL uint8 = 0x06 // draft-ietf-pce-segment-routing-ipv6 4.3.1 + NAITypeSRv6Absent NAITypeSRv6 = 0x00 + NAITypeSRv6IPv6Node NAITypeSRv6 = 0x02 + NAITypeSRv6IPv6AdjacencyGlobal NAITypeSRv6 = 0x04 + NAITypeSRv6IPv6AdjacencyLinkLocal NAITypeSRv6 = 0x06 ) +var naiTypeSRv6Descriptions = map[NAITypeSRv6]struct { + Description string + Reference string +}{ + NAITypeSRv6Absent: {"NAI is absent", "RFC9603"}, + NAITypeSRv6IPv6Node: {"NAI is an IPv6 node ID", "RFC9603"}, + NAITypeSRv6IPv6AdjacencyGlobal: {"NAI is an IPv6 adjacency with global IPv6 addresses", "RFC9603"}, + NAITypeSRv6IPv6AdjacencyLinkLocal: {"NAI is an IPv6 adjacency with link-local IPv6 addresses", "RFC9603"}, +} + +func (nt NAITypeSRv6) String() string { + if desc, ok := naiTypeSRv6Descriptions[nt]; ok { + return fmt.Sprintf("%s (0x%02x)", desc.Description, uint8(nt)) + } + return fmt.Sprintf("Unknown NAI Type (0x%02x)", uint8(nt)) +} + +func (nt NAITypeSRv6) StringWithReference() string { + if desc, ok := naiTypeSRv6Descriptions[nt]; ok { + return fmt.Sprintf("%s (0x%02x) [%s]", desc.Description, uint8(nt), desc.Reference) + } + return fmt.Sprintf("Unknown NAI Type (0x%02x)", uint8(nt)) +} + type SRv6EroSubobject struct { LFlag bool - SubobjectType uint8 + SubobjectType SubObjectType Length uint8 - NaiType uint8 + NAIType NAITypeSRv6 VFlag bool TFlag bool FFlag bool @@ -920,59 +1051,62 @@ type SRv6EroSubobject struct { Segment table.SegmentSRv6 } -func (o *SRv6EroSubobject) DecodeFromBytes(subObj []uint8) error { - o.LFlag = (subObj[0] & 0x80) != 0 - o.SubobjectType = subObj[0] & 0x7f - o.Length = subObj[1] - o.NaiType = subObj[2] >> 4 - o.VFlag = (subObj[3] & 0x08) != 0 - o.TFlag = (subObj[3] & 0x04) != 0 - o.FFlag = (subObj[3] & 0x02) != 0 - o.SFlag = (subObj[3] & 0x01) != 0 +func (o *SRv6EroSubobject) DecodeFromBytes(subObject []uint8) error { + o.LFlag = (subObject[0] & 0x80) != 0 + o.SubobjectType = SubObjectType(subObject[0] & 0x7f) + o.Length = subObject[1] + o.NAIType = NAITypeSRv6(subObject[2] >> 4) + o.VFlag = (subObject[3] & 0x08) != 0 + o.TFlag = (subObject[3] & 0x04) != 0 + o.FFlag = (subObject[3] & 0x02) != 0 + o.SFlag = (subObject[3] & 0x01) != 0 - sid, _ := netip.AddrFromSlice(subObj[8:24]) + sid, _ := netip.AddrFromSlice(subObject[8:24]) o.Segment = table.NewSegmentSRv6(sid) - if o.NaiType == NT_SRV6_NODE { - o.Segment.LocalAddr, _ = netip.AddrFromSlice(subObj[24:40]) + if o.NAIType == NAITypeSRv6IPv6Node { + o.Segment.LocalAddr, _ = netip.AddrFromSlice(subObject[24:40]) } - if o.NaiType == NT_SRV6_ADJACENCY_GLOBAL { - o.Segment.LocalAddr, _ = netip.AddrFromSlice(subObj[24:40]) - o.Segment.RemoteAddr, _ = netip.AddrFromSlice(subObj[40:56]) + if o.NAIType == NAITypeSRv6IPv6AdjacencyGlobal { + o.Segment.LocalAddr, _ = netip.AddrFromSlice(subObject[24:40]) + o.Segment.RemoteAddr, _ = netip.AddrFromSlice(subObject[40:56]) } return nil } -func (o *SRv6EroSubobject) Serialize() []uint8 { +func (o *SRv6EroSubobject) Serialize() ([]uint8, error) { buf := make([]uint8, 4) - buf[0] = o.SubobjectType + buf[0] = uint8(o.SubobjectType) if o.LFlag { - buf[0] = buf[0] | 0x80 + buf[0] |= 0x80 } buf[1] = o.Length - buf[2] = o.NaiType * 16 + buf[2] = uint8(o.NAIType) * 16 if o.VFlag { - buf[3] = buf[3] | 0x08 + buf[3] |= 0x08 } if o.TFlag { - buf[3] = buf[3] | 0x04 + buf[3] |= 0x04 } if o.FFlag { - buf[3] = buf[3] | 0x02 + buf[3] |= 0x02 } if o.SFlag { - buf[3] = buf[3] | 0x01 + buf[3] |= 0x01 } + reserved := make([]uint8, 2) - behavior := make([]uint8, 2) - binary.BigEndian.PutUint16(behavior, o.Segment.Behavior()) + + behavior, err := o.Segment.Behavior() + if err != nil { + return nil, err + } + behaviorBytes := Uint16ToByteSlice(behavior) + byteSid := o.Segment.Sid.AsSlice() - byteNai := []uint8{} - if o.Segment.LocalAddr.IsValid() { - byteNai = append(byteNai, o.Segment.LocalAddr.AsSlice()...) - if o.Segment.RemoteAddr.IsValid() { - byteNai = append(byteNai, o.Segment.RemoteAddr.AsSlice()...) - } + byteNAI := o.Segment.LocalAddr.AsSlice() + if o.Segment.RemoteAddr.IsValid() { + byteNAI = append(byteNAI, o.Segment.RemoteAddr.AsSlice()...) } byteSidStructure := []uint8{} @@ -981,8 +1115,8 @@ func (o *SRv6EroSubobject) Serialize() []uint8 { byteSidStructure = append(byteSidStructure, make([]uint8, 4)...) } - byteSRv6EroSubobject := AppendByteSlices(buf, reserved, behavior, byteSid, byteNai, byteSidStructure) - return byteSRv6EroSubobject + byteSRv6EroSubobject := AppendByteSlices(buf, reserved, behaviorBytes, byteSid, byteNAI, byteSidStructure) + return byteSRv6EroSubobject, nil } func (o *SRv6EroSubobject) Len() (uint16, error) { @@ -997,14 +1131,14 @@ func (o *SRv6EroSubobject) Len() (uint16, error) { } // NAI value in the subobject body is NOT absent if !o.FFlag { - switch o.NaiType { - case NT_IPV6_NODE: + switch o.NAIType { + case NAITypeSRv6IPv6Node: length += 16 - case NT_SRV6_ADJACENCY_GLOBAL: + case NAITypeSRv6IPv6AdjacencyGlobal: length += 32 - case NT_SRV6_ADJACENCY_LINKLOCAL: + case NAITypeSRv6IPv6AdjacencyLinkLocal: length += 40 - case NT_MUST_NOT_BE_INCLUDED: + case NAITypeSRv6Absent: return uint16(0), errors.New("when naitype is 0 then FFlag must be 1") default: return uint16(0), errors.New("unsupported naitype") @@ -1019,7 +1153,7 @@ func (o *SRv6EroSubobject) Len() (uint16, error) { func NewSRv6EroSubObject(seg table.SegmentSRv6) (*SRv6EroSubobject, error) { subo := &SRv6EroSubobject{ LFlag: false, - SubobjectType: OT_ERO_SRV6, + SubobjectType: SubObjectTypeEROSRv6, VFlag: false, SFlag: false, // SID is absent Segment: seg, @@ -1031,18 +1165,18 @@ func NewSRv6EroSubObject(seg table.SegmentSRv6) (*SRv6EroSubobject, error) { subo.TFlag = false } if seg.LocalAddr.IsValid() { - subo.FFlag = false // Nai is present + subo.FFlag = false // NAI is present if seg.RemoteAddr.IsValid() { // End.X or uA - subo.NaiType = NT_SRV6_ADJACENCY_GLOBAL + subo.NAIType = NAITypeSRv6IPv6AdjacencyGlobal } else { // End or uN - subo.NaiType = NT_SRV6_NODE + subo.NAIType = NAITypeSRv6IPv6Node } } else { subo.FFlag = true // SID is absent - subo.NaiType = NT_MUST_NOT_BE_INCLUDED + subo.NAIType = NAITypeSRv6Absent } length, err := subo.Len() @@ -1059,12 +1193,12 @@ func (o *SRv6EroSubobject) ToSegment() table.Segment { // END-POINTS Object (RFC5440 7.6) const ( - OT_EP_IPV4 uint8 = 1 - OT_EP_IPV6 uint8 = 2 + ObjectTypeEndpointIPv4 ObjectType = 0x01 + ObjectTypeEndpointIPv6 ObjectType = 0x02 ) type EndpointsObject struct { - ObjectType uint8 + ObjectType ObjectType SrcAddr netip.Addr DstAddr netip.Addr } @@ -1074,39 +1208,39 @@ func (o *EndpointsObject) Serialize() ([]uint8, error) { if err != nil { return nil, err } - endpointsObjectHeader := NewCommonObjectHeader(OC_END_POINTS, o.ObjectType, endpointsObjectLength) + endpointsObjectHeader := NewCommonObjectHeader(ObjectClassEndpoints, o.ObjectType, endpointsObjectLength) byteEroObjectHeader := endpointsObjectHeader.Serialize() byteEndpointsObject := AppendByteSlices(byteEroObjectHeader, o.SrcAddr.AsSlice(), o.DstAddr.AsSlice()) return byteEndpointsObject, nil } -func (o EndpointsObject) Len() (uint16, error) { +func (o *EndpointsObject) Len() (uint16, error) { var length uint16 if o.SrcAddr.Is4() && o.DstAddr.Is4() { // CommonObjectHeader(4byte) + srcIPv4 (4byte) + dstIPv4 (4byte) - length = COMMON_OBJECT_HEADER_LENGTH + 4 + 4 + length = commonObjectHeaderLength + 4 + 4 } else if o.SrcAddr.Is6() && o.DstAddr.Is6() { // CommonObjectHeader(4byte) + srcIPv4 (16byte) + dstIPv4 (16byte) - length = COMMON_OBJECT_HEADER_LENGTH + 16 + 16 + length = commonObjectHeaderLength + 16 + 16 } else { - return uint16(0), errors.New("invalid endpoints address") + return uint16(0), fmt.Errorf("invalid endpoint addresses (Len()): source and destination must be both IPv4 or both IPv6: src=%v dst=%v", o.SrcAddr, o.DstAddr) } return length, nil } func NewEndpointsObject(dstAddr netip.Addr, srcAddr netip.Addr) (*EndpointsObject, error) { - var objType uint8 + var objectType ObjectType if dstAddr.Is4() && srcAddr.Is4() { - objType = OT_EP_IPV4 + objectType = ObjectTypeEndpointIPv4 } else if dstAddr.Is6() && srcAddr.Is6() { - objType = OT_EP_IPV6 + objectType = ObjectTypeEndpointIPv6 } else { - return nil, errors.New("invalid endpoints address") + return nil, fmt.Errorf("invalid endpoint addresses (NewEndpointsObject): source and destination must be both IPv4 or both IPv6 (dst=%v src=%v)", dstAddr, srcAddr) } o := &EndpointsObject{ - ObjectType: objType, + ObjectType: objectType, DstAddr: dstAddr, SrcAddr: srcAddr, } @@ -1115,40 +1249,57 @@ func NewEndpointsObject(dstAddr netip.Addr, srcAddr netip.Addr) (*EndpointsObjec // ASSOCIATION Object (RFC8697 6.) const ( - OT_ASSOC_IPV4 uint8 = 1 - OT_ASSOC_IPV6 uint8 = 2 + ObjectTypeAssociationIPv4 ObjectType = 0x01 + ObjectTypeAssociationIPv6 ObjectType = 0x02 ) const ( - ASSOC_TYPE_SR_POLICY_ASSOCIATION uint16 = 0x06 + AssociationTypeSRPolicyAssociation AssocType = 0x06 + AssociationTypeSRPolicyAssociationCisco AssocType = 0x14 + AssociationTypeSRPolicyAssociationJuniper AssocType = 0xffe1 // Juniper specific TLV (deprecated) ) -// Juniper specific TLV (deprecated) const ( - JUNIPER_SPEC_TLV_EXTENDED_ASSOCIATION_ID uint16 = 65507 - JUNIPER_SPEC_TLV_SRPOLICY_CPATH_ID uint16 = 65508 - JUNIPER_SPEC_TLV_SRPOLICY_CPATH_PREFERENCE uint16 = 65509 - - JUNIPER_SPEC_ASSOC_TYPE_SR_POLICY_ASSOCIATION uint16 = 65505 + CiscoLegacy PccType = iota + JuniperLegacy + RFCCompliant ) +// Determine PCC type from capability +func DeterminePccType(caps []CapabilityInterface) (pccType PccType) { + pccType = RFCCompliant + for _, cap := range caps { + if t, ok := cap.(*AssocTypeList); ok { + for _, v := range t.AssocTypes { + if v == AssociationTypeSRPolicyAssociationCisco { + pccType = CiscoLegacy + } else if v == AssociationTypeSRPolicyAssociationJuniper { + pccType = JuniperLegacy + break + } + } + } + } + return +} + type AssociationObject struct { - ObjectType uint8 + ObjectType ObjectType RFlag bool - AssocType uint16 + AssocType AssocType AssocID uint16 AssocSrc netip.Addr TLVs []TLVInterface } -func (o *AssociationObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *AssociationObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.RFlag = (objectBody[3] & 0x01) != 0 - o.AssocType = uint16(binary.BigEndian.Uint16(objectBody[4:6])) + o.AssocType = AssocType(binary.BigEndian.Uint16(objectBody[4:6])) o.AssocID = uint16(binary.BigEndian.Uint16(objectBody[6:8])) switch o.ObjectType { - case OT_ASSOC_IPV4: + case ObjectTypeAssociationIPv4: assocSrcBytes, _ := netip.AddrFromSlice(objectBody[8:12]) o.AssocSrc = assocSrcBytes if len(objectBody) > 12 { @@ -1158,7 +1309,7 @@ func (o *AssociationObject) DecodeFromBytes(typ uint8, objectBody []uint8) error return err } } - case OT_ASSOC_IPV6: + case ObjectTypeAssociationIPv6: o.AssocSrc, _ = netip.AddrFromSlice(objectBody[8:24]) if len(objectBody) > 24 { byteTLVs := objectBody[24:] @@ -1168,7 +1319,7 @@ func (o *AssociationObject) DecodeFromBytes(typ uint8, objectBody []uint8) error } } default: - return errors.New("invalid association source address") + return errors.New("invalid association source address (DecodeFromBytes)") } return nil @@ -1179,7 +1330,7 @@ func (o *AssociationObject) Serialize() ([]uint8, error) { if err != nil { return nil, err } - associationObjectHeader := NewCommonObjectHeader(OC_ASSOCIATION, o.ObjectType, associationObjectLength) + associationObjectHeader := NewCommonObjectHeader(ObjectClassAssociation, o.ObjectType, associationObjectLength) byteAssociationObjectHeader := associationObjectHeader.Serialize() @@ -1216,47 +1367,47 @@ func (o AssociationObject) Len() (uint16, error) { // Reserved(2byte) + Flags(2byte) + Assoc Type(2byte) + Assoc ID(2byte) + IPv6 Assoc Src(16byte) associationObjectBodyLength = uint16(24) + tlvsByteLength } else { - return uint16(0), errors.New("invalid association source address") + return uint16(0), errors.New("invalid association source address (Len())") } - return (COMMON_OBJECT_HEADER_LENGTH + associationObjectBodyLength), nil + return (commonObjectHeaderLength + associationObjectBodyLength), nil } func NewAssociationObject(srcAddr netip.Addr, dstAddr netip.Addr, color uint32, preference uint32, opt ...Opt) (*AssociationObject, error) { opts := optParams{ - pccType: RFC_COMPLIANT, + pccType: RFCCompliant, } for _, o := range opt { o(&opts) } - var objType uint8 + var objectType ObjectType if dstAddr.Is4() && srcAddr.Is4() { - objType = OT_EP_IPV4 + objectType = ObjectTypeEndpointIPv4 } else if dstAddr.Is6() && srcAddr.Is6() { - objType = OT_EP_IPV6 + objectType = ObjectTypeEndpointIPv6 } else { - return nil, errors.New("invalid endpoints address") + return nil, fmt.Errorf("invalid endpoints address (NewAssociationObject): src=%v dst=%v", srcAddr, dstAddr) } o := &AssociationObject{ - ObjectType: objType, + ObjectType: objectType, RFlag: false, TLVs: []TLVInterface{}, AssocSrc: srcAddr, } - if opts.pccType == JUNIPER_LEGACY { + if opts.pccType == JuniperLegacy { o.AssocID = 0 - o.AssocType = JUNIPER_SPEC_ASSOC_TYPE_SR_POLICY_ASSOCIATION + o.AssocType = AssociationTypeSRPolicyAssociationJuniper associationObjectTLVs := []TLVInterface{ &UndefinedTLV{ - Typ: JUNIPER_SPEC_TLV_EXTENDED_ASSOCIATION_ID, - Length: TLV_EXTENDED_ASSOCIATION_ID_IPV4_LENGTH, // JUNIPER_LEGACY has only IPv4 implementation + Typ: TLVExtendedAssociationIDIPv4Juniper, + Length: TLVExtendedAssociationIDIPv4ValueLength, // JuniperLegacy has only IPv4 implementation Value: AppendByteSlices( Uint32ToByteSlice(color), dstAddr.AsSlice(), ), }, &UndefinedTLV{ - Typ: JUNIPER_SPEC_TLV_SRPOLICY_CPATH_ID, - Length: TLV_SRPOLICY_CPATH_ID_LENGTH, + Typ: TLVSRPolicyCPathIDJuniper, + Length: TLVSRPolicyCPathIDValueLength, Value: []uint8{ 0x00, // protocol origin 0x00, 0x00, 0x00, // mbz @@ -1266,15 +1417,15 @@ func NewAssociationObject(srcAddr netip.Addr, dstAddr netip.Addr, color uint32, }, }, &UndefinedTLV{ - Typ: JUNIPER_SPEC_TLV_SRPOLICY_CPATH_PREFERENCE, - Length: TLV_SRPOLICY_CPATH_PREFERENCE_LENGTH, + Typ: TLVSRPolicyCPathPreferenceJuniper, + Length: TLVSRPolicyCPathPreferenceValueLength, Value: Uint32ToByteSlice(preference), }, } o.TLVs = append(o.TLVs, associationObjectTLVs...) } else { - o.AssocID = 1 // (I.D. pce-segment-routing-policy-cp-07 5.1) - o.AssocType = ASSOC_TYPE_SR_POLICY_ASSOCIATION // (I.D. pce-segment-routing-policy-cp-07 5.1) + o.AssocID = 1 // (I.D. pce-segment-routing-policy-cp-07 5.1) + o.AssocType = AssociationTypeSRPolicyAssociation // (I.D. pce-segment-routing-policy-cp-07 5.1) associationObjectTLVs := []TLVInterface{ &ExtendedAssociationID{ Color: color, @@ -1297,7 +1448,7 @@ func NewAssociationObject(srcAddr netip.Addr, dstAddr netip.Addr, color uint32, func (o *AssociationObject) Color() uint32 { for _, tlv := range o.TLVs { if t, ok := tlv.(*UndefinedTLV); ok { - if t.Type() == JUNIPER_SPEC_TLV_EXTENDED_ASSOCIATION_ID { + if t.Type() == TLVExtendedAssociationIDIPv4Juniper { return uint32(binary.BigEndian.Uint32(t.Value[:4])) } } else if t, ok := tlv.(*ExtendedAssociationID); ok { @@ -1312,7 +1463,7 @@ func (o *AssociationObject) Color() uint32 { func (o *AssociationObject) Preference() uint32 { for _, tlv := range o.TLVs { if t, ok := tlv.(*UndefinedTLV); ok { - if t.Type() == JUNIPER_SPEC_TLV_SRPOLICY_CPATH_PREFERENCE { + if t.Type() == TLVSRPolicyCPathPreferenceJuniper { return uint32(binary.BigEndian.Uint32(t.Value)) } } else if t, ok := tlv.(*SRPolicyCandidatePathPreference); ok { @@ -1333,26 +1484,20 @@ func (o *AssociationObject) Endpoint() netip.Addr { // VENDOR-INFORMATION Object (RFC7470 4) const ( - OT_VENDOR_SPECIFIC_CONSTRAINTS uint8 = 1 + ObjectTypeVendorSpecificConstraints ObjectType = 0x01 ) const ( - EN_CISCO uint32 = 9 - - CISCO_SPEC_TLV_COLOR uint16 = 1 - CISCO_SPEC_TLV_PREFERENCE uint16 = 3 - - CISCO_SPEC_TLV_COLOR_LENGTH uint16 = 4 - CISCO_SPEC_TLV_PREFERENCE_LENGTH uint16 = 4 + EnterpriseNumberCisco uint32 = 9 ) type VendorInformationObject struct { - ObjectType uint8 // vendor specific constraints: 1 + ObjectType ObjectType // vendor specific constraints: 1 EnterpriseNumber uint32 TLVs []TLVInterface } -func (o *VendorInformationObject) DecodeFromBytes(typ uint8, objectBody []uint8) error { +func (o *VendorInformationObject) DecodeFromBytes(typ ObjectType, objectBody []uint8) error { o.ObjectType = typ o.EnterpriseNumber = binary.BigEndian.Uint32(objectBody[0:4]) if len(objectBody) > 4 { @@ -1367,7 +1512,7 @@ func (o *VendorInformationObject) DecodeFromBytes(typ uint8, objectBody []uint8) } func (o *VendorInformationObject) Serialize() []uint8 { - vendorInformationObjectHeader := NewCommonObjectHeader(OC_VENDOR_INFORMATION, o.ObjectType, o.Len()) + vendorInformationObjectHeader := NewCommonObjectHeader(ObjectClassVendorInformation, o.ObjectType, o.Len()) byteVendorInformationObjectHeader := vendorInformationObjectHeader.Serialize() enterpriseNumber := Uint32ToByteSlice(o.EnterpriseNumber) @@ -1386,27 +1531,27 @@ func (o *VendorInformationObject) Serialize() []uint8 { func (o VendorInformationObject) Len() uint16 { // TODO: Expantion for IPv6 Endpoint // CommonObjectHeader(4byte) + Enterprise Number (4byte) + colorTLV (8byte) + preferenceTLV (8byte) - return uint16(COMMON_OBJECT_HEADER_LENGTH + 4 + 8 + 8) + return uint16(commonObjectHeaderLength + 4 + 8 + 8) } func NewVendorInformationObject(vendor PccType, color uint32, preference uint32) (*VendorInformationObject, error) { o := &VendorInformationObject{ // for Cisco PCC - ObjectType: OT_VENDOR_SPECIFIC_CONSTRAINTS, // (RFC7470 4) + ObjectType: ObjectTypeVendorSpecificConstraints, // (RFC7470 4) TLVs: []TLVInterface{}, } - if vendor == CISCO_LEGACY { - o.EnterpriseNumber = EN_CISCO + if vendor == CiscoLegacy { + o.EnterpriseNumber = EnterpriseNumberCisco vendorInformationObjectTLVs := []TLVInterface{ &UndefinedTLV{ - Typ: CISCO_SPEC_TLV_COLOR, - Length: CISCO_SPEC_TLV_COLOR_LENGTH, // TODO: 20 if ipv6 endpoint + Typ: SubTLVColorCisco, + Length: SubTLVColorCiscoValueLength, // TODO: 20 if ipv6 endpoint Value: AppendByteSlices( Uint32ToByteSlice(color), ), }, &UndefinedTLV{ - Typ: CISCO_SPEC_TLV_PREFERENCE, - Length: CISCO_SPEC_TLV_PREFERENCE_LENGTH, + Typ: SubTLVPreferenceCisco, + Length: SubTLVPreferenceCiscoValueLength, Value: Uint32ToByteSlice(preference), }, } @@ -1420,7 +1565,7 @@ func NewVendorInformationObject(vendor PccType, color uint32, preference uint32) func (o *VendorInformationObject) Color() uint32 { for _, tlv := range o.TLVs { if t, ok := tlv.(*UndefinedTLV); ok { - if t.Type() == CISCO_SPEC_TLV_COLOR { + if t.Type() == SubTLVColorCisco { return uint32(binary.BigEndian.Uint32(t.Value)) } } @@ -1431,10 +1576,22 @@ func (o *VendorInformationObject) Color() uint32 { func (o *VendorInformationObject) Preference() uint32 { for _, tlv := range o.TLVs { if t, ok := tlv.(*UndefinedTLV); ok { - if t.Type() == CISCO_SPEC_TLV_PREFERENCE { + if t.Type() == SubTLVPreferenceCisco { return uint32(binary.BigEndian.Uint32(t.Value)) } } } return 0 } + +type optParams struct { + pccType PccType +} + +type Opt func(*optParams) + +func VendorSpecific(pt PccType) Opt { + return func(op *optParams) { + op.pccType = pt + } +} diff --git a/pkg/packet/pcep/pcep_util.go b/pkg/packet/pcep/pcep_util.go index a5fa3f0e..adc11ec3 100644 --- a/pkg/packet/pcep/pcep_util.go +++ b/pkg/packet/pcep/pcep_util.go @@ -7,33 +7,51 @@ package pcep import "encoding/binary" -// AppendByteSlices concatenates byte slices into a single slice. -func AppendByteSlices(byteSlices ...[]byte) []byte { - // Calculate the total length of the joined slice. - joinedSliceLength := 0 - for _, byteSlice := range byteSlices { - joinedSliceLength += len(byteSlice) +// AppendByteSlices concatenates multiple byte slices into a single slice. +func AppendByteSlices(slices ...[]byte) []byte { + totalLen := 0 + for _, s := range slices { + totalLen += len(s) } - // Allocate the joined slice with the total length and copy the byte slices. - joinedSlice := make([]byte, joinedSliceLength) - var index int - for _, byteSlice := range byteSlices { - copy(joinedSlice[index:], byteSlice) - index += len(byteSlice) + + result := make([]byte, totalLen) + offset := 0 + for _, s := range slices { + copy(result[offset:], s) + offset += len(s) } - return joinedSlice + + return result } -// Uint16ToByteSlice converts a uint16 value to a big-endian byte slice. -func Uint16ToByteSlice(input uint16) []byte { - uint16Bytes := make([]byte, 2) - binary.BigEndian.PutUint16(uint16Bytes, input) - return uint16Bytes +// Uint16ToByteSlice converts a uint16 or TLVType value to a big-endian byte slice. +func Uint16ToByteSlice[T ~uint16](v T) []byte { + b := make([]byte, 2) + binary.BigEndian.PutUint16(b, uint16(v)) + return b } // Uint32ToByteSlice converts a uint32 value to a big-endian byte slice. -func Uint32ToByteSlice(input uint32) []byte { - uint32Bytes := make([]byte, 4) - binary.BigEndian.PutUint32(uint32Bytes, input) - return uint32Bytes +func Uint32ToByteSlice(v uint32) []byte { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, v) + return b +} + +// Bitwise is a type constraint for unsigned integer types (uint8, uint16, uint32). +type Bitwise interface { + ~uint8 | ~uint16 | ~uint32 +} + +// IsBitSet checks if a specific bit is set in the value, with bit 0 as the least significant bit (LSB). +func IsBitSet[T Bitwise](value, mask T) bool { + return value&mask != 0 +} + +// SetBit sets a specific bit in the value of any unsigned integer type. +func SetBit[T Bitwise](value, bit T, condition bool) T { + if condition { + return value | bit + } + return value } diff --git a/pkg/packet/pcep/pcep_util_test.go b/pkg/packet/pcep/pcep_util_test.go new file mode 100644 index 00000000..f7554242 --- /dev/null +++ b/pkg/packet/pcep/pcep_util_test.go @@ -0,0 +1,229 @@ +// Copyright (c) 2022 NTT Communications Corporation +// +// This software is released under the MIT License. +// see https://github.com/nttcom/pola/blob/main/LICENSE + +package pcep + +import ( + "bytes" + "testing" +) + +func TestAppendByteSlices(t *testing.T) { + tests := []struct { + name string + input [][]byte + expected []byte + }{ + { + name: "Concatenate non-empty slices", + input: [][]byte{{0x01, 0x02}, {0x03, 0x04, 0x05}}, + expected: []byte{0x01, 0x02, 0x03, 0x04, 0x05}, + }, + { + name: "Concatenate empty slices", + input: [][]byte{{}, {}}, + expected: []byte{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := AppendByteSlices(tt.input...) + if !bytes.Equal(result, tt.expected) { + t.Errorf("expected %v, got %v", tt.expected, result) + } + }) + } +} + +func TestUint16ToByteSlice(t *testing.T) { + tests := []struct { + name string + input any + expected []byte + }{ + { + name: "Convert uint16 0x0102 to bytes", + input: uint16(0x0102), + expected: []byte{0x01, 0x02}, + }, + { + name: "Convert uint16 0xFFFF to bytes", + input: uint16(0xFFFF), + expected: []byte{0xFF, 0xFF}, + }, + { + name: "Convert TLVType 0x0102 to bytes", + input: TLVType(0x0102), + expected: []byte{0x01, 0x02}, + }, + { + name: "Convert TLVType 0xFFFF to bytes", + input: TLVType(0xFFFF), + expected: []byte{0xFF, 0xFF}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var result []byte + switch v := tt.input.(type) { + case uint16: + result = Uint16ToByteSlice(v) + case TLVType: + result = Uint16ToByteSlice(v) + default: + t.Fatalf("unexpected type %T", v) + } + if !bytes.Equal(result, tt.expected) { + t.Errorf("expected %v, got %v", tt.expected, result) + } + }) + } +} + +func TestUint32ToByteSlice(t *testing.T) { + tests := []struct { + name string + input uint32 + expected []byte + }{ + { + name: "Convert 0x01020304 to bytes", + input: 0x01020304, + expected: []byte{0x01, 0x02, 0x03, 0x04}, + }, + { + name: "Convert 0xFFFFFFFF to bytes", + input: 0xFFFFFFFF, + expected: []byte{0xFF, 0xFF, 0xFF, 0xFF}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := Uint32ToByteSlice(tt.input) + if !bytes.Equal(result, tt.expected) { + t.Errorf("expected %v, got %v", tt.expected, result) + } + }) + } +} + +func TestIsBitSet(t *testing.T) { + type testCase[T Bitwise] struct { + name string + value T + mask T + expected bool + } + + t.Run("uint8", func(t *testing.T) { + tests := []testCase[uint8]{ + {"bit 0 set", 0x01, 0x01, true}, + {"bit 1 set", 0x03, 0x02, true}, + {"bit 2 not set", 0x03, 0x04, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsBitSet(tt.value, tt.mask); got != tt.expected { + t.Errorf("expected %v, got %v", tt.expected, got) + } + }) + } + }) + + t.Run("uint16", func(t *testing.T) { + tests := []testCase[uint16]{ + {"bit 8 set", 0x0100, 0x0100, true}, + {"bit 9 set", 0x0201, 0x0200, true}, + {"bit 10 not set", 0x0201, 0x0400, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsBitSet(tt.value, tt.mask); got != tt.expected { + t.Errorf("expected %v, got %v", tt.expected, got) + } + }) + } + }) + + t.Run("uint32", func(t *testing.T) { + tests := []testCase[uint32]{ + {"bit 16 set", 0x00010000, 0x00010000, true}, + {"bit 17 set", 0x00020001, 0x00020000, true}, + {"bit 18 not set", 0x00020001, 0x00040000, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsBitSet(tt.value, tt.mask); got != tt.expected { + t.Errorf("expected %v, got %v", tt.expected, got) + } + }) + } + }) +} + +func TestSetBit(t *testing.T) { + tests := []struct { + name string + value uint8 + bit uint8 + condition bool + expected uint8 + }{ + { + name: "Set bit 0", + value: 0x00, + bit: 0x01, + condition: true, + expected: 0x01, + }, + { + name: "Set bit 1", + value: 0x00, + bit: 0x02, + condition: true, + expected: 0x02, + }, + { + name: "Set bit 0 when bit 0 is already set", + value: 0x01, + bit: 0x01, + condition: true, + expected: 0x01, + }, + { + name: "Set bit 1 when bit 0 is already set", + value: 0x01, + bit: 0x02, + condition: true, + expected: 0x03, + }, + { + name: "Set bit 0 when bit 1 is already set", + value: 0x02, + bit: 0x01, + condition: true, + expected: 0x03, + }, + { + name: "Do not set bit 0 when condition is false", + value: 0x00, + bit: 0x01, + condition: false, + expected: 0x00, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := SetBit(tt.value, tt.bit, tt.condition) + if result != tt.expected { + t.Errorf("Test %s failed: expected %v, got %v", tt.name, tt.expected, result) + } + }) + } +} diff --git a/pkg/packet/pcep/tlv.go b/pkg/packet/pcep/tlv.go index b9494421..e0929ac9 100644 --- a/pkg/packet/pcep/tlv.go +++ b/pkg/packet/pcep/tlv.go @@ -13,246 +13,347 @@ import ( "slices" "strconv" "strings" + "unicode/utf8" "go.uber.org/zap/zapcore" ) -const ( // PCEP TLV - TLV_RESERVED uint16 = 0x00 // RFC5440 - TLV_NO_PATH_VECTOR uint16 = 0x01 // RFC5440 - TLV_OVERLOAD_DURATION uint16 = 0x02 // RFC5440 - TLV_REQ_MISSING uint16 = 0x03 // RFC5440 - TLV_OF_LIST uint16 = 0x04 // RFC5541 - TLV_ORDER uint16 = 0x05 // RFC5557 - TLV_P2MP_CAPABLE uint16 = 0x06 // RFC8306 - TLV_VENDOR_INFORMATION uint16 = 0x07 // RFC7470 - TLV_WAVELENGTH_SELECTION uint16 = 0x08 // RFC8780 - TLV_WAVELENGTH_RESTRICTION uint16 = 0x09 // RFC8780 - TLV_WAVELENGTH_ALLOCATION uint16 = 0x0a // RFC8780 - TLV_OPTICAL_INTERFACE_CLASS_LIST uint16 = 0x0b // RFC8780 - TLV_CLIENT_SIGNAL_INFORMATION uint16 = 0x0c // RFC8780 - TLV_H_PCE_CAPABILITY uint16 = 0x0d // RFC8685 - TLV_DOMAIN_ID uint16 = 0x0e // RFC8685 - TLV_H_PCE_FLAG uint16 = 0x0f // RFC8685 - TLV_STATEFUL_PCE_CAPABILITY uint16 = 0x10 // RFC8231 - TLV_SYMBOLIC_PATH_NAME uint16 = 0x11 // RFC8231 - TLV_IPV4_LSP_IDENTIFIERS uint16 = 0x12 // RFC8231 - TLV_IPV6_LSP_IDENTIFIERS uint16 = 0x13 // RFC8231 - TLV_LSP_ERROR_CODE uint16 = 0x14 // RFC8231 - TLV_RSVP_ERROR_SPEC uint16 = 0x15 // RFC8231 - TLV_LSP_DB_VERSION uint16 = 0x17 // RFC8232 - TLV_SPEAKER_ENTITY_ID uint16 = 0x18 // RFC8232 - TLV_SR_PCE_CAPABILITY uint16 = 0x1a // RFC8664 - TLV_PATH_SETUP_TYPE uint16 = 0x1c // RFC8408 - TLV_OPERATOR_CONFIGURED_ASSOCIATION_RANGE uint16 = 0x1d // RFC8697 - TLV_GLOBAL_ASSOCIATION_SOURCE uint16 = 0x1e // RFC8697 - TLV_EXTENDED_ASSOCIATION_ID uint16 = 0x1f // RFC8697 - TLV_P2MP_IPV4_LSP_IDENTIFIERS uint16 = 0x20 // RFC8623 - TLV_P2MP_IPV6_LSP_IDENTIFIERS uint16 = 0x21 // RFC8623 - TLV_PATH_SETUP_TYPE_CAPABILITY uint16 = 0x22 // RFC8408 - TLV_ASSOC_TYPE_LIST uint16 = 0x23 // RFC8697 - TLV_AUTO_BANDWIDTH_CAPABILITY uint16 = 0x24 // RFC8733 - TLV_AUTO_BANDWIDTH_ATTRIBUTES uint16 = 0x25 // RFC8733 - TLV_PATH_PROTECTION_ASSOCIATION_GROUP_TLV uint16 = 0x26 // RFC8745 - TLV_IPV4_ADDRESS uint16 = 0x27 // RFC8779 - TLV_IPV6_ADDRESS uint16 = 0x28 // RFC8779 - TLV_UNNUMBERED_ENDPOINT uint16 = 0x29 // RFC8779 - TLV_LABEL_REQUEST uint16 = 0x2a // RFC8779 - TLV_LABEL_SET uint16 = 0x2b // RFC8779 - TLV_PROTECTION_ATTRIBUTE uint16 = 0x2c // RFC8779 - TLV_GMPLS_CAPABILITY uint16 = 0x2d // RFC8779 - TLV_DISJOINTNESS_CONFIGURATION uint16 = 0x2e // RFC8800 - TLV_DISJOINTNESS_STATUS uint16 = 0x2f // RFC8800 - TLV_POLICY_PARAMETERSjTLV uint16 = 0x30 // RFC9005 - TLV_SCHED_LSP_ATTRIBUTE uint16 = 0x31 // RFC8934 - TLV_SCHED_PD_LSP_ATTRIBUTE uint16 = 0x32 // RFC8934 - TLV_PCE_FLOWSPEC_CAPABILITY uint16 = 0x33 // RFC9168 - TLV_FLOW_FILTER uint16 = 0x34 // RFC9168 - TLV_BIDIRECTIONAL_LSP_ASSOCIATION_GROUP uint16 = 0x36 // RFC9059 - TLV_TE_PATH_BINDING uint16 = 0x37 // RFC9604 - TLV_SRPOLICY_POL_NAME uint16 = 0x38 // ietf-pce-segment-routing-policy-cp-07 - TLV_SRPOLICY_CPATH_ID uint16 = 0x39 // ietf-pce-segment-routing-policy-cp-07 - TLV_SRPOLICY_CPATH_NAME uint16 = 0x3a // ietf-pce-segment-routing-policy-cp-07 - TLV_SRPOLICY_CPATH_PREFERENCE uint16 = 0x3b // ietf-pce-segment-routing-policy-cp-07 - TLV_MULTIPATH_CAP uint16 = 0x3c // ietf-pce-pcep-multipath-07 - TLV_MULTIPATH_WIGHT uint16 = 0x3d // ietf-pce-pcep-multipath-07 - TLV_MULTIPATH_BACKUP uint16 = 0x3e // ietf-pce-pcep-multipath-07 - TLV_LSP_EXTENDED_FLAG uint16 = 0x3f // RFC9357 - TLV_VIRTUAL_NETWORK_TLV uint16 = 0x41 // RFC9358 - TLV_SR_ALGORITHM uint16 = 0x42 // ietf-pce-sid-algo-12 - TLV_COLOR uint16 = 0x43 // ietf-pce-pcep-color-06 - TLV_COMPUTATION_PRIORITY uint16 = 0x44 // ietf-pce-segment-routing-policy-cp-14 - TLV_EXPLICIT_NULL_LABEL_POLICY uint16 = 0x45 // draft-ietf-pce-segment-routing-policy-cp-14 - TLV_INVALIDATION uint16 = 0x4c // draft-ietf-pce-segment-routing-policy-cp-14 - TLV_SRPOLICY_CAPABILITY uint16 = 0x4d // draft-ietf-pce-segment-routing-policy-cp-14 - TLV_PATH_RECOMPUTATION uint16 = 0x4e // draft-ietf-pce-circuit-style-pcep-extensions-03 - TLV_SR_P2MP_POLICY_CAPABILITY uint16 = 0x4f // draft-ietf-pce-sr-p2mp-policy-09 - TLV_IPV4_SR_P2MP_INSTANCE_ID uint16 = 0x50 // draft-ietf-pce-sr-p2mp-policy-09 - TLV_IPV6_SR_P2MP_INSTANCE_ID uint16 = 0x51 // draft-ietf-pce-sr-p2mp-policy-09 +type TLVType uint16 + +// PCEP TLV types +const ( + TLVNoPathVector TLVType = 0x01 + TLVOverloadDuration TLVType = 0x02 + TLVReqMissing TLVType = 0x03 + TLVOFList TLVType = 0x04 + TLVOrder TLVType = 0x05 + TLVP2MPCapable TLVType = 0x06 + TLVVendorInformation TLVType = 0x07 + TLVWavelengthSelection TLVType = 0x08 + TLVWavelengthRestriction TLVType = 0x09 + TLVWavelengthAllocation TLVType = 0x0a + TLVOpticalInterfaceClassList TLVType = 0x0b + TLVClientSignalInformation TLVType = 0x0c + TLVHPCECapability TLVType = 0x0d + TLVDomainID TLVType = 0x0e + TLVHPCEFlag TLVType = 0x0f + TLVStatefulPCECapability TLVType = 0x10 + TLVSymbolicPathName TLVType = 0x11 + TLVIPv4LSPIdentifiers TLVType = 0x12 + TLVIPv6LSPIdentifiers TLVType = 0x13 + TLVLSPErrorCode TLVType = 0x14 + TLVRsvpErrorSpec TLVType = 0x15 + TLVLSPDBVersion TLVType = 0x17 + TLVSpeakerEntityID TLVType = 0x18 + TLVSRPCECapability TLVType = 0x1a + TLVPathSetupType TLVType = 0x1c + TLVOperatorConfiguredAssociationRange TLVType = 0x1d + TLVGlobalAssociationSource TLVType = 0x1e + TLVExtendedAssociationID TLVType = 0x1f + TLVP2MPIPv4LSPIdentifiers TLVType = 0x20 + TLVP2MPIPv6LSPIdentifiers TLVType = 0x21 + TLVPathSetupTypeCapability TLVType = 0x22 + TLVAssocTypeList TLVType = 0x23 + TLVAutoBandwidthCapability TLVType = 0x24 + TLVAutoBandwidthAttributes TLVType = 0x25 + TLVPathProtectionAssociationGroupTLV TLVType = 0x26 + TLVIPv4Address TLVType = 0x27 + TLVIPv6Address TLVType = 0x28 + TLVUnnumberedEndpoint TLVType = 0x29 + TLVLabelRequest TLVType = 0x2a + TLVLabelSet TLVType = 0x2b + TLVProtectionAttribute TLVType = 0x2c + TLVGmplsCapability TLVType = 0x2d + TLVDisjointnessConfiguration TLVType = 0x2e + TLVDisjointnessStatus TLVType = 0x2f + TLVPolicyParameters TLVType = 0x30 + TLVSchedLSPAttribute TLVType = 0x31 + TLVSchedPdLSPAttribute TLVType = 0x32 + TLVPCEFlowspecCapability TLVType = 0x33 + TLVFlowFilter TLVType = 0x34 + TLVBidirectionalLSPAssociationGroup TLVType = 0x36 + TLVTePathBinding TLVType = 0x37 + TLVSRPolicyPolName TLVType = 0x38 + TLVSRPolicyCPathID TLVType = 0x39 + TLVSRPolicyCPathName TLVType = 0x3a + TLVSRPolicyCPathPreference TLVType = 0x3b + TLVMultipathCap TLVType = 0x3c + TLVMultipathWeight TLVType = 0x3d + TLVMultipathBackup TLVType = 0x3e + TLVMultipathOppdirPath TLVType = 0x3f + TLVLSPExtendedFlag TLVType = 0x40 + TLVVirtualNetwork TLVType = 0x41 + TLVSrAlgorithm TLVType = 0x42 + TLVColor TLVType = 0x43 + TLVComputationPriority TLVType = 0x44 + TLVExplicitNullLabelPolicy TLVType = 0x45 + TLVInvalidation TLVType = 0x46 + TLVSRPolicyCapability TLVType = 0x47 + TLVPathRecomputation TLVType = 0x48 + TLVSRP2MPPolicyCapability TLVType = 0x49 + TLVIPv4SrP2MPInstanceID TLVType = 0x4a + TLVIPv6SrP2MPInstanceID TLVType = 0x4b ) -var tlvMap = map[uint16]func() TLVInterface{ - TLV_STATEFUL_PCE_CAPABILITY: func() TLVInterface { return &StatefulPceCapability{} }, - TLV_SYMBOLIC_PATH_NAME: func() TLVInterface { return &SymbolicPathName{} }, - TLV_IPV4_LSP_IDENTIFIERS: func() TLVInterface { return &IPv4LspIdentifiers{} }, - TLV_IPV6_LSP_IDENTIFIERS: func() TLVInterface { return &IPv6LspIdentifiers{} }, - TLV_LSP_DB_VERSION: func() TLVInterface { return &LSPDBVersion{} }, - TLV_SR_PCE_CAPABILITY: func() TLVInterface { return &SRPceCapability{} }, - TLV_PATH_SETUP_TYPE: func() TLVInterface { return &PathSetupType{} }, - TLV_EXTENDED_ASSOCIATION_ID: func() TLVInterface { return &ExtendedAssociationID{} }, - TLV_PATH_SETUP_TYPE_CAPABILITY: func() TLVInterface { return &PathSetupTypeCapability{} }, - TLV_ASSOC_TYPE_LIST: func() TLVInterface { return &AssocTypeList{} }, - TLV_COLOR: func() TLVInterface { return &Color{} }, +var tlvDescriptions = map[TLVType]struct { + Description string + Reference string +}{ + TLVNoPathVector: {"NO-PATH-VECTOR", "RFC5440"}, + TLVOverloadDuration: {"OVERLOAD-DURATION", "RFC5440"}, + TLVReqMissing: {"REQ-MISSING", "RFC5440"}, + TLVOFList: {"OF-LIST", "RFC5541"}, + TLVOrder: {"ORDER", "RFC5557"}, + TLVP2MPCapable: {"P2MP-CAPABLE", "RFC8306"}, + TLVVendorInformation: {"VENDOR-INFORMATION", "RFC7470"}, + TLVWavelengthSelection: {"WAVELENGTH-SELECTION", "RFC8780"}, + TLVWavelengthRestriction: {"WAVELENGTH-RESTRICTION", "RFC8780"}, + TLVWavelengthAllocation: {"WAVELENGTH-ALLOCATION", "RFC8780"}, + TLVOpticalInterfaceClassList: {"OPTICAL-INTERFACE-CLASS-LIST", "RFC8780"}, + TLVClientSignalInformation: {"CLIENT-SIGNAL-INFORMATION", "RFC8780"}, + TLVHPCECapability: {"H-PCE-CAPABILITY", "RFC8685"}, + TLVDomainID: {"DOMAIN-ID", "RFC8685"}, + TLVHPCEFlag: {"H-PCE-FLAG", "RFC8685"}, + TLVStatefulPCECapability: {"STATEFUL-PCE-CAPABILITY", "RFC8231"}, + TLVSymbolicPathName: {"SYMBOLIC-PATH-NAME", "RFC8231"}, + TLVIPv4LSPIdentifiers: {"IPV4-LSP-IDENTIFIERS", "RFC8231"}, + TLVIPv6LSPIdentifiers: {"IPV6-LSP-IDENTIFIERS", "RFC8231"}, + TLVLSPErrorCode: {"LSP-ERROR-CODE", "RFC8231"}, + TLVRsvpErrorSpec: {"RSVP-ERROR-SPEC", "RFC8231"}, + TLVLSPDBVersion: {"LSP-DB-VERSION", "RFC8232"}, + TLVSpeakerEntityID: {"SPEAKER-ENTITY-ID", "RFC8232"}, + TLVSRPCECapability: {"SR-PCE-CAPABILITY", "RFC8664"}, + TLVPathSetupType: {"PATH-SETUP-TYPE", "RFC8408"}, + TLVOperatorConfiguredAssociationRange: {"OPERATOR-CONFIGURED-ASSOCIATION-RANGE", "RFC8697"}, + TLVGlobalAssociationSource: {"GLOBAL-ASSOCIATION-SOURCE", "RFC8697"}, + TLVExtendedAssociationID: {"EXTENDED-ASSOCIATION-ID", "RFC8697"}, + TLVP2MPIPv4LSPIdentifiers: {"P2MP-IPV4-LSP-IDENTIFIERS", "RFC8623"}, + TLVP2MPIPv6LSPIdentifiers: {"P2MP-IPV6-LSP-IDENTIFIERS", "RFC8623"}, + TLVPathSetupTypeCapability: {"PATH-SETUP-TYPE-CAPABILITY", "RFC8408"}, + TLVAssocTypeList: {"ASSOC-TYPE-LIST", "RFC8697"}, + TLVAutoBandwidthCapability: {"AUTO-BANDWIDTH-CAPABILITY", "RFC8733"}, + TLVAutoBandwidthAttributes: {"AUTO-BANDWIDTH-ATTRIBUTES", "RFC8733"}, + TLVPathProtectionAssociationGroupTLV: {"PATH-PROTECTION-ASSOCIATION-GROUP", "RFC8745"}, + TLVIPv4Address: {"IPV4-ADDRESS", "RFC8779"}, + TLVIPv6Address: {"IPV6-ADDRESS", "RFC8779"}, + TLVUnnumberedEndpoint: {"UNNUMBERED-ENDPOINT", "RFC8779"}, + TLVLabelRequest: {"LABEL-REQUEST", "RFC8779"}, + TLVLabelSet: {"LABEL-SET", "RFC8779"}, + TLVProtectionAttribute: {"PROTECTION-ATTRIBUTE", "RFC8779"}, + TLVGmplsCapability: {"GMPLS-CAPABILITY", "RFC8779"}, + TLVDisjointnessConfiguration: {"DISJOINTNESS-CONFIGURATION", "RFC8800"}, + TLVDisjointnessStatus: {"DISJOINTNESS-STATUS", "RFC8800"}, + TLVPolicyParameters: {"POLICY-PARAMETERS-TLV", "RFC9005"}, + TLVSchedLSPAttribute: {"SCHED-LSP-ATTRIBUTE", "RFC8934"}, + TLVSchedPdLSPAttribute: {"SCHED-PD-LSP-ATTRIBUTE", "RFC8934"}, + TLVPCEFlowspecCapability: {"PCE-FLOWSPEC-CAPABILITY TLV", "RFC9168"}, + TLVFlowFilter: {"FLOW-FILTER-TLV", "RFC9168"}, + TLVBidirectionalLSPAssociationGroup: {"BIDIRECTIONAL-LSP Association Group TLV", "RFC9059"}, + TLVTePathBinding: {"TE-PATH-BINDING", "RFC9604"}, + TLVSRPolicyPolName: {"SRPOLICY-POL-NAME", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVSRPolicyCPathID: {"SRPOLICY-CPATH-ID", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVSRPolicyCPathName: {"SRPOLICY-CPATH-NAME", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVSRPolicyCPathPreference: {"SRPOLICY-CPATH-PREFERENCE", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVMultipathCap: {"MULTIPATH-CAP", "draft-ietf-pce-multipath-07"}, + TLVMultipathWeight: {"MULTIPATH-WEIGHT", "draft-ietf-pce-multipath-07"}, + TLVMultipathBackup: {"MULTIPATH-BACKUP", "draft-ietf-pce-multipath-07"}, + TLVMultipathOppdirPath: {"MULTIPATH-OPPDIR-PATH", "draft-ietf-pce-multipath-07"}, + TLVLSPExtendedFlag: {"LSP-EXTENDED-FLAG", "RFC9357"}, + TLVVirtualNetwork: {"VIRTUAL-NETWORK", "RFC9358"}, + TLVSrAlgorithm: {"SR-ALGORITHM", "draft-ietf-pce-sid-algo-12"}, + TLVColor: {"COLOR", "RFC-ietf-pce-pcep-color-12"}, + TLVComputationPriority: {"COMPUTATION-PRIORITY", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVExplicitNullLabelPolicy: {"EXPLICIT-NULL-LABEL-POLICY", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVInvalidation: {"INVALIDATION", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVSRPolicyCapability: {"SRPOLICY-CAPABILITY", "draft-ietf-pce-segment-routing-policy-cp-14"}, + TLVPathRecomputation: {"PATH-RECOMPUTATION", "draft-ietf-pce-circuit-style-pcep-extensions-03"}, + TLVSRP2MPPolicyCapability: {"SRP2MP-POLICY-CAPABILITY", "draft-ietf-pce-sr-p2mp-policy-09"}, + TLVIPv4SrP2MPInstanceID: {"IPV4-SR-P2MP-INSTANCE-ID", "draft-ietf-pce-sr-p2mp-policy-09"}, + TLVIPv6SrP2MPInstanceID: {"IPV6-SR-P2MP-INSTANCE-ID", "draft-ietf-pce-sr-p2mp-policy-09"}, +} + +func (t TLVType) String() string { + if desc, ok := tlvDescriptions[t]; ok { + return fmt.Sprintf("%s (%s)", desc.Description, desc.Reference) + } + return fmt.Sprintf("Unknown TLV (0x%04x)", uint16(t)) } +// TLV header length (type + length) +const TLVHeaderLength = 4 + +// TLV value lengths, excluding the 4-byte TLV header (type + length) +const ( + TLVStatefulPCECapabilityValueLength uint16 = 4 + TLVIPv4LSPIdentifiersValueLength uint16 = 16 + TLVIPv6LSPIdentifiersValueLength uint16 = 52 + TLVLSPDBVersionValueLength uint16 = 8 + TLVSRPCECapabilityValueLength uint16 = 4 + TLVPathSetupTypeValueLength uint16 = 4 + TLVExtendedAssociationIDIPv4ValueLength uint16 = 8 + TLVExtendedAssociationIDIPv6ValueLength uint16 = 20 + TLVSRPolicyCPathIDValueLength uint16 = 28 + TLVSRPolicyCPathPreferenceValueLength uint16 = 4 + TLVColorValueLength uint16 = 4 +) + +// Juniper specific TLV (deprecated) +const ( + TLVExtendedAssociationIDIPv4Juniper TLVType = 0xffe3 + TLVSRPolicyCPathIDJuniper TLVType = 0xffe4 + TLVSRPolicyCPathPreferenceJuniper TLVType = 0xffe5 +) + +// Cisco specific SubTLV const ( - TLV_STATEFUL_PCE_CAPABILITY_LENGTH uint16 = 4 - TLV_LSP_DB_VERSION_LENGTH uint16 = 8 - TLV_SR_PCE_CAPABILITY_LENGTH uint16 = 4 - TLV_PATH_SETUP_TYPE_LENGTH uint16 = 4 - TLV_EXTENDED_ASSOCIATION_ID_IPV4_LENGTH uint16 = 8 - TLV_EXTENDED_ASSOCIATION_ID_IPV6_LENGTH uint16 = 20 - TLV_IPV4_LSP_IDENTIFIERS_LENGTH uint16 = 16 - TLV_IPV6_LSP_IDENTIFIERS_LENGTH uint16 = 52 - TLV_SRPOLICY_CPATH_ID_LENGTH uint16 = 28 - TLV_SRPOLICY_CPATH_PREFERENCE_LENGTH uint16 = 4 - TLV_COLOR_LENGTH uint16 = 4 + SubTLVColorCisco TLVType = 0x01 + SubTLVPreferenceCisco TLVType = 0x03 ) -const TL_LENGTH = 4 +// Cisco specific SubTLV length +const ( + SubTLVColorCiscoValueLength uint16 = 4 + SubTLVPreferenceCiscoValueLength uint16 = 4 +) type TLVInterface interface { - DecodeFromBytes(data []uint8) error - Serialize() []uint8 + DecodeFromBytes(data []byte) error + Serialize() []byte MarshalLogObject(enc zapcore.ObjectEncoder) error - Type() uint16 + Type() TLVType Len() uint16 // Total length of Type, Length, and Value } -type StatefulPceCapability struct { - LspUpdateCapability bool // 31 +var tlvMap = map[TLVType]func() TLVInterface{ + TLVStatefulPCECapability: func() TLVInterface { return &StatefulPCECapability{} }, + TLVSymbolicPathName: func() TLVInterface { return &SymbolicPathName{} }, + TLVIPv4LSPIdentifiers: func() TLVInterface { return &IPv4LSPIdentifiers{} }, + TLVIPv6LSPIdentifiers: func() TLVInterface { return &IPv6LSPIdentifiers{} }, + TLVLSPDBVersion: func() TLVInterface { return &LSPDBVersion{} }, + TLVSRPCECapability: func() TLVInterface { return &SRPCECapability{} }, + TLVPathSetupType: func() TLVInterface { return &PathSetupType{} }, + TLVExtendedAssociationID: func() TLVInterface { return &ExtendedAssociationID{} }, + TLVPathSetupTypeCapability: func() TLVInterface { return &PathSetupTypeCapability{} }, + TLVAssocTypeList: func() TLVInterface { return &AssocTypeList{} }, + TLVColor: func() TLVInterface { return &Color{} }, +} + +type StatefulPCECapability struct { + LSPUpdateCapability bool // 31 IncludeDBVersion bool // 30 - LspInstantiationCapability bool // 29 + LSPInstantiationCapability bool // 29 TriggeredResync bool // 28 - DeltaLspSyncCapability bool // 27 + DeltaLSPSyncCapability bool // 27 TriggeredInitialSync bool // 26 P2mpCapability bool // 25 - P2mpLspUpdateCapability bool // 24 - P2mpLspInstantiationCapability bool // 23 - LspSchedulingCapability bool // 22 - PdLspCapability bool // 21 + P2mpLSPUpdateCapability bool // 24 + P2mpLSPInstantiationCapability bool // 23 + LSPSchedulingCapability bool // 22 + PdLSPCapability bool // 21 ColorCapability bool // 20 PathRecomputationCapability bool // 19 StrictPathCapability bool // 18 Relax bool // 17 } -func (tlv *StatefulPceCapability) DecodeFromBytes(flags []uint8) error { - if len(flags) < 4 { - return fmt.Errorf("flags array is too short, expected at least 4 bytes but got %d", len(flags)) - } +const ( + LSPUpdateCapabilityBit uint32 = 0x01 + IncludeDBVersionCapabilityBit uint32 = 0x02 + LSPInstantiationCapabilityBit uint32 = 0x04 + TriggeredResyncCapabilityBit uint32 = 0x08 + DeltaLSPSyncCapabilityBit uint32 = 0x10 + TriggeredInitialSyncBit uint32 = 0x20 +) - flagMap := []struct { - field *bool - mask uint8 - index int - }{ - {&tlv.LspUpdateCapability, 0x01, 3}, - {&tlv.IncludeDBVersion, 0x02, 3}, - {&tlv.LspInstantiationCapability, 0x04, 3}, - {&tlv.TriggeredResync, 0x08, 3}, - {&tlv.DeltaLspSyncCapability, 0x10, 3}, - {&tlv.TriggeredInitialSync, 0x20, 3}, - {&tlv.P2mpCapability, 0x40, 3}, - {&tlv.P2mpLspUpdateCapability, 0x80, 3}, - {&tlv.P2mpLspInstantiationCapability, 0x01, 2}, - {&tlv.LspSchedulingCapability, 0x02, 2}, - {&tlv.PdLspCapability, 0x04, 2}, - {&tlv.ColorCapability, 0x08, 2}, - {&tlv.PathRecomputationCapability, 0x10, 2}, - {&tlv.StrictPathCapability, 0x20, 2}, - {&tlv.Relax, 0x40, 2}, - } +const definedStatefulPCEFlagsMask uint32 = LSPUpdateCapabilityBit | + IncludeDBVersionCapabilityBit | + LSPInstantiationCapabilityBit | + TriggeredResyncCapabilityBit | + DeltaLSPSyncCapabilityBit | + TriggeredInitialSyncBit - for _, f := range flagMap { - *f.field = (flags[f.index] & f.mask) != 0 +const ( + StatefulPCECapabilityFlagsIndex = 3 +) + +func (tlv *StatefulPCECapability) DecodeFromBytes(data []byte) error { + expectedLength := TLVHeaderLength + int(TLVStatefulPCECapabilityValueLength) + if len(data) < expectedLength { + return fmt.Errorf("data is too short: expected at least %d bytes, but got %d bytes for StatefulPCECapability", expectedLength, len(data)) } + flags := uint32(data[TLVHeaderLength+StatefulPCECapabilityFlagsIndex]) + tlv.ExtractCapabilities(flags) + return nil } -func setFlag(flags []uint8, index int, mask uint8, condition bool) { - if condition { - flags[index] = flags[index] | mask - } +func (tlv *StatefulPCECapability) Serialize() []byte { + flags := tlv.SetFlags() & definedStatefulPCEFlagsMask + return AppendByteSlices( + Uint16ToByteSlice(tlv.Type()), + Uint16ToByteSlice(TLVStatefulPCECapabilityValueLength), + Uint32ToByteSlice(flags), + ) } -func (tlv *StatefulPceCapability) Serialize() []uint8 { - buf := []uint8{} - - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) - buf = append(buf, typ...) - - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, TLV_STATEFUL_PCE_CAPABILITY_LENGTH) - buf = append(buf, length...) - - flags := make([]uint8, TLV_STATEFUL_PCE_CAPABILITY_LENGTH) - - setFlag(flags, 3, 0x01, tlv.LspUpdateCapability) - setFlag(flags, 3, 0x02, tlv.IncludeDBVersion) - setFlag(flags, 3, 0x04, tlv.LspInstantiationCapability) - setFlag(flags, 3, 0x08, tlv.TriggeredResync) - setFlag(flags, 3, 0x10, tlv.DeltaLspSyncCapability) - setFlag(flags, 3, 0x20, tlv.TriggeredInitialSync) - setFlag(flags, 3, 0x40, tlv.P2mpCapability) - setFlag(flags, 3, 0x80, tlv.P2mpLspUpdateCapability) - setFlag(flags, 2, 0x01, tlv.P2mpLspInstantiationCapability) - setFlag(flags, 2, 0x02, tlv.LspSchedulingCapability) - setFlag(flags, 2, 0x04, tlv.PdLspCapability) - setFlag(flags, 2, 0x08, tlv.ColorCapability) - setFlag(flags, 2, 0x10, tlv.PathRecomputationCapability) - setFlag(flags, 2, 0x20, tlv.StrictPathCapability) - setFlag(flags, 2, 0x40, tlv.Relax) - - buf = append(buf, flags...) +func (tlv *StatefulPCECapability) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddBool("lspUpdateCapability", tlv.LSPUpdateCapability) + enc.AddBool("includeDBVersion", tlv.IncludeDBVersion) + enc.AddBool("lspInstantiationCapability", tlv.LSPInstantiationCapability) + enc.AddBool("triggeredResync", tlv.TriggeredResync) + enc.AddBool("deltaLSPSyncCapability", tlv.DeltaLSPSyncCapability) + enc.AddBool("triggeredInitialSync", tlv.TriggeredInitialSync) + return nil +} - return buf +func (tlv *StatefulPCECapability) Type() TLVType { + return TLVStatefulPCECapability } -func (tlv *StatefulPceCapability) MarshalLogObject(enc zapcore.ObjectEncoder) error { - return nil +func (tlv *StatefulPCECapability) Len() uint16 { + return TLVHeaderLength + TLVStatefulPCECapabilityValueLength } -func (tlv *StatefulPceCapability) Type() uint16 { - return TLV_STATEFUL_PCE_CAPABILITY +func (tlv *StatefulPCECapability) ExtractCapabilities(flags uint32) { + tlv.LSPUpdateCapability = flags&LSPUpdateCapabilityBit != 0 + tlv.IncludeDBVersion = flags&IncludeDBVersionCapabilityBit != 0 + tlv.LSPInstantiationCapability = flags&LSPInstantiationCapabilityBit != 0 + tlv.TriggeredResync = flags&TriggeredResyncCapabilityBit != 0 + tlv.DeltaLSPSyncCapability = flags&DeltaLSPSyncCapabilityBit != 0 + tlv.TriggeredInitialSync = flags&TriggeredInitialSyncBit != 0 } -func (tlv *StatefulPceCapability) Len() uint16 { - return TL_LENGTH + TLV_STATEFUL_PCE_CAPABILITY_LENGTH +func (tlv *StatefulPCECapability) SetFlags() uint32 { + var flags uint32 + flags = SetBit(flags, LSPUpdateCapabilityBit, tlv.LSPUpdateCapability) + flags = SetBit(flags, IncludeDBVersionCapabilityBit, tlv.IncludeDBVersion) + flags = SetBit(flags, LSPInstantiationCapabilityBit, tlv.LSPInstantiationCapability) + flags = SetBit(flags, TriggeredResyncCapabilityBit, tlv.TriggeredResync) + flags = SetBit(flags, DeltaLSPSyncCapabilityBit, tlv.DeltaLSPSyncCapability) + flags = SetBit(flags, TriggeredInitialSyncBit, tlv.TriggeredInitialSync) + return flags } -func (tlv *StatefulPceCapability) CapStrings() []string { - ret := []string{} - ret = append(ret, "Stateful") - if tlv.LspUpdateCapability { +func (tlv *StatefulPCECapability) CapStrings() []string { + ret := []string{"Stateful"} + if tlv.LSPUpdateCapability { ret = append(ret, "Update") } if tlv.IncludeDBVersion { ret = append(ret, "Include-DB-Ver") } - if tlv.LspInstantiationCapability { - ret = append(ret, "Initiate") + if tlv.LSPInstantiationCapability { + ret = append(ret, "Instantiation") } if tlv.TriggeredResync { - ret = append(ret, "Triggerd-Resync") + ret = append(ret, "Triggered-Resync") } - if tlv.DeltaLspSyncCapability { + if tlv.DeltaLSPSyncCapability { ret = append(ret, "Delta-LSP-Sync") } if tlv.TriggeredInitialSync { - ret = append(ret, "Triggerd-init-sync") + ret = append(ret, "Triggered-Initial-Sync") } if tlv.ColorCapability { ret = append(ret, "Color") @@ -260,140 +361,242 @@ func (tlv *StatefulPceCapability) CapStrings() []string { return ret } +func NewStatefulPCECapability(flags uint32) *StatefulPCECapability { + tlv := &StatefulPCECapability{} + tlv.ExtractCapabilities(flags) + return tlv +} + type SymbolicPathName struct { Name string } -func (tlv *SymbolicPathName) DecodeFromBytes(data []uint8) error { - length := binary.BigEndian.Uint16(data[2:4]) - tlv.Name = string(data[4 : 4+length]) +func (tlv *SymbolicPathName) DecodeFromBytes(data []byte) error { + if len(data) < TLVHeaderLength { + return fmt.Errorf("data is too short: expected at least %d bytes, but got %d bytes for SymbolicPathName", TLVHeaderLength, len(data)) + } + + nameLen := binary.BigEndian.Uint16(data[2:4]) + totalLength := TLVHeaderLength + int(nameLen) + if len(data) < totalLength { + return fmt.Errorf("data is too short: expected at least %d bytes, but got %d bytes for SymbolicPathName", totalLength, len(data)) + } + + tlv.Name = string(data[TLVHeaderLength:totalLength]) + if !utf8.Valid([]byte(tlv.Name)) { + return fmt.Errorf("invalid UTF-8 sequence in SymbolicPathName") + } + return nil } -func (tlv *SymbolicPathName) Serialize() []uint8 { - buf := []uint8{} +func (tlv *SymbolicPathName) Serialize() []byte { + const alignment = 4 - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) - buf = append(buf, typ...) + nameLen := uint16(len(tlv.Name)) + padding := (alignment - (nameLen % alignment)) % alignment // Padding for 4-byte alignment - l := uint16(len(tlv.Name)) - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, l) - buf = append(buf, length...) + value := make([]byte, 0, int(nameLen)+int(padding)) + value = append(value, []byte(tlv.Name)...) + value = append(value, make([]byte, padding)...) + + return AppendByteSlices( + Uint16ToByteSlice(tlv.Type()), + Uint16ToByteSlice(nameLen), + value, + ) +} - buf = append(buf, []uint8(tlv.Name)...) +func (tlv *SymbolicPathName) Type() TLVType { + return TLVSymbolicPathName +} - if l%4 != 0 { - pad := make([]uint8, 4-l%4) - buf = append(buf, pad...) +func (tlv *SymbolicPathName) Len() uint16 { + length := uint16(len(tlv.Name)) + padding := uint16(0) + if mod := length % 4; mod != 0 { + padding = 4 - mod } - return buf + + return TLVHeaderLength + length + padding } func (tlv *SymbolicPathName) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddString("symbolicPathName", tlv.Name) return nil } -func (tlv *SymbolicPathName) Type() uint16 { - return TLV_SYMBOLIC_PATH_NAME +func NewSymbolicPathName(name string) *SymbolicPathName { + return &SymbolicPathName{Name: name} } -func (tlv *SymbolicPathName) Len() uint16 { - l := uint16(len(tlv.Name)) - padding := uint16(0) - if l%4 != 0 { - padding = (4 - l%4) - } - return TL_LENGTH + l + padding -} - -type IPv4LspIdentifiers struct { +type IPv4LSPIdentifiers struct { IPv4TunnelSenderAddress netip.Addr IPv4TunnelEndpointAddress netip.Addr - LspID uint16 + LSPID uint16 TunnelID uint16 + ExtendedTunnelID uint32 } -func (tlv *IPv4LspIdentifiers) DecodeFromBytes(data []uint8) error { +const ( + IPv4LSPIdentifiersTunnelSenderAddressIndex = 4 + IPv4LSPIdentifiersLSPIDIndex = 6 + IPv4LSPIdentifiersTunnelIDIndex = 8 + IPv4LSPIdentifiersExtendedTunnelIDIndex = 12 +) + +func (tlv *IPv4LSPIdentifiers) DecodeFromBytes(data []byte) error { + expectedLength := TLVHeaderLength + int(TLVIPv4LSPIdentifiersValueLength) + if len(data) != expectedLength { + return fmt.Errorf("data length mismatch: expected %d bytes, but got %d bytes for IPv4LSPIdentifiers", expectedLength, len(data)) + } + var ok bool - if tlv.IPv4TunnelSenderAddress, ok = netip.AddrFromSlice(data[12:16]); !ok { - tlv.IPv4TunnelSenderAddress, _ = netip.AddrFromSlice(data[4:8]) + if tlv.IPv4TunnelSenderAddress, ok = netip.AddrFromSlice(data[TLVHeaderLength : TLVHeaderLength+IPv4LSPIdentifiersTunnelSenderAddressIndex]); !ok { + return fmt.Errorf("failed to parse IPv4TunnelSenderAddress") } - tlv.LspID = binary.BigEndian.Uint16(data[8:10]) - tlv.TunnelID = binary.BigEndian.Uint16(data[10:12]) - tlv.IPv4TunnelEndpointAddress, _ = netip.AddrFromSlice(data[16:20]) + + tlv.LSPID = binary.BigEndian.Uint16(data[TLVHeaderLength+IPv4LSPIdentifiersTunnelSenderAddressIndex : TLVHeaderLength+IPv4LSPIdentifiersLSPIDIndex]) + tlv.TunnelID = binary.BigEndian.Uint16(data[TLVHeaderLength+IPv4LSPIdentifiersLSPIDIndex : TLVHeaderLength+IPv4LSPIdentifiersTunnelIDIndex]) + tlv.ExtendedTunnelID = binary.BigEndian.Uint32(data[TLVHeaderLength+IPv4LSPIdentifiersTunnelIDIndex : TLVHeaderLength+IPv4LSPIdentifiersExtendedTunnelIDIndex]) + + if tlv.IPv4TunnelEndpointAddress, ok = netip.AddrFromSlice(data[TLVHeaderLength+IPv4LSPIdentifiersExtendedTunnelIDIndex : TLVHeaderLength+TLVIPv4LSPIdentifiersValueLength]); !ok { + return fmt.Errorf("failed to parse IPv4TunnelEndpointAddress") + } + return nil } -func (tlv *IPv4LspIdentifiers) Serialize() []uint8 { - return nil +func (tlv *IPv4LSPIdentifiers) Serialize() []byte { + value := make([]byte, TLVIPv4LSPIdentifiersValueLength) + + copy(value[0:4], tlv.IPv4TunnelSenderAddress.AsSlice()) + binary.BigEndian.PutUint16(value[4:6], tlv.LSPID) + binary.BigEndian.PutUint16(value[6:8], tlv.TunnelID) + binary.BigEndian.PutUint32(value[8:12], tlv.ExtendedTunnelID) + copy(value[12:16], tlv.IPv4TunnelEndpointAddress.AsSlice()) + + return AppendByteSlices( + Uint16ToByteSlice(tlv.Type()), + Uint16ToByteSlice(TLVIPv4LSPIdentifiersValueLength), + value, + ) } -func (tlv *IPv4LspIdentifiers) MarshalLogObject(enc zapcore.ObjectEncoder) error { +func (tlv *IPv4LSPIdentifiers) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -func (tlv *IPv4LspIdentifiers) Type() uint16 { - return TLV_IPV4_LSP_IDENTIFIERS +func (tlv *IPv4LSPIdentifiers) Type() TLVType { + return TLVIPv4LSPIdentifiers } -func (tlv *IPv4LspIdentifiers) Len() uint16 { - return TL_LENGTH + TLV_IPV4_LSP_IDENTIFIERS_LENGTH +func (tlv *IPv4LSPIdentifiers) Len() uint16 { + return TLVHeaderLength + TLVIPv4LSPIdentifiersValueLength } -type IPv6LspIdentifiers struct { +func NewIPv4LSPIdentifiers(senderAddr, endpointAddr netip.Addr, lspID, tunnelID uint16, extendedTunnelID uint32) *IPv4LSPIdentifiers { + return &IPv4LSPIdentifiers{ + IPv4TunnelSenderAddress: senderAddr, + IPv4TunnelEndpointAddress: endpointAddr, + LSPID: lspID, + TunnelID: tunnelID, + ExtendedTunnelID: extendedTunnelID, + } +} + +type IPv6LSPIdentifiers struct { IPv6TunnelSenderAddress netip.Addr IPv6TunnelEndpointAddress netip.Addr - LspID uint16 + LSPID uint16 TunnelID uint16 + ExtendedTunnelID [16]byte } -func (tlv *IPv6LspIdentifiers) DecodeFromBytes(data []uint8) error { - tlv.IPv6TunnelSenderAddress, _ = netip.AddrFromSlice(data[4:20]) - tlv.LspID = binary.BigEndian.Uint16(data[20:22]) +func (tlv *IPv6LSPIdentifiers) DecodeFromBytes(data []byte) error { + expectedLength := TLVHeaderLength + int(TLVIPv6LSPIdentifiersValueLength) + if len(data) != expectedLength { + return fmt.Errorf("data length mismatch: expected %d bytes, but got %d bytes for IPv6LSPIdentifiers", expectedLength, len(data)) + } + + var ok bool + if tlv.IPv6TunnelSenderAddress, ok = netip.AddrFromSlice(data[4:20]); !ok { + return fmt.Errorf("failed to parse IPv6TunnelSenderAddress") + } + + tlv.LSPID = binary.BigEndian.Uint16(data[20:22]) tlv.TunnelID = binary.BigEndian.Uint16(data[22:24]) - tlv.IPv6TunnelEndpointAddress, _ = netip.AddrFromSlice(data[40:56]) + copy(tlv.ExtendedTunnelID[:], data[24:40]) + + if tlv.IPv6TunnelEndpointAddress, ok = netip.AddrFromSlice(data[40:56]); !ok { + return fmt.Errorf("failed to parse IPv6TunnelEndpointAddress") + } + return nil } -func (tlv *IPv6LspIdentifiers) Serialize() []uint8 { - return nil +func (tlv *IPv6LSPIdentifiers) Serialize() []byte { + buf := make([]byte, tlv.Len()) + + binary.BigEndian.PutUint16(buf[0:2], uint16(tlv.Type())) + binary.BigEndian.PutUint16(buf[2:4], TLVIPv6LSPIdentifiersValueLength) + copy(buf[4:20], tlv.IPv6TunnelSenderAddress.AsSlice()) + binary.BigEndian.PutUint16(buf[20:22], tlv.LSPID) + binary.BigEndian.PutUint16(buf[22:24], tlv.TunnelID) + copy(buf[24:40], tlv.ExtendedTunnelID[:]) + copy(buf[40:56], tlv.IPv6TunnelEndpointAddress.AsSlice()) + + return buf } -func (tlv *IPv6LspIdentifiers) MarshalLogObject(enc zapcore.ObjectEncoder) error { +func (tlv *IPv6LSPIdentifiers) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -func (tlv *IPv6LspIdentifiers) Type() uint16 { - return TLV_IPV6_LSP_IDENTIFIERS +func (tlv *IPv6LSPIdentifiers) Type() TLVType { + return TLVIPv6LSPIdentifiers } -func (tlv *IPv6LspIdentifiers) Len() uint16 { - return TL_LENGTH + TLV_IPV6_LSP_IDENTIFIERS_LENGTH +func (tlv *IPv6LSPIdentifiers) Len() uint16 { + return TLVHeaderLength + TLVIPv6LSPIdentifiersValueLength +} + +func NewIPv6LSPIdentifiers(senderAddr, endpointAddr netip.Addr, lspID, tunnelID uint16, extendedTunnelID [16]byte) *IPv6LSPIdentifiers { + return &IPv6LSPIdentifiers{ + IPv6TunnelSenderAddress: senderAddr, + IPv6TunnelEndpointAddress: endpointAddr, + LSPID: lspID, + TunnelID: tunnelID, + ExtendedTunnelID: extendedTunnelID, + } } type LSPDBVersion struct { VersionNumber uint64 } -func (tlv *LSPDBVersion) DecodeFromBytes(data []uint8) error { +func (tlv *LSPDBVersion) DecodeFromBytes(data []byte) error { + expectedLength := TLVHeaderLength + int(TLVLSPDBVersionValueLength) + if len(data) != expectedLength { + return fmt.Errorf("data length mismatch: expected %d bytes, but got %d bytes for LSPDBVersion", expectedLength, len(data)) + } + tlv.VersionNumber = binary.BigEndian.Uint64(data[4:12]) return nil } -func (tlv *LSPDBVersion) Serialize() []uint8 { - buf := []uint8{} +func (tlv *LSPDBVersion) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, TLV_LSP_DB_VERSION_LENGTH) + length := make([]byte, 2) + binary.BigEndian.PutUint16(length, TLVLSPDBVersionValueLength) buf = append(buf, length...) - val := make([]uint8, TLV_LSP_DB_VERSION_LENGTH) + val := make([]byte, TLVLSPDBVersionValueLength) binary.BigEndian.PutUint64(val, tlv.VersionNumber) buf = append(buf, val...) @@ -404,80 +607,143 @@ func (tlv *LSPDBVersion) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -func (tlv *LSPDBVersion) Type() uint16 { - return TLV_LSP_DB_VERSION +func (tlv *LSPDBVersion) Type() TLVType { + return TLVLSPDBVersion } func (tlv *LSPDBVersion) Len() uint16 { - return TL_LENGTH + TLV_LSP_DB_VERSION_LENGTH + return TLVHeaderLength + TLVLSPDBVersionValueLength } func (tlv *LSPDBVersion) CapStrings() []string { return []string{"LSP-DB-VERSION"} } -type SRPceCapability struct { - UnlimitedMSD bool - SupportNAI bool - MaximumSidDepth uint8 +func NewLSPDBVersion(version uint64) *LSPDBVersion { + return &LSPDBVersion{ + VersionNumber: version, + } +} + +type SRPCECapability struct { + HasUnlimitedMaxSIDDepth bool + IsNAISupported bool + MaximumSidDepth uint8 } -func (tlv *SRPceCapability) DecodeFromBytes(data []uint8) error { - tlv.UnlimitedMSD = (data[6] & 0x01) != 0 - tlv.SupportNAI = (data[6] & 0x02) != 0 - tlv.MaximumSidDepth = data[7] +const ( + UnlimitedMaximumSIDDepthFlag byte = 0x01 + NAISupportedFlag byte = 0x02 +) + +const ( + SRPCECapabilityFlagsIndex = 2 + SRPCECapabilityMSDIndex = 3 +) + +func (tlv *SRPCECapability) DecodeFromBytes(data []byte) error { + expectedLength := TLVHeaderLength + int(TLVSRPCECapabilityValueLength) + if len(data) != expectedLength { + return fmt.Errorf("data length mismatch: expected %d bytes, but got %d bytes for SRPCECapability", expectedLength, len(data)) + } + + // Extract TLV value field (after 4-byte TLV header) + val := data[TLVHeaderLength:] + + if len(val) != int(TLVSRPCECapabilityValueLength) { + return fmt.Errorf("invalid value length for SRPCECapability: expected %d bytes, but got %d bytes", TLVSRPCECapabilityValueLength, len(val)) + } + + flags := val[SRPCECapabilityFlagsIndex] + tlv.HasUnlimitedMaxSIDDepth = IsBitSet(flags, UnlimitedMaximumSIDDepthFlag) + tlv.IsNAISupported = IsBitSet(flags, NAISupportedFlag) + tlv.MaximumSidDepth = val[SRPCECapabilityMSDIndex] + return nil } -func (tlv *SRPceCapability) Serialize() []uint8 { - buf := []uint8{} +func (tlv *SRPCECapability) Serialize() []byte { + buf := make([]byte, 0, TLVHeaderLength+TLVSRPCECapabilityValueLength) - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, TLV_SR_PCE_CAPABILITY_LENGTH) + length := make([]byte, 2) + binary.BigEndian.PutUint16(length, TLVSRPCECapabilityValueLength) buf = append(buf, length...) - val := make([]uint8, TLV_SR_PCE_CAPABILITY_LENGTH) - if tlv.UnlimitedMSD { - val[2] = val[2] | 0x01 - } - if tlv.SupportNAI { - val[2] = val[2] | 0x02 - } - val[3] = tlv.MaximumSidDepth + val := make([]byte, TLVSRPCECapabilityValueLength) + val[SRPCECapabilityFlagsIndex] = SetBit(val[SRPCECapabilityFlagsIndex], UnlimitedMaximumSIDDepthFlag, tlv.HasUnlimitedMaxSIDDepth) + val[SRPCECapabilityFlagsIndex] = SetBit(val[SRPCECapabilityFlagsIndex], NAISupportedFlag, tlv.IsNAISupported) + val[SRPCECapabilityMSDIndex] = tlv.MaximumSidDepth buf = append(buf, val...) return buf } -func (tlv *SRPceCapability) MarshalLogObject(enc zapcore.ObjectEncoder) error { +func (tlv *SRPCECapability) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddBool("unlimited_max_sid_depth", tlv.HasUnlimitedMaxSIDDepth) + enc.AddBool("nai_is_supported", tlv.IsNAISupported) + enc.AddUint8("maximum_sid_depth", tlv.MaximumSidDepth) return nil } -func (tlv *SRPceCapability) Type() uint16 { - return TLV_SR_PCE_CAPABILITY +func (tlv *SRPCECapability) Type() TLVType { + return TLVSRPCECapability } -func (tlv *SRPceCapability) Len() uint16 { - return TL_LENGTH + TLV_SR_PCE_CAPABILITY_LENGTH +func (tlv *SRPCECapability) Len() uint16 { + return TLVHeaderLength + TLVSRPCECapabilityValueLength } -func (tlv *SRPceCapability) CapStrings() []string { - return []string{"SR-TE"} +func (tlv *SRPCECapability) CapStrings() []string { + var ret []string + if tlv.HasUnlimitedMaxSIDDepth { + ret = append(ret, "Unlimited-SID-Depth") + } + if tlv.IsNAISupported { + ret = append(ret, "NAI-Supported") + } + return ret +} + +func NewSRPCECapability(hasUnlimitedMaxSIDDepth bool, isNAISupported bool, maximumSidDepth uint8) *SRPCECapability { + return &SRPCECapability{ + HasUnlimitedMaxSIDDepth: hasUnlimitedMaxSIDDepth, + IsNAISupported: isNAISupported, + MaximumSidDepth: maximumSidDepth, + } } type Pst uint8 const ( - PST_RSVP_TE Pst = 0x0 - PST_SR_TE Pst = 0x1 - PST_PCECC_TE Pst = 0x2 - PST_SRV6_TE Pst = 0x3 + PathSetupTypeRSVPTE Pst = 0x00 + PathSetupTypeSRTE Pst = 0x01 + PathSetupTypePCECCTE Pst = 0x02 + PathSetupTypeSRv6TE Pst = 0x03 + PathSetupTypeIPTE Pst = 0x04 ) +var pathSetupDescriptions = map[Pst]struct { + Description string + Reference string +}{ + PathSetupTypeRSVPTE: {"Path is set up using the RSVP-TE signaling protocol", "RFC8408"}, + PathSetupTypeSRTE: {"Traffic engineering path is set up using Segment Routing", "RFC8664"}, + PathSetupTypePCECCTE: {"Traffic engineering path is set up using PCECC mode", "RFC9050"}, + PathSetupTypeSRv6TE: {"Traffic engineering path is set up using SRv6", "RFC9603"}, + PathSetupTypeIPTE: {"Native IP TE Path", "RFC9757"}, +} + +func (pst Pst) String() string { + if desc, found := pathSetupDescriptions[pst]; found { + return fmt.Sprintf("%s (%s)", desc.Description, desc.Reference) + } + return fmt.Sprintf("Unknown PathSetupType (0x%02x)", uint16(pst)) +} + type Psts []Pst func (ts Psts) MarshalJSON() ([]byte, error) { @@ -485,7 +751,11 @@ func (ts Psts) MarshalJSON() ([]byte, error) { if ts == nil { result = "null" } else { - result = strings.Join(strings.Fields(fmt.Sprintf("%d", ts)), ",") + var values []string + for _, pst := range ts { + values = append(values, fmt.Sprintf("%d", pst)) + } + result = strings.Join(values, ",") } return []byte(result), nil } @@ -494,24 +764,33 @@ type PathSetupType struct { PathSetupType Pst } -func (tlv *PathSetupType) DecodeFromBytes(data []uint8) error { - tlv.PathSetupType = Pst(data[7]) +const ( + PathSetupTypePathSetupTypeIndex = 3 +) + +func (tlv *PathSetupType) DecodeFromBytes(data []byte) error { + expectedLength := TLVHeaderLength + int(TLVPathSetupTypeValueLength) + if len(data) != expectedLength { + return fmt.Errorf("data length mismatch: expected %d bytes, but got %d bytes for PathSetupType", expectedLength, len(data)) + } + + tlv.PathSetupType = Pst(data[TLVHeaderLength+PathSetupTypePathSetupTypeIndex]) return nil } -func (tlv *PathSetupType) Serialize() []uint8 { - buf := []uint8{} +func (tlv *PathSetupType) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, TLV_PATH_SETUP_TYPE_LENGTH) + length := make([]byte, 2) + binary.BigEndian.PutUint16(length, TLVPathSetupTypeValueLength) buf = append(buf, length...) - val := make([]uint8, TLV_PATH_SETUP_TYPE_LENGTH) - val[3] = uint8(tlv.PathSetupType) + val := make([]byte, TLVPathSetupTypeValueLength) + val[PathSetupTypePathSetupTypeIndex] = byte(tlv.PathSetupType) buf = append(buf, val...) return buf @@ -521,12 +800,18 @@ func (tlv *PathSetupType) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -func (tlv *PathSetupType) Type() uint16 { - return TLV_PATH_SETUP_TYPE +func (tlv *PathSetupType) Type() TLVType { + return TLVPathSetupType } func (tlv *PathSetupType) Len() uint16 { - return TL_LENGTH + TLV_PATH_SETUP_TYPE_LENGTH + return TLVHeaderLength + TLVPathSetupTypeValueLength +} + +func NewPathSetupType(pst Pst) *PathSetupType { + return &PathSetupType{ + PathSetupType: pst, + } } type ExtendedAssociationID struct { @@ -534,37 +819,37 @@ type ExtendedAssociationID struct { Endpoint netip.Addr } -func (tlv *ExtendedAssociationID) DecodeFromBytes(data []uint8) error { - l := binary.BigEndian.Uint16(data[2:4]) +func (tlv *ExtendedAssociationID) DecodeFromBytes(data []byte) error { + length := binary.BigEndian.Uint16(data[2:4]) tlv.Color = binary.BigEndian.Uint32(data[4:8]) - switch l { - case TLV_EXTENDED_ASSOCIATION_ID_IPV4_LENGTH: + switch length { + case TLVExtendedAssociationIDIPv4ValueLength: tlv.Endpoint, _ = netip.AddrFromSlice(data[8:12]) - case TLV_EXTENDED_ASSOCIATION_ID_IPV6_LENGTH: + case TLVExtendedAssociationIDIPv6ValueLength: tlv.Endpoint, _ = netip.AddrFromSlice(data[8:24]) } return nil } -func (tlv *ExtendedAssociationID) Serialize() []uint8 { - buf := []uint8{} +func (tlv *ExtendedAssociationID) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - length := make([]uint8, 2) + length := make([]byte, 2) if tlv.Endpoint.Is4() { - binary.BigEndian.PutUint16(length, TLV_EXTENDED_ASSOCIATION_ID_IPV4_LENGTH) + binary.BigEndian.PutUint16(length, TLVExtendedAssociationIDIPv4ValueLength) } else if tlv.Endpoint.Is6() { - binary.BigEndian.PutUint16(length, TLV_EXTENDED_ASSOCIATION_ID_IPV6_LENGTH) + binary.BigEndian.PutUint16(length, TLVExtendedAssociationIDIPv6ValueLength) } buf = append(buf, length...) - color := make([]uint8, 4) + color := make([]byte, 4) binary.BigEndian.PutUint32(color, tlv.Color) buf = append(buf, color...) @@ -576,15 +861,15 @@ func (tlv *ExtendedAssociationID) MarshalLogObject(enc zapcore.ObjectEncoder) er return nil } -func (tlv *ExtendedAssociationID) Type() uint16 { - return TLV_EXTENDED_ASSOCIATION_ID +func (tlv *ExtendedAssociationID) Type() TLVType { + return TLVExtendedAssociationID } func (tlv *ExtendedAssociationID) Len() uint16 { if tlv.Endpoint.Is4() { - return TL_LENGTH + TLV_EXTENDED_ASSOCIATION_ID_IPV4_LENGTH + return TLVHeaderLength + TLVExtendedAssociationIDIPv4ValueLength } else if tlv.Endpoint.Is6() { - return TL_LENGTH + TLV_EXTENDED_ASSOCIATION_ID_IPV6_LENGTH + return TLVHeaderLength + TLVExtendedAssociationIDIPv6ValueLength } return 0 @@ -595,8 +880,8 @@ type PathSetupTypeCapability struct { SubTLVs []TLVInterface } -func (tlv *PathSetupTypeCapability) DecodeFromBytes(data []uint8) error { - l := binary.BigEndian.Uint16(data[2:4]) +func (tlv *PathSetupTypeCapability) DecodeFromBytes(data []byte) error { + length := binary.BigEndian.Uint16(data[2:4]) pstNum := int(data[7]) for i := 0; i < pstNum; i++ { @@ -607,45 +892,45 @@ func (tlv *PathSetupTypeCapability) DecodeFromBytes(data []uint8) error { pstNum += 4 - (pstNum % 4) // padding byte } var err error - tlv.SubTLVs, err = DecodeTLVs(data[8+pstNum : TL_LENGTH+l]) // 8 byte: Type&Length (4 byte) + Reserve&pstNum (4 byte) + tlv.SubTLVs, err = DecodeTLVs(data[8+pstNum : TLVHeaderLength+length]) // 8 byte: Type&Length (4 byte) + Reserve&pstNum (4 byte) if err != nil { return err } return nil } -func (tlv *PathSetupTypeCapability) Serialize() []uint8 { - buf := []uint8{} +func (tlv *PathSetupTypeCapability) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) numOfPst := uint16(len(tlv.PathSetupTypes)) - l := uint16(4) // 4 byte: reserve & num of PSTs field - l += numOfPst + length := uint16(4) // 4 byte: reserve & num of PSTs field + length += numOfPst if numOfPst%4 != 0 { - l += 4 - (numOfPst % 4) + length += 4 - (numOfPst % 4) } for _, subTLV := range tlv.SubTLVs { - l += subTLV.Len() + length += subTLV.Len() } - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, l) - buf = append(buf, length...) + lengthBytes := make([]byte, 2) + binary.BigEndian.PutUint16(lengthBytes, length) + buf = append(buf, lengthBytes...) - var val []uint8 + var val []byte if numOfPst%4 == 0 { - val = make([]uint8, 4+numOfPst) // 4 byte: Reserve & Num of PST + val = make([]byte, 4+numOfPst) // 4 byte: Reserve & Num of PST } else { - val = make([]uint8, 4+numOfPst+(4-(numOfPst%4))) // 4 byte: Reserve & Num of PST + val = make([]byte, 4+numOfPst+(4-(numOfPst%4))) // 4 byte: Reserve & Num of PST } - val[3] = uint8(numOfPst) + val[3] = byte(numOfPst) for i, pst := range tlv.PathSetupTypes { - val[4+i] = uint8(pst) + val[4+i] = byte(pst) } for _, subTLV := range tlv.SubTLVs { @@ -659,29 +944,29 @@ func (tlv *PathSetupTypeCapability) MarshalLogObject(enc zapcore.ObjectEncoder) return nil } -func (tlv *PathSetupTypeCapability) Type() uint16 { - return TLV_PATH_SETUP_TYPE_CAPABILITY +func (tlv *PathSetupTypeCapability) Type() TLVType { + return TLVPathSetupTypeCapability } func (tlv *PathSetupTypeCapability) Len() uint16 { - l := uint16(4) // 4 byte: reserve & num of PSTs field + length := uint16(4) // 4 byte: reserve & num of PSTs field numOfPst := uint16(len(tlv.PathSetupTypes)) - l += numOfPst + length += numOfPst if numOfPst%4 != 0 { - l += 4 - (numOfPst % 4) + length += 4 - (numOfPst % 4) } for _, subTLV := range tlv.SubTLVs { - l += subTLV.Len() + length += subTLV.Len() } - return TL_LENGTH + l + return TLVHeaderLength + length } func (tlv *PathSetupTypeCapability) CapStrings() []string { ret := []string{} - if slices.Contains(tlv.PathSetupTypes, PST_SR_TE) { + if slices.Contains(tlv.PathSetupTypes, PathSetupTypeSRTE) { ret = append(ret, "SR-TE") } - if slices.Contains(tlv.PathSetupTypes, PST_SRV6_TE) { + if slices.Contains(tlv.PathSetupTypes, PathSetupTypeSRv6TE) { ret = append(ret, "SRv6-TE") } return ret @@ -690,21 +975,37 @@ func (tlv *PathSetupTypeCapability) CapStrings() []string { type AssocType uint16 const ( - AT_RESERVED AssocType = 0x00 - AT_PATH_PROTECTION_ASSOCIATION AssocType = 0x01 - AT_DISCOINT_ASSOCIATION AssocType = 0x02 - AT_POLICY_ASSOCIATION AssocType = 0x03 - AT_SINGLE_SIDED_BIDIRECTIONAL_LSP_ASSOCIATION AssocType = 0x04 - AT_DOUBLE_SIDED_BIDIRECTIONAL_LSP_ASSOCIATION AssocType = 0x05 - AT_SR_POLICY_ASSOCIATION AssocType = 0x06 - AT_VN_ASSOCIATION_TYPE AssocType = 0x07 + AssocTypePathProtectionAssociation AssocType = 0x01 + AssocTypeDisjointAssociation AssocType = 0x02 + AssocTypePolicyAssociation AssocType = 0x03 + AssocTypeSingleSidedBidirectionalLSPAssociation AssocType = 0x04 + AssocTypeDoubleSidedBidirectionalLSPAssociation AssocType = 0x05 + AssocTypeSRPolicyAssociation AssocType = 0x06 + AssocTypeVnAssociationType AssocType = 0x07 ) +var assocTypeNames = map[AssocType]string{ + AssocTypePathProtectionAssociation: "Path Protection Association", + AssocTypeDisjointAssociation: "Disjoint Association", + AssocTypePolicyAssociation: "Policy Association", + AssocTypeSingleSidedBidirectionalLSPAssociation: "Single Sided Bidirectional LSP Association", + AssocTypeDoubleSidedBidirectionalLSPAssociation: "Double Sided Bidirectional LSP Association", + AssocTypeSRPolicyAssociation: "SR Policy Association", + AssocTypeVnAssociationType: "VN Association Type", +} + +func (at AssocType) String() string { + if name, ok := assocTypeNames[at]; ok { + return name + } + return fmt.Sprintf("Unknown AssocType (0x%04x)", uint16(at)) +} + type AssocTypeList struct { AssocTypes []AssocType } -func (tlv *AssocTypeList) DecodeFromBytes(data []uint8) error { +func (tlv *AssocTypeList) DecodeFromBytes(data []byte) error { AssocTypeNum := binary.BigEndian.Uint16(data[2:4]) / 2 for i := 0; i < int(AssocTypeNum); i++ { at := binary.BigEndian.Uint16(data[4+2*i : 6+2*i]) @@ -713,25 +1014,25 @@ func (tlv *AssocTypeList) DecodeFromBytes(data []uint8) error { return nil } -func (tlv *AssocTypeList) Serialize() []uint8 { - buf := []uint8{} +func (tlv *AssocTypeList) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - l := uint16(len(tlv.AssocTypes)) * 2 - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, l) - buf = append(buf, length...) + length := uint16(len(tlv.AssocTypes)) * 2 + lengthBytes := make([]byte, 2) + binary.BigEndian.PutUint16(lengthBytes, length) + buf = append(buf, lengthBytes...) for _, at := range tlv.AssocTypes { - binAt := make([]uint8, 2) + binAt := make([]byte, 2) binary.BigEndian.PutUint16(binAt, uint16(at)) buf = append(buf, binAt...) } - if l%4 != 0 { - pad := make([]uint8, 4-(l%4)) + if length%4 != 0 { + pad := make([]byte, 4-(length%4)) buf = append(buf, pad...) } return buf @@ -741,17 +1042,17 @@ func (tlv *AssocTypeList) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -func (tlv *AssocTypeList) Type() uint16 { - return TLV_ASSOC_TYPE_LIST +func (tlv *AssocTypeList) Type() TLVType { + return TLVAssocTypeList } func (tlv *AssocTypeList) Len() uint16 { - l := uint16(len(tlv.AssocTypes)) * 2 + length := uint16(len(tlv.AssocTypes)) * 2 padding := uint16(0) - if l%4 != 0 { + if length%4 != 0 { padding = 2 } - return TL_LENGTH + l + padding + return TLVHeaderLength + length + padding } func (tlv *AssocTypeList) CapStrings() []string { @@ -762,20 +1063,20 @@ type SRPolicyCandidatePathIdentifier struct { OriginatorAddr netip.Addr // After DecodeFromBytes, even ipv4 addresses are assigned in ipv6 format } -func (tlv *SRPolicyCandidatePathIdentifier) DecodeFromBytes(data []uint8) error { +func (tlv *SRPolicyCandidatePathIdentifier) DecodeFromBytes(data []byte) error { tlv.OriginatorAddr, _ = netip.AddrFromSlice(data[12:28]) return nil } -func (tlv *SRPolicyCandidatePathIdentifier) Serialize() []uint8 { - buf := []uint8{} +func (tlv *SRPolicyCandidatePathIdentifier) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, TLV_SRPOLICY_CPATH_ID_LENGTH) + length := make([]byte, 2) + binary.BigEndian.PutUint16(length, TLVSRPolicyCPathIDValueLength) buf = append(buf, length...) buf = append(buf, 0x0a) // protocol origin, PCEP = 10 @@ -797,35 +1098,35 @@ func (tlv *SRPolicyCandidatePathIdentifier) MarshalLogObject(enc zapcore.ObjectE return nil } -func (tlv *SRPolicyCandidatePathIdentifier) Type() uint16 { - return TLV_SRPOLICY_CPATH_ID +func (tlv *SRPolicyCandidatePathIdentifier) Type() TLVType { + return TLVSRPolicyCPathID } func (tlv *SRPolicyCandidatePathIdentifier) Len() uint16 { - return TL_LENGTH + TLV_SRPOLICY_CPATH_ID_LENGTH + return TLVHeaderLength + TLVSRPolicyCPathIDValueLength } type SRPolicyCandidatePathPreference struct { Preference uint32 } -func (tlv *SRPolicyCandidatePathPreference) DecodeFromBytes(data []uint8) error { +func (tlv *SRPolicyCandidatePathPreference) DecodeFromBytes(data []byte) error { tlv.Preference = binary.BigEndian.Uint32(data[4:8]) return nil } -func (tlv *SRPolicyCandidatePathPreference) Serialize() []uint8 { - buf := []uint8{} +func (tlv *SRPolicyCandidatePathPreference) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, TLV_SRPOLICY_CPATH_PREFERENCE_LENGTH) + length := make([]byte, 2) + binary.BigEndian.PutUint16(length, TLVSRPolicyCPathPreferenceValueLength) buf = append(buf, length...) - preference := make([]uint8, 4) + preference := make([]byte, 4) binary.BigEndian.PutUint32(preference, tlv.Preference) buf = append(buf, preference...) @@ -836,35 +1137,35 @@ func (tlv *SRPolicyCandidatePathPreference) MarshalLogObject(enc zapcore.ObjectE return nil } -func (tlv *SRPolicyCandidatePathPreference) Type() uint16 { - return TLV_SRPOLICY_CPATH_PREFERENCE +func (tlv *SRPolicyCandidatePathPreference) Type() TLVType { + return TLVSRPolicyCPathPreference } func (tlv *SRPolicyCandidatePathPreference) Len() uint16 { - return TL_LENGTH + TLV_SRPOLICY_CPATH_PREFERENCE_LENGTH + return TLVHeaderLength + TLVSRPolicyCPathPreferenceValueLength } type Color struct { Color uint32 } -func (tlv *Color) DecodeFromBytes(data []uint8) error { +func (tlv *Color) DecodeFromBytes(data []byte) error { tlv.Color = binary.BigEndian.Uint32(data[4:8]) return nil } -func (tlv *Color) Serialize() []uint8 { - buf := []uint8{} +func (tlv *Color) Serialize() []byte { + buf := []byte{} - typ := make([]uint8, 2) - binary.BigEndian.PutUint16(typ, tlv.Type()) + typ := make([]byte, 2) + binary.BigEndian.PutUint16(typ, uint16(tlv.Type())) buf = append(buf, typ...) - length := make([]uint8, 2) - binary.BigEndian.PutUint16(length, TLV_COLOR) + length := make([]byte, 2) + binary.BigEndian.PutUint16(length, TLVColorValueLength) buf = append(buf, length...) - color := make([]uint8, 4) + color := make([]byte, 4) binary.BigEndian.PutUint32(color, tlv.Color) buf = append(buf, color...) @@ -875,52 +1176,52 @@ func (tlv *Color) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -func (tlv *Color) Type() uint16 { - return TLV_COLOR +func (tlv *Color) Type() TLVType { + return TLVColor } func (tlv *Color) Len() uint16 { - return TL_LENGTH + TLV_COLOR_LENGTH + return TLVHeaderLength + TLVColorValueLength } type UndefinedTLV struct { - Typ uint16 + Typ TLVType Length uint16 - Value []uint8 + Value []byte } -func (tlv *UndefinedTLV) DecodeFromBytes(data []uint8) error { - tlv.Typ = binary.BigEndian.Uint16(data[0:2]) +func (tlv *UndefinedTLV) DecodeFromBytes(data []byte) error { + tlv.Typ = TLVType(binary.BigEndian.Uint16(data[0:2])) tlv.Length = binary.BigEndian.Uint16(data[2:4]) tlv.Value = data[4 : 4+tlv.Length] return nil } -func (tlv *UndefinedTLV) Serialize() []uint8 { - bytePcepTLV := []uint8{} +func (tlv *UndefinedTLV) Serialize() []byte { + bytePCEPTLV := []byte{} - byteTLVType := make([]uint8, 2) - binary.BigEndian.PutUint16(byteTLVType, tlv.Typ) - bytePcepTLV = append(bytePcepTLV, byteTLVType...) // Type (2byte) + byteTLVType := make([]byte, 2) + binary.BigEndian.PutUint16(byteTLVType, uint16(tlv.Typ)) + bytePCEPTLV = append(bytePCEPTLV, byteTLVType...) // Type (2byte) - byteTLVLength := make([]uint8, 2) + byteTLVLength := make([]byte, 2) binary.BigEndian.PutUint16(byteTLVLength, tlv.Length) - bytePcepTLV = append(bytePcepTLV, byteTLVLength...) // Length (2byte) + bytePCEPTLV = append(bytePCEPTLV, byteTLVLength...) // Length (2byte) - bytePcepTLV = append(bytePcepTLV, tlv.Value...) // Value (Length byte) + bytePCEPTLV = append(bytePCEPTLV, tlv.Value...) // Value (Length byte) if padding := tlv.Length % 4; padding != 0 { - bytePadding := make([]uint8, 4-padding) - bytePcepTLV = append(bytePcepTLV, bytePadding...) + bytePadding := make([]byte, 4-padding) + bytePCEPTLV = append(bytePCEPTLV, bytePadding...) } - return bytePcepTLV + return bytePCEPTLV } func (tlv *UndefinedTLV) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -func (tlv *UndefinedTLV) Type() uint16 { +func (tlv *UndefinedTLV) Type() TLVType { return tlv.Typ } @@ -929,26 +1230,26 @@ func (tlv *UndefinedTLV) Len() uint16 { if tlv.Length%4 != 0 { padding = (4 - tlv.Length%4) } - return TL_LENGTH + tlv.Length + padding + return TLVHeaderLength + tlv.Length + padding } func (tlv *UndefinedTLV) CapStrings() []string { - cap := "unknown_type_" + strconv.FormatInt(int64(tlv.Typ), 10) - return []string{cap} + capStr := "unknown_type_" + strconv.FormatInt(int64(tlv.Typ), 10) + return []string{capStr} } func (tlv *UndefinedTLV) SetLength() { tlv.Length = uint16(len(tlv.Value)) } -func DecodeTLV(data []uint8) (TLVInterface, error) { +func DecodeTLV(data []byte) (TLVInterface, error) { if len(data) < 2 { return nil, errors.New("insufficient data to read TLV type") } tlvType := binary.BigEndian.Uint16(data[0:2]) - if createTLV, found := tlvMap[tlvType]; found { + if createTLV, found := tlvMap[TLVType(tlvType)]; found { tlv := createTLV() if err := tlv.DecodeFromBytes(data); err != nil { return nil, fmt.Errorf("error decoding TLV type %x: %w", tlvType, err) @@ -964,23 +1265,31 @@ func DecodeTLV(data []uint8) (TLVInterface, error) { return tlv, nil } -func DecodeTLVs(data []uint8) ([]TLVInterface, error) { +func DecodeTLVs(data []byte) ([]TLVInterface, error) { var tlvs []TLVInterface + offset := 0 - for len(data) > 0 { - tlv, err := DecodeTLV(data) - if err != nil { - return nil, err + for offset < len(data) { + if len(data[offset:]) < 4 { + return nil, fmt.Errorf("truncated TLV header at offset %d", offset) } - tlvs = append(tlvs, tlv) + tlvType := binary.BigEndian.Uint16(data[offset : offset+2]) + valueLen := int(binary.BigEndian.Uint16(data[offset+2 : offset+4])) + totalLen := 4 + valueLen - tlvLen := int(tlv.Len()) - if len(data) < tlvLen { - return nil, fmt.Errorf("expected TLV length %d but found %d bytes remaining", tlvLen, len(data)) + if len(data[offset:]) < totalLen { + return nil, fmt.Errorf("truncated TLV value for type 0x%x at offset %d", tlvType, offset) } - data = data[tlvLen:] + tlv, err := DecodeTLV(data[offset : offset+totalLen]) + if err != nil { + return nil, fmt.Errorf("error decoding TLV type 0x%x: %w", tlvType, err) + } + + tlvs = append(tlvs, tlv) + paddedLen := (totalLen + 3) & ^3 + offset += paddedLen } return tlvs, nil diff --git a/pkg/packet/pcep/tlv_test.go b/pkg/packet/pcep/tlv_test.go new file mode 100644 index 00000000..3784d4de --- /dev/null +++ b/pkg/packet/pcep/tlv_test.go @@ -0,0 +1,610 @@ +// Copyright (c) 2022 NTT Communications Corporation +// +// This software is released under the MIT License. +// see https://github.com/nttcom/pola/blob/main/LICENSE + +package pcep + +import ( + "net/netip" + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap/zapcore" +) + +func TestStatefulPCECapability_DecodeFromBytes(t *testing.T) { + tests := []struct { + name string + input []uint8 + expected *StatefulPCECapability + err bool + }{ + { + name: "Single capability: LSP Update enabled", + input: NewStatefulPCECapability(0x01).Serialize(), + expected: NewStatefulPCECapability(0x01), + err: false, + }, + { + name: "All capabilities enabled", + input: NewStatefulPCECapability(0x3F).Serialize(), + expected: NewStatefulPCECapability(0x3F), + err: false, + }, + { + name: "Input too short (missing TLV body)", + input: []uint8{uint8(TLVStatefulPCECapability >> 8), uint8(TLVStatefulPCECapability & 0xFF), 0x00, 0x04}, // type=0x0010, length=4, but body missing + expected: nil, + err: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var actual StatefulPCECapability + err := actual.DecodeFromBytes(tt.input) + if tt.err { + assert.Error(t, err, "expected error for input: %v", tt.input) + } else { + assert.NoError(t, err, "unexpected error for input: %v", tt.input) + assert.Equal(t, *tt.expected, actual, "decoded capability mismatch") + } + }) + } +} + +func TestStatefulPCECapability_Serialize(t *testing.T) { + tests := []struct { + name string + bits uint32 + }{ + { + name: "LSP Update Capability enabled", + bits: 0x01, + }, + { + name: "All capabilities enabled", + bits: 0x3F, + }, + { + name: "No capabilities enabled", + bits: 0x00, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tlv := NewStatefulPCECapability(tt.bits) + expected := AppendByteSlices( + Uint16ToByteSlice(TLVStatefulPCECapability), + Uint16ToByteSlice(TLVStatefulPCECapabilityValueLength), + Uint32ToByteSlice(tlv.SetFlags()), + ) + + assert.Equal(t, expected, tlv.Serialize(), "serialized output mismatch") + }) + } +} + +func TestStatefulPCECapability_MarshalLogObject(t *testing.T) { + tests := []struct { + name string + tlv *StatefulPCECapability + expected bool + }{ + { + name: "LSP Update Capability enabled", + tlv: &StatefulPCECapability{ + LSPUpdateCapability: true, + }, + expected: true, + }, + { + name: "LSP Update Capability disabled", + tlv: &StatefulPCECapability{ + LSPUpdateCapability: false, + }, + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + enc := zapcore.NewMapObjectEncoder() + err := tt.tlv.MarshalLogObject(enc) + + assert.NoError(t, err, "expected no error while marshaling log object") + assert.Equal(t, tt.expected, enc.Fields["lspUpdateCapability"], "field 'lspUpdateCapability' mismatch") + }) + } +} + +func TestStatefulPCECapability_CapStrings(t *testing.T) { + tests := []struct { + name string + bits uint32 + expected []string + }{ + { + name: "All capabilities enabled", + bits: 0x3F, + expected: []string{"Stateful", "Update", "Include-DB-Ver", "Instantiation", "Triggered-Resync", "Delta-LSP-Sync", "Triggered-Initial-Sync"}, + }, + { + name: "No capabilities enabled", + bits: 0x00, + expected: []string{"Stateful"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + input := NewStatefulPCECapability(tt.bits) + assert.ElementsMatch(t, tt.expected, input.CapStrings(), "capabilities mismatch") + }) + } +} + +func TestSymbolicPathName_DecodeFromBytes(t *testing.T) { + tests := []struct { + name string + input []uint8 + expected *SymbolicPathName + err bool + }{ + { + name: "Valid Symbolic Path Name", + input: NewSymbolicPathName("Test").Serialize(), + expected: NewSymbolicPathName("Test"), + err: false, + }, + { + name: "Invalid input (too short data)", + input: []byte{0x00, 0x11, 0x00, 0x02, 'T'}, // Input too short for valid decoding + expected: NewSymbolicPathName(""), + err: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tlv SymbolicPathName + err := tlv.DecodeFromBytes(tt.input) + if tt.err { + assert.Error(t, err, "expected error for input: %v", tt.input) + } else { + assert.NoError(t, err, "unexpected error for input: %v", tt.input) + assert.Equal(t, tt.expected, &tlv) + } + }) + } +} + +func TestSymbolicPathName_Serialize(t *testing.T) { + tests := []struct { + name string + input *SymbolicPathName + expected []uint8 + }{ + { + name: "Valid Symbolic Path Name", + input: NewSymbolicPathName("Test"), + expected: NewSymbolicPathName("Test").Serialize(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Serialize()) + }) + } +} + +func TestSymbolicPathName_Len(t *testing.T) { + tests := []struct { + name string + input *SymbolicPathName + expected uint16 + }{ + { + name: "Symbolic Path Name length", + input: NewSymbolicPathName("Test"), + expected: TLVHeaderLength + 4, + }, + { + name: "Symbolic Path Name with padding", + input: NewSymbolicPathName("ABC"), // 3 bytes + 1 byte padding + expected: TLVHeaderLength + 3 + 1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Len()) + }) + } +} + +func TestIPv4LSPIdentifiers_DecodeFromBytes(t *testing.T) { + tests := []struct { + name string + input []uint8 + expected *IPv4LSPIdentifiers + err bool + }{ + { + name: "Valid IPv4 LSP Identifiers", + input: NewIPv4LSPIdentifiers(netip.MustParseAddr("192.0.2.1"), netip.MustParseAddr("192.0.2.2"), 1, 2, 1234).Serialize(), + expected: NewIPv4LSPIdentifiers(netip.MustParseAddr("192.0.2.1"), netip.MustParseAddr("192.0.2.2"), 1, 2, 1234), + err: false, + }, + { + name: "Invalid IPv4 LSP Identifiers (truncated '192.0.2.1')", + input: []uint8{ + 0x00, 0x12, 0x00, 0x14, // Type (0x12) and Length (0x10) + 0xC0, 0x00, 0x02, // Incomplete address: missing last byte (0x01) + }, + expected: NewIPv4LSPIdentifiers(netip.Addr{}, netip.Addr{}, 0, 0, 0), + err: true, + }, + { + name: "Invalid IPv4 LSP Identifiers (extra bytes after '192.0.2.1')", + input: []uint8{ + 0x00, 0x12, 0x00, 0x14, // Type (0x12) and Length (0x10) + 0xC0, 0x00, 0x02, 0x01, // Valid IPv4 address: 192.0.2.1 + 0xDE, 0xAD, 0xBE, 0xEF, // Extra unexpected bytes + }, + expected: NewIPv4LSPIdentifiers(netip.Addr{}, netip.Addr{}, 0, 0, 0), + err: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tlv IPv4LSPIdentifiers + err := tlv.DecodeFromBytes(tt.input) + if tt.err { + assert.Error(t, err, "expected error for input: %v", tt.input) + } else { + assert.NoError(t, err, "unexpected error for input: %v", tt.input) + assert.Equal(t, tt.expected, &tlv) + } + }) + } +} + +func TestIPv4LSPIdentifiers_Serialize(t *testing.T) { + tests := []struct { + name string + input *IPv4LSPIdentifiers + expected []uint8 + }{ + { + name: "Valid IPv4 LSP Identifiers", + input: NewIPv4LSPIdentifiers(netip.MustParseAddr("192.0.2.1"), netip.MustParseAddr("192.0.2.2"), 1, 2, 1234), + expected: NewIPv4LSPIdentifiers(netip.MustParseAddr("192.0.2.1"), netip.MustParseAddr("192.0.2.2"), 1, 2, 1234).Serialize(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Serialize()) + }) + } +} + +func TestIPv6LSPIdentifiers_DecodeFromBytes(t *testing.T) { + tests := []struct { + name string + input []uint8 + expected *IPv6LSPIdentifiers + err bool + }{ + { + name: "Valid IPv6 LSP Identifiers", + input: NewIPv6LSPIdentifiers(netip.MustParseAddr("2001:db8::1"), netip.MustParseAddr("2001:db8::2"), 1, 2, [16]byte{}).Serialize(), + expected: NewIPv6LSPIdentifiers(netip.MustParseAddr("2001:db8::1"), netip.MustParseAddr("2001:db8::2"), 1, 2, [16]byte{}), + err: false, + }, + { + name: "Invalid IPv6 LSP Identifiers (truncated '2001:db8::1')", + input: []uint8{ + 0x00, 0x13, 0x00, 0x20, // Type IPV6-LSP-IDENTIFIERS (0x13)、Length 32 (0x20) + 0x20, 0x01, 0x0D, 0xB8, // Start of '2001:db8::' + 0x00, 0x00, 0x00, // Incomplete (should be 16 bytes total) + }, + expected: NewIPv6LSPIdentifiers(netip.Addr{}, netip.Addr{}, 0, 0, [16]byte{}), + err: true, + }, + { + name: "Invalid IPv6 LSP Identifiers (extra bytes after '2001:db8::1')", + input: []uint8{ + 0x00, 0x13, 0x00, 0x20, // Type IPV6-LSP-IDENTIFIERS (0x13), Length 32 (0x20) + 0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Valid IPv6: 2001:db8::1 + 0xCA, 0xFE, 0xBA, 0xBE, // Extra unexpected bytes + }, + expected: NewIPv6LSPIdentifiers(netip.Addr{}, netip.Addr{}, 0, 0, [16]byte{}), + err: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tlv IPv6LSPIdentifiers + err := tlv.DecodeFromBytes(tt.input) + if tt.err { + assert.Error(t, err, "expected error for input: %v", tt.input) + } else { + assert.NoError(t, err, "unexpected error for input: %v", tt.input) + assert.Equal(t, tt.expected, &tlv) + } + }) + } +} + +func TestIPv6LSPIdentifiers_Serialize(t *testing.T) { + tests := []struct { + name string + input *IPv6LSPIdentifiers + expected []uint8 + }{ + { + name: "Valid IPv6 LSP Identifiers", + input: NewIPv6LSPIdentifiers(netip.MustParseAddr("2001:db8::1"), netip.MustParseAddr("2001:db8::2"), 1, 2, [16]byte{}), + expected: NewIPv6LSPIdentifiers(netip.MustParseAddr("2001:db8::1"), netip.MustParseAddr("2001:db8::2"), 1, 2, [16]byte{}).Serialize(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Serialize()) + }) + } +} + +func TestLSPDBVersion_DecodeFromBytes(t *testing.T) { + tests := []struct { + name string + input []uint8 + expected *LSPDBVersion + err bool + }{ + { + name: "Valid LSPDB Version", + input: NewLSPDBVersion(12345).Serialize(), + expected: NewLSPDBVersion(12345), + err: false, + }, + { + name: "Invalid input (too short data)", + input: []byte{0x00, 0x17, 0x00, 0x02}, // Type LSP-DB-VERSION (0x17)、Input too short for valid decoding + expected: NewLSPDBVersion(0), + err: true, + }, + { + name: "Invalid input (too long data)", + input: []byte{ + 0x00, 0x17, 0x00, 0x09, // Type LSP-DB-VERSION (0x17)、Length 8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, + 0x00, // Extra bytes after version + }, + expected: NewLSPDBVersion(0), + err: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tlv LSPDBVersion + err := tlv.DecodeFromBytes(tt.input) + if tt.err { + assert.Error(t, err, "expected error for input: %v", tt.input) + } else { + assert.NoError(t, err, "unexpected error for input: %v", tt.input) + assert.Equal(t, tt.expected, &tlv) + } + }) + } +} + +func TestLSPDBVersion_Serialize(t *testing.T) { + tests := []struct { + name string + input *LSPDBVersion + expected []uint8 + }{ + { + name: "Valid LSPDB Version", + input: NewLSPDBVersion(12345), + expected: NewLSPDBVersion(12345).Serialize(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Serialize()) + }) + } +} + +func TestLSPDBVersion_Len(t *testing.T) { + tests := []struct { + name string + input *LSPDBVersion + expected uint16 + }{ + { + name: "LSPDB Version length", + input: NewLSPDBVersion(12345), + expected: TLVHeaderLength + TLVLSPDBVersionValueLength, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Len()) + }) + } +} + +func TestSRPCECapability_DecodeFromBytes(t *testing.T) { + tests := []struct { + name string + input []uint8 + expected *SRPCECapability + err bool + }{ + { + name: "Valid SRPCE Capability", + input: NewSRPCECapability(true, true, 42).Serialize(), // Maximum SID Depth 42 + expected: NewSRPCECapability(true, true, 42), + err: false, + }, + { + name: "Invalid input (too short data)", + input: []uint8{0x00, 0x11, 0x00, 0x02}, // Too short for valid decoding + expected: NewSRPCECapability(false, false, 0), + err: true, + }, + { + name: "Invalid input (too long data)", + input: []uint8{0x00, 0x11, 0x00, 0x02, 0x00, 0x00, 0x03, 0x05, 0x01}, // Too long for valid decoding + expected: NewSRPCECapability(false, false, 0), + err: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tlv SRPCECapability + err := tlv.DecodeFromBytes(tt.input) + if tt.err { + assert.Error(t, err, "expected error for input: %v", tt.input) + } else { + assert.NoError(t, err, "unexpected error for input: %v", tt.input) + assert.Equal(t, tt.expected, &tlv) + } + }) + } +} + +func TestSRPCECapability_Serialize(t *testing.T) { + tests := []struct { + name string + input *SRPCECapability + expected []uint8 + }{ + { + name: "Valid SRPCE Capability", + input: NewSRPCECapability(true, true, 5), + expected: NewSRPCECapability(true, true, 5).Serialize(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Serialize()) + }) + } +} + +func TestSRPCECapability_Len(t *testing.T) { + tests := []struct { + name string + input *SRPCECapability + expected uint16 + }{ + { + name: "SRPCE Capability length", + input: NewSRPCECapability(true, true, 5), + expected: TLVHeaderLength + TLVSRPCECapabilityValueLength, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Len()) + }) + } +} + +func TestPathSetupType_DecodeFromBytes(t *testing.T) { + tests := []struct { + name string + input []uint8 + expected *PathSetupType + err bool + }{ + { + name: "Valid PathSetupType SRv6TE", + input: NewPathSetupType(PathSetupTypeSRv6TE).Serialize(), + expected: NewPathSetupType(PathSetupTypeSRv6TE), + err: false, + }, + { + name: "Invalid input (too short)", + input: []uint8{0x00, 0x15, 0x00, 0x04}, // insufficient data + expected: NewPathSetupType(0), + err: true, + }, + { + name: "Invalid input (too long)", + input: append(NewPathSetupType(PathSetupTypeSRTE).Serialize(), 0x00, 0x00), + expected: NewPathSetupType(0), + err: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var tlv PathSetupType + err := tlv.DecodeFromBytes(tt.input) + if tt.err { + assert.Error(t, err, "expected error for input: %v", tt.input) + } else { + assert.NoError(t, err, "unexpected error for input: %v", tt.input) + assert.Equal(t, tt.expected, &tlv) + } + }) + } +} + +func TestPathSetupType_Serialize(t *testing.T) { + tests := []struct { + name string + input *PathSetupType + expected []uint8 + }{ + { + name: "Serialize PathSetupType SRTE", + input: NewPathSetupType(PathSetupTypeSRTE), + expected: NewPathSetupType(PathSetupTypeSRTE).Serialize(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Serialize()) + }) + } +} + +func TestPathSetupType_Len(t *testing.T) { + tests := []struct { + name string + input *PathSetupType + expected uint16 + }{ + { + name: "Length should be header + value length", + input: NewPathSetupType(PathSetupTypeRSVPTE), + expected: TLVHeaderLength + TLVPathSetupTypeValueLength, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.input.Len()) + }) + } +} diff --git a/pkg/server/error.go b/pkg/server/error.go index b670d724..a25feabc 100644 --- a/pkg/server/error.go +++ b/pkg/server/error.go @@ -5,7 +5,7 @@ package server -type ServerError struct { +type Error struct { Error error Server string } diff --git a/pkg/server/grpc_server.go b/pkg/server/grpc_server.go index 743ee213..c76e8e15 100644 --- a/pkg/server/grpc_server.go +++ b/pkg/server/grpc_server.go @@ -14,8 +14,7 @@ import ( "net/netip" "slices" - "github.com/golang/protobuf/ptypes/empty" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" "github.com/nttcom/pola/internal/pkg/cspf" "github.com/nttcom/pola/internal/pkg/table" "github.com/nttcom/pola/pkg/packet/pcep" @@ -28,7 +27,7 @@ type APIServer struct { grpcServer *grpc.Server usidMode bool logger *zap.Logger - pb.UnimplementedPceServiceServer + pb.UnimplementedPCEServiceServer } func NewAPIServer(pce *Server, grpcServer *grpc.Server, usidMode bool, logger *zap.Logger) *APIServer { @@ -38,7 +37,7 @@ func NewAPIServer(pce *Server, grpcServer *grpc.Server, usidMode bool, logger *z usidMode: usidMode, logger: logger.With(zap.String("server", "grpc")), } - pb.RegisterPceServiceServer(grpcServer, s) + pb.RegisterPCEServiceServer(grpcServer, s) return s } @@ -52,39 +51,31 @@ func (s *APIServer) Serve(address string, port string) error { return s.grpcServer.Serve(grpcListener) } -func (s *APIServer) CreateSRPolicy(ctx context.Context, input *pb.CreateSRPolicyInput) (*pb.RequestStatus, error) { - return s.createSRPolicy(ctx, input, true) -} - -func (s *APIServer) CreateSRPolicyWithoutLinkState(ctx context.Context, input *pb.CreateSRPolicyInput) (*pb.RequestStatus, error) { - return s.createSRPolicy(ctx, input, false) -} - -func validateCreateSRPolicy(input *pb.CreateSRPolicyInput, withLinkState bool) error { - if withLinkState { - return validate(input.GetSRPolicy(), input.GetAsn(), ValidationAdd) +func validateCreateSRPolicy(req *pb.CreateSRPolicyRequest, disablePathCompute bool) error { + if disablePathCompute { + return validate(req.GetSrPolicy(), req.GetAsn(), ValidationAddDisablePathCompute) } - return validate(input.GetSRPolicy(), input.GetAsn(), ValidationAddWithoutLinkState) + return validate(req.GetSrPolicy(), req.GetAsn(), ValidationAdd) } -func buildSegmentList(s *APIServer, input *pb.CreateSRPolicyInput, withLinkState bool) ([]table.Segment, netip.Addr, netip.Addr, error) { +func buildSegmentList(s *APIServer, input *pb.CreateSRPolicyRequest, disablePathCompute bool) ([]table.Segment, netip.Addr, netip.Addr, error) { var srcAddr, dstAddr netip.Addr var segmentList []table.Segment var err error - inputSRPolicy := input.GetSRPolicy() + inputSRPolicy := input.GetSrPolicy() - if withLinkState { + if !disablePathCompute { if s.pce.ted == nil { return nil, netip.Addr{}, netip.Addr{}, errors.New("ted is disabled") } - srcAddr, err = getLoopbackAddr(s.pce, input.GetAsn(), inputSRPolicy.GetSrcRouterID()) + srcAddr, err = getLoopbackAddr(s.pce, input.GetAsn(), inputSRPolicy.GetSrcRouterId()) if err != nil { return nil, netip.Addr{}, netip.Addr{}, err } - dstAddr, err = getLoopbackAddr(s.pce, input.GetAsn(), inputSRPolicy.GetDstRouterID()) + dstAddr, err = getLoopbackAddr(s.pce, input.GetAsn(), inputSRPolicy.GetDstRouterId()) if err != nil { return nil, netip.Addr{}, netip.Addr{}, err } @@ -109,12 +100,12 @@ func buildSegmentList(s *APIServer, input *pb.CreateSRPolicyInput, withLinkState return segmentList, srcAddr, dstAddr, nil } -func sendSRPolicyRequest(s *APIServer, input *pb.CreateSRPolicyInput, segmentList []table.Segment, srcAddr, dstAddr netip.Addr) (*pb.RequestStatus, error) { - inputSRPolicy := input.GetSRPolicy() +func sendSRPolicyRequest(s *APIServer, input *pb.CreateSRPolicyRequest, segmentList []table.Segment, srcAddr, dstAddr netip.Addr) error { + inputSRPolicy := input.GetSrPolicy() - pcepSession, err := getSyncedPcepSession(s.pce, inputSRPolicy.GetPcepSessionAddr()) + pcepSession, err := getSyncedPCEPSession(s.pce, inputSRPolicy.GetPcepSessionAddr()) if err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + return fmt.Errorf("failed to get synchronized PCEP session: %w", err) } srPolicy := table.SRPolicy{ @@ -131,38 +122,43 @@ func sendSRPolicyRequest(s *APIServer, input *pb.CreateSRPolicyInput, segmentLis srPolicy.PlspID = id if err := pcepSession.SendPCUpdate(srPolicy); err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + return fmt.Errorf("failed to send PC update: %w", err) } } else { s.logger.Debug("Request to create SR Policy") if err := pcepSession.RequestSRPolicyCreated(srPolicy); err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + return fmt.Errorf("failed to request SR policy creation: %w", err) } } - return &pb.RequestStatus{IsSuccess: true}, nil + return nil } -func (s *APIServer) createSRPolicy(_ context.Context, input *pb.CreateSRPolicyInput, withLinkState bool) (*pb.RequestStatus, error) { - if err := validateCreateSRPolicy(input, withLinkState); err != nil { - return &pb.RequestStatus{IsSuccess: false}, err +func (s *APIServer) CreateSRPolicy(ctx context.Context, req *pb.CreateSRPolicyRequest) (*pb.CreateSRPolicyResponse, error) { + sidvalidate := req.GetSidValidate() + if err := validateCreateSRPolicy(req, sidvalidate); err != nil { + return nil, fmt.Errorf("failed to validate SR policy creation: %w", err) } - segmentList, srcAddr, dstAddr, err := buildSegmentList(s, input, withLinkState) + segmentList, srcAddr, dstAddr, err := buildSegmentList(s, req, sidvalidate) if err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + return nil, fmt.Errorf("failed to build segment list: %w", err) } - return sendSRPolicyRequest(s, input, segmentList, srcAddr, dstAddr) + if err := sendSRPolicyRequest(s, req, segmentList, srcAddr, dstAddr); err != nil { + return nil, fmt.Errorf("failed to send SR policy request: %w", err) + } + + return &pb.CreateSRPolicyResponse{IsSuccess: true}, nil } -func (s *APIServer) DeleteSRPolicy(ctx context.Context, input *pb.DeleteSRPolicyInput) (*pb.RequestStatus, error) { - err := validate(input.GetSRPolicy(), input.GetAsn(), ValidationDelete) +func (s *APIServer) DeleteSRPolicy(ctx context.Context, input *pb.DeleteSRPolicyRequest) (*pb.DeleteSRPolicyResponse, error) { + err := validate(input.GetSrPolicy(), input.GetAsn(), ValidationDelete) if err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + return &pb.DeleteSRPolicyResponse{IsSuccess: false}, err } - inputSRPolicy := input.GetSRPolicy() + inputSRPolicy := input.GetSrPolicy() var srcAddr, dstAddr netip.Addr var segmentList []table.Segment @@ -171,21 +167,21 @@ func (s *APIServer) DeleteSRPolicy(ctx context.Context, input *pb.DeleteSRPolicy for _, segment := range inputSRPolicy.GetSegmentList() { seg, err := table.NewSegment(segment.GetSid()) if err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + return &pb.DeleteSRPolicyResponse{IsSuccess: false}, err } segmentList = append(segmentList, seg) } - inputJson, err := json.Marshal(input) + inputJSON, err := json.Marshal(input) if err != nil { return nil, err } s.logger.Info("Received DeleteSRPolicy API request") - s.logger.Debug("Received paramater", zap.String("input", string(inputJson))) + s.logger.Debug("Received parameter", zap.String("input", string(inputJSON))) - pcepSession, err := getSyncedPcepSession(s.pce, inputSRPolicy.GetPcepSessionAddr()) + pcepSession, err := getSyncedPCEPSession(s.pce, inputSRPolicy.GetPcepSessionAddr()) if err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + return &pb.DeleteSRPolicyResponse{IsSuccess: false}, err } srPolicy := table.SRPolicy{ @@ -198,24 +194,33 @@ func (s *APIServer) DeleteSRPolicy(ctx context.Context, input *pb.DeleteSRPolicy } if id, exists := pcepSession.SearchPlspID(inputSRPolicy.GetColor(), dstAddr); exists { - // Delete SR Policy s.logger.Debug("Request to delete SR Policy", zap.Uint32("plspID", id)) srPolicy.PlspID = id if err := pcepSession.RequestSRPolicyDeleted(srPolicy); err != nil { - return &pb.RequestStatus{IsSuccess: false}, nil + return &pb.DeleteSRPolicyResponse{IsSuccess: false}, err } } else { // Invalid SR Policy - return &pb.RequestStatus{IsSuccess: false}, fmt.Errorf("requested SR Policy not found") + return &pb.DeleteSRPolicyResponse{IsSuccess: false}, fmt.Errorf("requested SR Policy not found") } - return &pb.RequestStatus{IsSuccess: true}, nil + return &pb.DeleteSRPolicyResponse{IsSuccess: true}, nil } func validate(inputSRPolicy *pb.SRPolicy, asn uint32, validationKind ValidationKind) error { - if !validator[validationKind](inputSRPolicy, asn) { - return errors.New("validate error, invalid input") + if inputSRPolicy == nil { + return errors.New("validate error, input is nil") + } + if asn == 0 { + return errors.New("validate error, ASN must not be zero") + } + if validateFunc, ok := validator[validationKind]; ok { + if err := validateFunc(inputSRPolicy, asn); err != nil { + return fmt.Errorf("validate error: %w", err) + } + } else { + return fmt.Errorf("validate error: unknown validation kind %q", validationKind) } return nil @@ -224,34 +229,65 @@ func validate(inputSRPolicy *pb.SRPolicy, asn uint32, validationKind ValidationK type ValidationKind string const ( - ValidationAdd ValidationKind = "Add" - ValidationAddWithoutLinkState ValidationKind = "AddWithoutLinkState" - ValidationDelete ValidationKind = "Delete" + ValidationAdd ValidationKind = "Add" + ValidationAddDisablePathCompute ValidationKind = "AddDisablePathCompute" + ValidationDelete ValidationKind = "Delete" ) -var validator = map[ValidationKind]func(policy *pb.SRPolicy, asn uint32) bool{ - ValidationKind("Add"): func(policy *pb.SRPolicy, asn uint32) bool { - return asn != 0 && - policy.PcepSessionAddr != nil && - policy.Color != 0 && - policy.SrcRouterID != "" && - policy.DstRouterID != "" +var validator = map[ValidationKind]func(policy *pb.SRPolicy, asn uint32) error{ + ValidationAdd: func(policy *pb.SRPolicy, asn uint32) error { + if asn == 0 { + return errors.New("policy.ASN must not be zero") + } + if policy.PcepSessionAddr == nil { + return errors.New("policy.PCEP session address must not be nil") + } + if policy.Color == 0 { + return errors.New("policy.Color must not be zero") + } + if policy.SrcRouterId == "" { + return errors.New("policy.SrcRouterId must not be empty") + } + if policy.DstRouterId == "" { + return errors.New("policy.DstRouterId must not be empty") + } + return nil }, - ValidationKind("AddWithoutLinkState"): func(policy *pb.SRPolicy, asn uint32) bool { - return policy.PcepSessionAddr != nil && - len(policy.SrcAddr) > 0 && - len(policy.DstAddr) > 0 && - len(policy.SegmentList) > 0 + + ValidationAddDisablePathCompute: func(policy *pb.SRPolicy, asn uint32) error { + if policy.PcepSessionAddr == nil { + return errors.New("policy.PCEP session address must not be nil") + } + if len(policy.SrcAddr) == 0 { + return errors.New("policy.SrcAddr must not be empty") + } + if len(policy.DstAddr) == 0 { + return errors.New("policy.DstAddr must not be empty") + } + if len(policy.SegmentList) == 0 { + return errors.New("policy.SegmentList must not be empty") + } + return nil }, - ValidationKind("Delete"): func(policy *pb.SRPolicy, asn uint32) bool { - return policy.PcepSessionAddr != nil && - policy.Color != 0 && - len(policy.DstAddr) > 0 && - policy.PolicyName != "" + + ValidationDelete: func(policy *pb.SRPolicy, asn uint32) error { + if policy.PcepSessionAddr == nil { + return errors.New("policy.PCEP session address must not be nil") + } + if policy.Color == 0 { + return errors.New("policy.Color must not be zero") + } + if len(policy.DstAddr) == 0 { + return errors.New("policy.DstAddr must not be empty") + } + if policy.PolicyName == "" { + return errors.New("policy.PolicyName must not be empty") + } + return nil }, } -func getSyncedPcepSession(pce *Server, addr []byte) (*Session, error) { +func getSyncedPCEPSession(pce *Server, addr []byte) (*Session, error) { pcepSessionAddr, _ := netip.AddrFromSlice(addr) pcepSession := pce.SearchSession(pcepSessionAddr, true) if pcepSession == nil { @@ -268,11 +304,11 @@ func getLoopbackAddr(pce *Server, asn uint32, routerID string) (netip.Addr, erro return node.LoopbackAddr() } -func getSegmentList(inputSRPolicy *pb.SRPolicy, asn uint32, ted *table.LsTed) ([]table.Segment, error) { +func getSegmentList(inputSRPolicy *pb.SRPolicy, asn uint32, ted *table.LsTED) ([]table.Segment, error) { var segmentList []table.Segment switch inputSRPolicy.GetType() { - case pb.SRPolicyType_EXPLICIT: + case pb.SRPolicyType_SR_POLICY_TYPE_EXPLICIT: if len(inputSRPolicy.GetSegmentList()) == 0 { return nil, errors.New("no segments in SRPolicy input") } @@ -283,12 +319,12 @@ func getSegmentList(inputSRPolicy *pb.SRPolicy, asn uint32, ted *table.LsTed) ([ } segmentList = append(segmentList, sid) } - case pb.SRPolicyType_DYNAMIC: + case pb.SRPolicyType_SR_POLICY_TYPE_DYNAMIC: metricType, err := getMetricType(inputSRPolicy.GetMetric()) if err != nil { return nil, err } - segmentList, err = cspf.Cspf(inputSRPolicy.GetSrcRouterID(), inputSRPolicy.GetDstRouterID(), asn, metricType, ted) + segmentList, err = cspf.Cspf(inputSRPolicy.GetSrcRouterId(), inputSRPolicy.GetDstRouterId(), asn, metricType, ted) if err != nil { return nil, err } @@ -301,27 +337,27 @@ func getSegmentList(inputSRPolicy *pb.SRPolicy, asn uint32, ted *table.LsTed) ([ func getMetricType(metricType pb.MetricType) (table.MetricType, error) { switch metricType { - case pb.MetricType_IGP: - return table.IGP_METRIC, nil - case pb.MetricType_TE: - return table.TE_METRIC, nil - case pb.MetricType_DELAY: - return table.DELAY_METRIC, nil - case pb.MetricType_HOPCOUNT: - return table.HOPCOUNT_METRIC, nil + case pb.MetricType_METRIC_TYPE_IGP: + return table.IGPMetric, nil + case pb.MetricType_METRIC_TYPE_TE: + return table.TEMetric, nil + case pb.MetricType_METRIC_TYPE_DELAY: + return table.DelayMetric, nil + case pb.MetricType_METRIC_TYPE_HOPCOUNT: + return table.HopcountMetric, nil default: return 0, fmt.Errorf("unknown metric type: %v", metricType) } } -func (s *APIServer) GetSessionList(context.Context, *empty.Empty) (*pb.SessionList, error) { +func (s *APIServer) GetSessionList(ctx context.Context, _ *pb.GetSessionListRequest) (*pb.GetSessionListResponse, error) { s.logger.Info("Received GetSessionList API request") - var ret pb.SessionList + var sessions []*pb.Session for _, pcepSession := range s.pce.sessionList { ss := &pb.Session{ Addr: pcepSession.peerAddr.AsSlice(), - State: pb.SessionState_UP, // Only the UP state in the current specification + State: pb.SessionState_SESSION_STATE_UP, // Only the UP state in the current specification Caps: []string{}, IsSynced: pcepSession.isSynced, } @@ -329,20 +365,22 @@ func (s *APIServer) GetSessionList(context.Context, *empty.Empty) (*pb.SessionLi ss.Caps = append(ss.Caps, cap.CapStrings()...) } ss.Caps = slices.Compact(ss.Caps) - ret.Sessions = append(ret.Sessions, ss) + sessions = append(sessions, ss) } - s.logger.Debug("Send GetPeerAddrList API reply") - return &ret, nil + s.logger.Debug("Send GetSessionList API reply") + return &pb.GetSessionListResponse{ + Sessions: sessions, + }, nil } -func (s *APIServer) GetSRPolicyList(context.Context, *empty.Empty) (*pb.SRPolicyList, error) { +func (s *APIServer) GetSRPolicyList(ctx context.Context, _ *pb.GetSRPolicyListRequest) (*pb.GetSRPolicyListResponse, error) { s.logger.Info("Received GetSRPolicyList API request") - var ret pb.SRPolicyList + var srPolicies []*pb.SRPolicy for ssAddr, policies := range s.pce.SRPolicies() { for _, policy := range policies { - srPolicyData := &pb.SRPolicy{ + srPolicy := &pb.SRPolicy{ PcepSessionAddr: ssAddr.AsSlice(), SegmentList: make([]*pb.Segment, 0), Color: policy.Color, @@ -353,106 +391,218 @@ func (s *APIServer) GetSRPolicyList(context.Context, *empty.Empty) (*pb.SRPolicy } for _, segment := range policy.SegmentList { - srPolicyData.SegmentList = append(srPolicyData.SegmentList, &pb.Segment{ + srPolicy.SegmentList = append(srPolicy.SegmentList, &pb.Segment{ Sid: segment.SidString(), }) } - ret.SRPolicies = append(ret.SRPolicies, srPolicyData) + srPolicies = append(srPolicies, srPolicy) } } s.logger.Debug("Send SRPolicyList API reply") - return &ret, nil + return &pb.GetSRPolicyListResponse{ + SrPolicies: srPolicies, + }, nil } -func (s *APIServer) GetTed(context.Context, *empty.Empty) (*pb.Ted, error) { - s.logger.Info("Received GetTed API request") +// GetTED returns the TED information in a structured way. +func (s *APIServer) GetTED(ctx context.Context, req *pb.GetTEDRequest) (*pb.GetTEDResponse, error) { + s.logger.Info("Received GetTED API request") - ret := &pb.Ted{ - Enable: true, - } - - if s.pce.ted == nil { + ret := &pb.GetTEDResponse{Enable: true} + if s.pce == nil || s.pce.ted == nil { ret.Enable = false return ret, nil } - ret.LsNodes = make([]*pb.LsNode, 0, len(s.pce.ted.Nodes)) - - for _, lsNodes := range s.pce.ted.Nodes { - for _, lsNode := range lsNodes { - node := &pb.LsNode{ - Asn: lsNode.Asn, - RouterID: lsNode.RouterID, - IsisAreaID: lsNode.IsisAreaID, - Hostname: lsNode.Hostname, - SrgbBegin: lsNode.SrgbBegin, - SrgbEnd: lsNode.SrgbEnd, - LsLinks: make([]*pb.LsLink, 0, len(lsNode.Links)), - LsPrefixes: make([]*pb.LsPrefix, 0, len(lsNode.Prefixes)), + for _, nodes := range s.pce.ted.Nodes { + for _, node := range nodes { + if n := convertLsNode(node, s.logger); n != nil { + ret.LsNodes = append(ret.LsNodes, n) } + } + } - for _, lsLink := range lsNode.Links { - link := &pb.LsLink{ - LocalRouterID: lsLink.LocalNode.RouterID, - LocalAsn: lsLink.LocalNode.Asn, - LocalIP: lsLink.LocalIP.String(), - RemoteRouterID: lsLink.RemoteNode.RouterID, - RemoteAsn: lsLink.RemoteNode.Asn, - RemoteIP: lsLink.RemoteIP.String(), - Metrics: make([]*pb.Metric, 0, len(lsLink.Metrics)), - AdjSid: lsLink.AdjSid, - } - - for _, lsMetric := range lsLink.Metrics { - metricType, ok := pb.MetricType_value[lsMetric.Type.String()] - - if !ok { - return nil, fmt.Errorf("invalid metric type: %s", lsMetric.Type.String()) - } - - metric := &pb.Metric{ - Type: pb.MetricType(metricType), - Value: lsMetric.Value, - } - - link.Metrics = append(link.Metrics, metric) - } - - node.LsLinks = append(node.LsLinks, link) - } + s.logger.Debug("Send GetTED API reply") + return ret, nil +} + +// convertLsNode converts a table.LsNode to a protobuf LsNode. +func convertLsNode(lsNode *table.LsNode, logger *zap.Logger) *pb.LsNode { + if lsNode == nil { + return nil + } - for _, lsPrefix := range lsNode.Prefixes { - prefix := &pb.LsPrefix{ - Prefix: lsPrefix.Prefix.String(), - SidIndex: lsPrefix.SidIndex, - } + return &pb.LsNode{ + Asn: lsNode.ASN, + RouterId: lsNode.RouterID, + IsisAreaId: lsNode.IsisAreaID, + Hostname: lsNode.Hostname, + SrgbBegin: lsNode.SrgbBegin, + SrgbEnd: lsNode.SrgbEnd, + LsLinks: convertLsLinks(lsNode.Links, logger), + LsPrefixes: convertLsPrefixes(lsNode.Prefixes), + LsSrv6Sids: convertLsSrv6SIDs(lsNode.SRv6SIDs), + } +} - node.LsPrefixes = append(node.LsPrefixes, prefix) +// convertLsLinks converts a slice of table.LsLink to protobuf LsLink. +func convertLsLinks(links []*table.LsLink, logger *zap.Logger) []*pb.LsLink { + if links == nil { + return nil + } + result := make([]*pb.LsLink, 0, len(links)) + for _, link := range links { + if link == nil || link.LocalNode == nil || link.RemoteNode == nil { + logger.Debug("skip link with nil node", zap.Any("link", link)) + continue + } + result = append(result, buildLsLink(link)) + } + return result +} + +// buildLsLink converts a single table.LsLink to protobuf LsLink. +func buildLsLink(link *table.LsLink) *pb.LsLink { + localIP, _ := link.LocalIP.MarshalText() + remoteIP, _ := link.RemoteIP.MarshalText() + + pbLink := &pb.LsLink{ + LocalRouterId: link.LocalNode.RouterID, + LocalAsn: link.LocalNode.ASN, + LocalIp: string(localIP), + RemoteRouterId: link.RemoteNode.RouterID, + RemoteAsn: link.RemoteNode.ASN, + RemoteIp: string(remoteIP), + Metrics: convertMetrics(link.Metrics), + AdjSid: link.AdjSid, + } + + if link.Srv6EndXSID != nil { + pbLink.Srv6EndXSid = convertSrv6EndXSID(link.Srv6EndXSID) + } + return pbLink +} + +// convertMetrics converts a slice of table.Metric to protobuf Metric. +func convertMetrics(metrics []*table.Metric) []*pb.Metric { + if metrics == nil { + return nil + } + result := make([]*pb.Metric, 0, len(metrics)) + for _, m := range metrics { + if m != nil { + if mt, ok := pb.MetricType_value[m.Type.String()]; ok { + result = append(result, &pb.Metric{Type: pb.MetricType(mt), Value: m.Value}) } + } + } + return result +} - ret.LsNodes = append(ret.LsNodes, node) +// convertLsPrefixes converts a slice of table.LsPrefix to protobuf LsPrefix. +func convertLsPrefixes(prefixes []*table.LsPrefix) []*pb.LsPrefix { + if prefixes == nil { + return nil + } + result := make([]*pb.LsPrefix, 0, len(prefixes)) + for _, p := range prefixes { + if p != nil { + result = append(result, &pb.LsPrefix{Prefix: p.Prefix.String(), SidIndex: p.SidIndex}) } } + return result +} - s.logger.Debug("Send GetTed API reply") - return ret, nil +// convertLsSrv6SIDs converts a slice of table.LsSrv6SID to protobuf LsSrv6SID. +func convertLsSrv6SIDs(sids []*table.LsSrv6SID) []*pb.LsSrv6SID { + if sids == nil { + return nil + } + result := make([]*pb.LsSrv6SID, 0, len(sids)) + for _, s := range sids { + if s != nil { + result = append(result, buildLsSrv6SID(s)) + } + } + return result +} + +// buildLsSrv6SID converts a single table.LsSrv6SID to protobuf LsSrv6SID. +func buildLsSrv6SID(s *table.LsSrv6SID) *pb.LsSrv6SID { + pbSID := &pb.LsSrv6SID{ + Sids: make([]*pb.SID, 0, len(s.Sids)), + MultiTopoIds: make([]*pb.MultiTopoID, 0, len(s.MultiTopoIDs)), + SidStructure: &pb.SidStructure{ + LocalBlock: uint32(s.SIDStructure.LocalBlock), + LocalNode: uint32(s.SIDStructure.LocalNode), + LocalFunc: uint32(s.SIDStructure.LocalFunc), + LocalArg: uint32(s.SIDStructure.LocalArg), + }, + } + + for _, sid := range s.Sids { + if sid != "" { + pbSID.Sids = append(pbSID.Sids, &pb.SID{Sid: sid}) + } + } + + for _, topoID := range s.MultiTopoIDs { + pbSID.MultiTopoIds = append(pbSID.MultiTopoIds, &pb.MultiTopoID{MultiTopoId: topoID}) + } + + if s.EndpointBehavior != (table.EndpointBehavior{}) { + pbSID.EndpointBehavior = &pb.EndpointBehavior{ + Behavior: uint32(s.EndpointBehavior.Behavior), + Flags: uint32(s.EndpointBehavior.Flags), + Algorithm: uint32(s.EndpointBehavior.Algorithm), + } + } + + return pbSID +} + +// convertSrv6EndXSID converts table.Srv6EndXSID to protobuf Srv6EndXSID. +func convertSrv6EndXSID(sid *table.Srv6EndXSID) *pb.Srv6EndXSID { + pbSID := &pb.Srv6EndXSID{ + EndpointBehavior: uint32(sid.EndpointBehavior), + Sids: make([]*pb.SID, 0, len(sid.Sids)), + SidStructure: &pb.SidStructure{ + LocalBlock: uint32(sid.Srv6SIDStructure.LocalBlock), + LocalNode: uint32(sid.Srv6SIDStructure.LocalNode), + LocalFunc: uint32(sid.Srv6SIDStructure.LocalFunc), + LocalArg: uint32(sid.Srv6SIDStructure.LocalArg), + }, + } + + for _, s := range sid.Sids { + if s != "" { + pbSID.Sids = append(pbSID.Sids, &pb.SID{Sid: s}) + } + } + + return pbSID } -func (c *APIServer) DeleteSession(ctx context.Context, input *pb.Session) (*pb.RequestStatus, error) { - ssAddr, _ := netip.AddrFromSlice(input.GetAddr()) +func (s *APIServer) DeleteSession(ctx context.Context, req *pb.DeleteSessionRequest) (*pb.DeleteSessionResponse, error) { + ssAddr, ok := netip.AddrFromSlice(req.GetAddr()) + if !ok { + return nil, fmt.Errorf("invalid address: %v", req.GetAddr()) + } - s := c.pce - var ss *Session - if ss = s.SearchSession(ssAddr, false); ss == nil { - return nil, fmt.Errorf("no session with %s", ssAddr) + pce := s.pce + ss := pce.SearchSession(ssAddr, false) + if ss == nil { + return nil, fmt.Errorf("no session with address %s found", ssAddr) } - if err := ss.SendClose(pcep.R_NO_EXPLANATION_PROVIDED); err != nil { - return &pb.RequestStatus{IsSuccess: false}, err + + if err := ss.SendClose(pcep.CloseReasonNoExplanationProvided); err != nil { + return &pb.DeleteSessionResponse{IsSuccess: false}, fmt.Errorf("failed to send close message: %v", err) } + // Remove session info from PCE server - s.closeSession(ss) + pce.closeSession(ss) - return &pb.RequestStatus{IsSuccess: true}, nil + return &pb.DeleteSessionResponse{IsSuccess: true}, nil } diff --git a/pkg/server/server.go b/pkg/server/server.go index d08dc5f0..4d803fe9 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -21,23 +21,23 @@ import ( type Server struct { sessionList []*Session - ted *table.LsTed + ted *table.LsTED logger *zap.Logger } -type PceOptions struct { - PcepAddr string - PcepPort string - GrpcAddr string - GrpcPort string - TedEnable bool +type PCEOptions struct { + PCEPAddr string + PCEPPort string + GRPCAddr string + GRPCPort string + TEDEnable bool USidMode bool } -func NewPce(o *PceOptions, logger *zap.Logger, tedElemsChan chan []table.TedElem) ServerError { +func NewPCE(o *PCEOptions, logger *zap.Logger, tedElemsChan chan []table.TEDElem) Error { s := &Server{logger: logger} - if o.TedEnable { - s.ted = &table.LsTed{ + if o.TEDEnable { + s.ted = &table.LsTED{ ID: 1, Nodes: map[uint32]map[string]*table.LsNode{}, } @@ -46,7 +46,7 @@ func NewPce(o *PceOptions, logger *zap.Logger, tedElemsChan chan []table.TedElem go func() { for { tedElems := <-tedElemsChan - ted := &table.LsTed{ + ted := &table.LsTED{ ID: s.ted.ID, Nodes: map[uint32]map[string]*table.LsNode{}, } @@ -57,10 +57,10 @@ func NewPce(o *PceOptions, logger *zap.Logger, tedElemsChan chan []table.TedElem }() } - errChan := make(chan ServerError) + errChan := make(chan Error) go func() { - if err := s.Serve(o.PcepAddr, o.PcepPort, o.USidMode); err != nil { - errChan <- ServerError{ + if err := s.Serve(o.PCEPAddr, o.PCEPPort, o.USidMode); err != nil { + errChan <- Error{ Server: "pcep", Error: err, } @@ -70,8 +70,8 @@ func NewPce(o *PceOptions, logger *zap.Logger, tedElemsChan chan []table.TedElem go func() { grpcServer := grpc.NewServer() apiServer := NewAPIServer(s, grpcServer, o.USidMode, logger) - if err := apiServer.Serve(o.GrpcAddr, o.GrpcPort); err != nil { - errChan <- ServerError{ + if err := apiServer.Serve(o.GRPCAddr, o.GRPCPort); err != nil { + errChan <- Error{ Server: "grpc", Error: err, } @@ -118,7 +118,7 @@ func (s *Server) Serve(address string, port string, usidMode bool) error { if err != nil { return fmt.Errorf("failed to parse remote address %s: %w", tcpConn.RemoteAddr().String(), err) } - ss := NewSession(sessionID, peerAddrPort.Addr(), tcpConn, s.logger) + ss := NewSession(sessionID, peerAddrPort.Addr(), tcpConn, s.logger, s.ted) ss.logger.Info("start PCEP session") s.sessionList = append(s.sessionList, ss) diff --git a/pkg/server/session.go b/pkg/server/session.go index 1026a348..7c4ef510 100644 --- a/pkg/server/session.go +++ b/pkg/server/session.go @@ -6,11 +6,13 @@ package server import ( + "errors" "fmt" "net" "net/netip" "time" + "github.com/nttcom/pola/internal/pkg/cspf" "github.com/nttcom/pola/internal/pkg/table" "github.com/nttcom/pola/pkg/packet/pcep" @@ -28,17 +30,19 @@ type Session struct { keepAlive uint8 pccType pcep.PccType pccCapabilities []pcep.CapabilityInterface + ted *table.LsTED } -func NewSession(sessionID uint8, peerAddr netip.Addr, tcpConn *net.TCPConn, logger *zap.Logger) *Session { +func NewSession(sessionID uint8, peerAddr netip.Addr, tcpConn *net.TCPConn, logger *zap.Logger, ted *table.LsTED) *Session { return &Session{ sessionID: sessionID, isSynced: false, srpIDHead: uint32(1), logger: logger.With(zap.String("server", "pcep"), zap.String("session", peerAddr.String())), - pccType: pcep.RFC_COMPLIANT, + pccType: pcep.RFCCompliant, peerAddr: peerAddr, tcpConn: tcpConn, + ted: ted, } } @@ -60,7 +64,7 @@ func (ss *Session) Established() { // Receive PCEP messages in a separate goroutine go func() { - if err := ss.ReceivePcepMessage(); err != nil { + if err := ss.ReceivePCEPMessage(); err != nil { ss.logger.Debug("ERROR! Receive PCEP Message", zap.Error(err)) } done <- struct{}{} @@ -82,7 +86,7 @@ func (ss *Session) Established() { } } -func (ss *Session) sendPcepMessage(message pcep.Message) error { +func (ss *Session) sendPCEPMessage(message pcep.Message) error { byteMessage, err := message.Serialize() if err != nil { return err @@ -102,7 +106,7 @@ func (ss *Session) Open() error { } func (ss *Session) parseOpenMessage() (*pcep.OpenMessage, error) { - byteOpenHeader := make([]uint8, pcep.COMMON_HEADER_LENGTH) + byteOpenHeader := make([]uint8, pcep.CommonHeaderLength) if _, err := ss.tcpConn.Read(byteOpenHeader); err != nil { return nil, err } @@ -115,11 +119,11 @@ func (ss *Session) parseOpenMessage() (*pcep.OpenMessage, error) { if openHeader.Version != 1 { return nil, fmt.Errorf("PCEP version mismatch (receive version: %d)", openHeader.Version) } - if openHeader.MessageType != pcep.MT_OPEN { - return nil, fmt.Errorf("this peer has not been opened (messageType: %d)", openHeader.MessageType) + if openHeader.MessageType != pcep.MessageTypeOpen { + return nil, fmt.Errorf("this peer has not been opened (messageType: %s)", openHeader.MessageType.String()) } - byteOpenObject := make([]uint8, openHeader.MessageLength-pcep.COMMON_HEADER_LENGTH) + byteOpenObject := make([]uint8, openHeader.MessageLength-pcep.CommonHeaderLength) if _, err := ss.tcpConn.Read(byteOpenObject); err != nil { return nil, err } @@ -156,10 +160,10 @@ func (ss *Session) SendKeepalive() error { return err } ss.logger.Debug("Send Keepalive Message") - return ss.sendPcepMessage(keepaliveMessage) + return ss.sendPCEPMessage(keepaliveMessage) } -func (ss *Session) SendClose(reason uint8) error { +func (ss *Session) SendClose(reason pcep.CloseReason) error { closeMessage, err := pcep.NewCloseMessage(reason) if err != nil { return err @@ -167,7 +171,7 @@ func (ss *Session) SendClose(reason uint8) error { byteCloseMessage := closeMessage.Serialize() ss.logger.Debug("Send Close Message", - zap.Uint8("reason", closeMessage.CloseObject.Reason), + zap.Uint8("reason", uint8(closeMessage.CloseObject.Reason)), zap.String("detail", "See https://www.iana.org/assignments/pcep/pcep.xhtml#close-object-reason-field")) if _, err := ss.tcpConn.Write(byteCloseMessage); err != nil { return err @@ -175,7 +179,7 @@ func (ss *Session) SendClose(reason uint8) error { return nil } -func (ss *Session) ReceivePcepMessage() error { +func (ss *Session) ReceivePCEPMessage() error { for { commonHeader, err := ss.readCommonHeader() if err != nil { @@ -185,15 +189,15 @@ func (ss *Session) ReceivePcepMessage() error { time.Sleep(10 * time.Millisecond) switch commonHeader.MessageType { - case pcep.MT_KEEPALIVE: + case pcep.MessageTypeKeepalive: ss.logger.Debug("Received Keepalive") - case pcep.MT_REPORT: + case pcep.MessageTypeReport: err = ss.handlePCRpt(commonHeader.MessageLength) if err != nil { return err } - case pcep.MT_ERROR: - bytePCErrMessageBody := make([]uint8, commonHeader.MessageLength-pcep.COMMON_HEADER_LENGTH) + case pcep.MessageTypeError: + bytePCErrMessageBody := make([]uint8, commonHeader.MessageLength-pcep.CommonHeaderLength) if _, err := ss.tcpConn.Read(bytePCErrMessageBody); err != nil { return err } @@ -203,11 +207,11 @@ func (ss *Session) ReceivePcepMessage() error { } ss.logger.Debug("Received PCErr", - zap.Uint8("error-Type", pcerrMessage.PcepErrorObject.ErrorType), - zap.Uint8("error-value", pcerrMessage.PcepErrorObject.ErrorValue), + zap.Uint8("error-Type", pcerrMessage.PCEPErrorObject.ErrorType), + zap.Uint8("error-value", pcerrMessage.PCEPErrorObject.ErrorValue), zap.String("detail", "See https://www.iana.org/assignments/pcep/pcep.xhtml#pcep-error-object")) - case pcep.MT_CLOSE: - byteCloseMessageBody := make([]uint8, commonHeader.MessageLength-pcep.COMMON_HEADER_LENGTH) + case pcep.MessageTypeClose: + byteCloseMessageBody := make([]uint8, commonHeader.MessageLength-pcep.CommonHeaderLength) if _, err := ss.tcpConn.Read(byteCloseMessageBody); err != nil { return err } @@ -216,19 +220,19 @@ func (ss *Session) ReceivePcepMessage() error { return err } ss.logger.Debug("Received Close", - zap.Uint8("reason", closeMessage.CloseObject.Reason), + zap.String("reason", closeMessage.CloseObject.Reason.String()), zap.String("detail", "See https://www.iana.org/assignments/pcep/pcep.xhtml#close-object-reason-field")) // Close session if get Close Message return nil default: ss.logger.Debug("Received unsupported MessageType", - zap.Uint8("MessageType", commonHeader.MessageType)) + zap.String("MessageType", commonHeader.MessageType.String())) } } } func (ss *Session) readCommonHeader() (*pcep.CommonHeader, error) { - commonHeaderBytes := make([]uint8, pcep.COMMON_HEADER_LENGTH) + commonHeaderBytes := make([]uint8, pcep.CommonHeaderLength) if _, err := ss.tcpConn.Read(commonHeaderBytes); err != nil { return nil, err } @@ -244,7 +248,7 @@ func (ss *Session) readCommonHeader() (*pcep.CommonHeader, error) { func (ss *Session) handlePCRpt(length uint16) error { ss.logger.Debug("Received PCRpt Message") - messageBodyBytes := make([]uint8, length-pcep.COMMON_HEADER_LENGTH) + messageBodyBytes := make([]uint8, length-pcep.CommonHeaderLength) if _, err := ss.tcpConn.Read(messageBodyBytes); err != nil { return err } @@ -255,37 +259,236 @@ func (ss *Session) handlePCRpt(length uint16) error { } for _, sr := range message.StateReports { - // synchronization - if sr.LspObject.SFlag { - ss.logger.Debug("Synchronize SR Policy information", zap.Any("Message", message)) - ss.RegisterSRPolicy(*sr) - } else if !sr.LspObject.SFlag { - switch { - // finish synchronization - case sr.LspObject.PlspID == 0: - ss.logger.Debug("Finish PCRpt state synchronization") - ss.isSynced = true - // response to request from PCE - case sr.SrpObject.SrpID != 0: - ss.logger.Debug("Finish Stateful PCE request", zap.Uint32("srpID", sr.SrpObject.SrpID)) - if sr.LspObject.RFlag { - ss.DeleteSRPolicy(*sr) - } else { - ss.RegisterSRPolicy(*sr) - } + if sr.LSPObject.SFlag { + if err := ss.handleSynchronization(sr, message); err != nil { + return err + } + continue + } - default: - if sr.LspObject.RFlag { - ss.DeleteSRPolicy(*sr) - } else { - ss.RegisterSRPolicy(*sr) - } + switch { + case sr.LSPObject.PlspID == 0: + ss.handleFinishSynchronization() + case sr.SrpObject.SrpID != 0: + if err := ss.handleStatefulPCERequest(sr); err != nil { + return err + } + case sr.LSPObject.PlspID != 0: + if err := ss.handleSRPolicyWithPLSPID(sr); err != nil { + return err + } + default: + if err := ss.handleDefaultSRPolicy(sr); err != nil { + return err } } } + + return nil +} + +// Synchronization (S-Flag) +func (ss *Session) handleSynchronization(sr *pcep.StateReport, message *pcep.PCRptMessage) error { + ss.logger.Debug("Synchronize SR Policy information", zap.Any("Message", message)) + if err := ss.RegisterSRPolicy(*sr); err != nil { + ss.logger.Error("Failed to register SR Policy during synchronization", zap.Error(err), zap.Uint32("plspID", sr.LSPObject.PlspID)) + return err + } return nil } +// Finish synchronization (PlspID == 0) +func (ss *Session) handleFinishSynchronization() { + ss.logger.Debug("Finish PCRpt state synchronization") + ss.isSynced = true +} + +// Response to request from PCE (SrpID != 0) +func (ss *Session) handleStatefulPCERequest(sr *pcep.StateReport) error { + ss.logger.Debug("Finish Stateful PCE request", zap.Uint32("srpID", sr.SrpObject.SrpID)) + if sr.LSPObject.RFlag { + ss.DeleteSRPolicy(*sr) + } else if err := ss.RegisterSRPolicy(*sr); err != nil { + ss.logger.Error("Failed to register SR Policy for Stateful PCE request", zap.Error(err), zap.Uint32("plspID", sr.LSPObject.PlspID)) + return err + } + return nil +} + +// Receive SR Policy with PLSP-ID +func (ss *Session) handleSRPolicyWithPLSPID(sr *pcep.StateReport) error { + ss.logger.Debug("Received SR Policy", zap.Uint32("plspID", sr.LSPObject.PlspID)) + + computedSegmentList, err := ss.computePathFromTED(*sr) + if err != nil { + ss.logger.Error("Failed to compute path from TED", zap.Error(err)) + return err + } + sr.EroObject = createEroFromSegmentList(computedSegmentList) + + if err := ss.RegisterSRPolicy(*sr); err != nil { + ss.logger.Error("Failed to register SR Policy", zap.Error(err), zap.Uint32("plspID", sr.LSPObject.PlspID)) + return err + } + + policy, found := ss.SearchSRPolicy(sr.LSPObject.PlspID) + if !found { + ss.logger.Warn("SR Policy not found after registration", zap.Uint32("plspID", sr.LSPObject.PlspID)) + return fmt.Errorf("SR Policy %d not found after registration", sr.LSPObject.PlspID) + } + + if err := ss.SendPCUpdate(*policy); err != nil { + ss.logger.Error("Failed to send PC update", zap.Uint32("plspID", sr.LSPObject.PlspID), zap.Error(err)) + return err + } + return nil +} + +// Default case +func (ss *Session) handleDefaultSRPolicy(sr *pcep.StateReport) error { + if sr.LSPObject.RFlag { + ss.DeleteSRPolicy(*sr) + } else if err := ss.RegisterSRPolicy(*sr); err != nil { + ss.logger.Error("Failed to register SR Policy (default case)", zap.Error(err), zap.Uint32("plspID", sr.LSPObject.PlspID)) + return err + } + return nil +} + +func (ss *Session) computePathFromTED(sr pcep.StateReport) ([]table.Segment, error) { + if ss.ted == nil { + return nil, errors.New("TED not available") + } + + srcRouterID, dstRouterID, err := ss.extractSrcDstRouterIDs(sr) + if err != nil { + return nil, fmt.Errorf("failed to extract router IDs: %w", err) + } + + asn, err := ss.extractASN(srcRouterID) + if err != nil { + ss.logger.Error("Could not determine ASN", zap.Error(err)) + } + + metricType := ss.selectMetricType(sr) + + ss.logger.Debug("Computed CSPF parameters", + zap.String("srcRouterID", srcRouterID), + zap.String("dstRouterID", dstRouterID), + zap.Uint32("asn", asn), + zap.String("metricType", metricType.String())) + + segmentList, err := cspf.Cspf(srcRouterID, dstRouterID, asn, metricType, ss.ted) + if err != nil { + return nil, fmt.Errorf("CSPF computation failed: %w", err) + } + + return segmentList, nil +} + +func (ss *Session) extractSrcDstRouterIDs(sr pcep.StateReport) (string, string, error) { + var srcAddr, dstAddr netip.Addr + + if sr.LSPObject.SrcAddr.IsValid() { + srcAddr = sr.LSPObject.SrcAddr + } + if sr.LSPObject.DstAddr.IsValid() { + dstAddr = sr.LSPObject.DstAddr + } + + if !srcAddr.IsValid() || !dstAddr.IsValid() { + return "", "", errors.New("could not extract valid source and destination addresses") + } + + srcRouterID, err := ss.findRouterIDFromAddress(srcAddr) + if err != nil { + return "", "", fmt.Errorf("cannot find source router ID for %s: %w", srcAddr, err) + } + + dstRouterID, err := ss.findRouterIDFromAddress(dstAddr) + if err != nil { + return "", "", fmt.Errorf("cannot find destination router ID for %s: %w", dstAddr, err) + } + + return srcRouterID, dstRouterID, nil +} + +func (ss *Session) findRouterIDFromAddress(addr netip.Addr) (string, error) { + for _, nodes := range ss.ted.Nodes { + for routerID, node := range nodes { + if node.RouterID == addr.String() { + return routerID, nil + } + + for _, prefix := range node.Prefixes { + if prefix.Prefix.Addr() == addr { + return routerID, nil + } + } + } + } + return "", fmt.Errorf("address %s not found in TED", addr) +} + +func (ss *Session) extractASN(srcRouterID string) (uint32, error) { + for asn, nodes := range ss.ted.Nodes { + if _, exists := nodes[srcRouterID]; exists { + return asn, nil + } + } + return 0, fmt.Errorf("ASN not found for router %s", srcRouterID) +} + +func (ss *Session) selectMetricType(sr pcep.StateReport) table.MetricType { + if len(sr.MetricObjects) > 0 { + switch sr.MetricObjects[0].MetricType { + case 1: + return table.IGPMetric + case 2: + return table.TEMetric + case 3: + return table.DelayMetric + case 4: + return table.HopcountMetric + default: + return table.TEMetric + } + } + + switch ss.pccType { + case pcep.CiscoLegacy: + return table.TEMetric + case pcep.JuniperLegacy: + return table.IGPMetric + default: + return table.TEMetric + } +} + +func createEroFromSegmentList(segmentList []table.Segment) *pcep.EroObject { + eroObject := &pcep.EroObject{ + ObjectType: pcep.ObjectTypeEROExplicitRoute, + EroSubobjects: make([]pcep.EroSubobject, 0), + } + + for _, segment := range segmentList { + switch seg := segment.(type) { + case table.SegmentSRMPLS: + subobj, err := pcep.NewSREroSubObject(seg) + if err == nil { + eroObject.EroSubobjects = append(eroObject.EroSubobjects, subobj) + } + case table.SegmentSRv6: + subobj, err := pcep.NewSRv6EroSubObject(seg) + if err == nil { + eroObject.EroSubobjects = append(eroObject.EroSubobjects, subobj) + } + } + } + + return eroObject +} + func (ss *Session) RequestAllSRPolicyDeleted() error { var srPolicy table.SRPolicy return ss.SendPCInitiate(srPolicy, true) @@ -305,7 +508,7 @@ func (ss *Session) SendOpen() error { return err } ss.logger.Debug("Send Open Message") - return ss.sendPcepMessage(openMessage) + return ss.sendPCEPMessage(openMessage) } func (ss *Session) SendPCInitiate(srPolicy table.SRPolicy, lspDelete bool) error { @@ -314,7 +517,7 @@ func (ss *Session) SendPCInitiate(srPolicy table.SRPolicy, lspDelete bool) error return err } ss.logger.Debug("Send PCInitiate Message") - err = ss.sendPcepMessage(pcinitiateMessage) + err = ss.sendPCEPMessage(pcinitiateMessage) if err == nil { ss.srpIDHead++ } @@ -327,102 +530,133 @@ func (ss *Session) SendPCUpdate(srPolicy table.SRPolicy) error { return err } ss.logger.Debug("Send Update Message") - err = ss.sendPcepMessage(pcupdateMessage) + err = ss.sendPCEPMessage(pcupdateMessage) if err == nil { ss.srpIDHead++ } return err } -func (ss *Session) RegisterSRPolicy(sr pcep.StateReport) { - var color uint32 = 0 // Default color value (RFC does not specify a default) - var preference uint32 = 0 // Default preference value (RFC does not specify a default) +func (ss *Session) RegisterSRPolicy(sr pcep.StateReport) error { + // Resolve color and preference for this SR Policy + color, preference := ss.resolveColorPreference(&sr) + + // Determine the policy state based on O-Flag + state := resolvePolicyState(sr.LSPObject.OFlag) + + // Validate Segment List + segmentList, err := validateSegmentList(sr) + if err != nil { + return err + } + + // Update existing policy or create a new one + return ss.updateOrCreatePolicy(sr, segmentList, color, preference, state) +} + +// resolveColorPreference returns the color and preference for the SR Policy +func (ss *Session) resolveColorPreference(sr *pcep.StateReport) (uint32, uint32) { + var color, preference uint32 - if ss.pccType == pcep.CISCO_LEGACY { - // In Cisco legacy mode, get color and preference from Vendor Information Object + if ss.pccType == pcep.CiscoLegacy { + // Cisco legacy mode: get color and preference from Vendor Information Object color = sr.VendorInformationObject.Color() preference = sr.VendorInformationObject.Preference() } else { - // TODO: Move hasColorCapability to Session struct - hasColorCapability := false + // Check if PCC supports color capability + hasColor := false for _, cap := range ss.pccCapabilities { - if statefulCap, ok := cap.(*pcep.StatefulPceCapability); ok { - if statefulCap.ColorCapability { - hasColorCapability = true - break - } + if c, ok := cap.(*pcep.StatefulPCECapability); ok && c.ColorCapability { + hasColor = true + break } } - // SR Policy Association color takes precedence over LSP Object Color TLV - // Ref: https://datatracker.ietf.org/doc/draft-ietf-pce-pcep-color/12/ Section 2 - if sr.AssociationObject.Color() != 0 { - color = sr.AssociationObject.Color() - } else if hasColorCapability { - color = sr.LspObject.Color() + // SR Policy Association color takes precedence + if c := sr.AssociationObject.Color(); c != 0 { + color = c + } else if hasColor { + color = sr.LSPObject.Color() } preference = sr.AssociationObject.Preference() } - lspID := sr.LspObject.LspID + return color, preference +} - var state table.PolicyState - switch sr.LspObject.OFlag { - case uint8(0x00): - state = table.POLICY_DOWN - case uint8(0x01): - state = table.POLICY_UP - case uint8(0x02): - state = table.POLICY_ACTIVE +// resolvePolicyState converts O-Flag to internal PolicyState +func resolvePolicyState(oflag uint8) table.PolicyState { + switch oflag { + case 0x00: + return table.PolicyDown + case 0x01: + return table.PolicyUp + case 0x02: + return table.PolicyActive default: - state = table.POLICY_UNKNOWN + return table.PolicyUnknown + } +} + +// validateSegmentList checks if the Segment List exists and is non-empty +func validateSegmentList(sr pcep.StateReport) ([]table.Segment, error) { + if sr.EroObject == nil { + return nil, fmt.Errorf("EroObject is nil for PlspID %d", sr.LSPObject.PlspID) } + list := sr.EroObject.ToSegmentList() + if len(list) == 0 { + return nil, fmt.Errorf("SegmentList is empty for PlspID %d", sr.LSPObject.PlspID) + } + return list, nil +} - if p, ok := ss.SearchSRPolicy(sr.LspObject.PlspID); ok { - // update - // If the LSP ID is old, it is not the latest data update. - if p.LspID <= lspID { - p.Update( - table.PolicyDiff{ - Name: &sr.LspObject.Name, - Color: &color, - Preference: &preference, - SegmentList: sr.EroObject.ToSegmentList(), - LspID: lspID, - State: state, - }, - ) - } - } else { - // create - var src, dst netip.Addr - if src = sr.LspObject.SrcAddr; !src.IsValid() { - src = sr.AssociationObject.AssocSrc - } - if dst = sr.LspObject.DstAddr; !dst.IsValid() { - dst = sr.AssociationObject.Endpoint() +// updateOrCreatePolicy updates an existing SR Policy or creates a new one +func (ss *Session) updateOrCreatePolicy(sr pcep.StateReport, segmentList []table.Segment, color, preference uint32, state table.PolicyState) error { + lspID := sr.LSPObject.LSPID + + if p, ok := ss.SearchSRPolicy(sr.LSPObject.PlspID); ok { + // Update existing policy if LSPID is new or equal + if p.LSPID <= lspID { + p.Update(table.PolicyDiff{ + Name: &sr.LSPObject.Name, + Color: &color, + Preference: &preference, + SegmentList: segmentList, + LSPID: lspID, + State: state, + }) } - p := table.NewSRPolicy( - sr.LspObject.PlspID, - sr.LspObject.Name, - sr.EroObject.ToSegmentList(), - src, - dst, - color, - preference, - lspID, - state, - ) - ss.srPolicies = append(ss.srPolicies, p) + return nil } + + // Create a new SR Policy + src := sr.LSPObject.SrcAddr + if !src.IsValid() { + src = sr.AssociationObject.AssocSrc + } + if !src.IsValid() { + return fmt.Errorf("invalid source address for PlspID %d", sr.LSPObject.PlspID) + } + + dst := sr.LSPObject.DstAddr + if !dst.IsValid() { + dst = sr.AssociationObject.Endpoint() + } + if !dst.IsValid() { + return fmt.Errorf("invalid destination address for PlspID %d", sr.LSPObject.PlspID) + } + + p := table.NewSRPolicy(sr.LSPObject.PlspID, sr.LSPObject.Name, segmentList, src, dst, color, preference, lspID, state) + ss.srPolicies = append(ss.srPolicies, p) + return nil } func (ss *Session) DeleteSRPolicy(sr pcep.StateReport) { - lspID := sr.LspObject.LspID + lspID := sr.LSPObject.LSPID for i, v := range ss.srPolicies { // If the LSP ID is old, it is not the latest data update. - if v.PlspID == sr.LspObject.PlspID && v.LspID <= lspID { + if v.PlspID == sr.LSPObject.PlspID && v.LSPID <= lspID { ss.srPolicies[i] = ss.srPolicies[len(ss.srPolicies)-1] ss.srPolicies = ss.srPolicies[:len(ss.srPolicies)-1] break diff --git a/test/README.md b/test/README.md index f447db7a..8f67230d 100644 --- a/test/README.md +++ b/test/README.md @@ -1,6 +1,5 @@ # Scenario Test - ## 1. Install Required Tools and Container Images Make sure the following tools and container images are installed: @@ -8,14 +7,15 @@ Make sure the following tools and container images are installed: ### Docker \* Note: Please make it executable without using sudo -``` + +```bash $ docker --version Docker version 28.3.3, build 980b856 ``` ### containerlab -``` +```bash $ containerlab version ____ ___ _ _ _____ _ ___ _ _ _____ ____ _ _ / ___/ _ \| \ | |_ _|/ \ |_ _| \ | | ____| _ \| | __ _| |__ @@ -32,29 +32,27 @@ $ containerlab version ### uv -``` +```bash $ uv -V uv 0.8.13 ``` ### vjunos-router -``` -$ docker images | grep vrnetlab/juniper_vjunos-router | grep 24.2R1-S2.5 -vrnetlab/juniper_vjunos-router 24.2R1-S2.5 27c5af1efc9c 2 months ago 4.17GB +```bash +$ docker images | grep vrnetlab/juniper_vjunos-router | grep 25.2R1.9 +vrnetlab/juniper_vjunos-router 25.2R1.9 6e9b1472b46b X hours/days ago 4.18GB ``` #### how to install image -1. Get VM image from [here](https://support.juniper.net/support/downloads/) +1. Get VM image from [Juniper support downloads page](https://support.juniper.net/support/downloads/) 2. Clone the vrnetlab repository from [GitHub](https://github.com/srl-labs/vrnetlab/tree/master) -3. Create vjunos-router image - +3. Create vjunos-router image ## 2. Synchronize Dependencies with uv -``` - +```bash cd /test uv sync ``` @@ -64,7 +62,8 @@ uv sync Place the binary you want to test in the appropriate location. ex: -``` + +```bash $ ls -la /test/bin drwxrwxr-x 2 --- --- 4096 Sep 3 06:06 . drwxrwxr-x 9 --- --- 4096 Aug 28 01:23 .. @@ -76,10 +75,11 @@ drwxrwxr-x 9 --- --- 4096 Aug 28 01:23 .. ``` ## 4. Run the Test + Execute the test using the appropriate command or script. \* Note: Make sure to run `uv run pytest` with the `-s` option. Otherwise, the test fail. -``` -$ uv run pytest -s +```bash +uv run pytest -s ``` diff --git a/test/scenario_test/show_ted/srmpls/expected/srmpls.json b/test/scenario_test/show_ted/srmpls/expected/srmpls.json index fc1631b9..c0cec496 100644 --- a/test/scenario_test/show_ted/srmpls/expected/srmpls.json +++ b/test/scenario_test/show_ted/srmpls/expected/srmpls.json @@ -10,11 +10,11 @@ "localIP": "10.0.0.1", "metrics": [ { - "type": "IGP", + "type": "METRIC_TYPE_IGP", "value": 10 }, { - "type": "TE", + "type": "METRIC_TYPE_TE", "value": 10 } ], @@ -30,7 +30,8 @@ ], "routerID": "0000.0aff.0001", "srgbBegin": 800000, - "srgbEnd": 804096 + "srgbEnd": 804096, + "srv6SIDs": [] }, { "asn": 65000, @@ -42,11 +43,11 @@ "localIP": "10.0.0.2", "metrics": [ { - "type": "IGP", + "type": "METRIC_TYPE_IGP", "value": 10 }, { - "type": "TE", + "type": "METRIC_TYPE_TE", "value": 10 } ], @@ -62,7 +63,8 @@ ], "routerID": "0000.0aff.0002", "srgbBegin": 800000, - "srgbEnd": 804096 + "srgbEnd": 804096, + "srv6SIDs": [] } ] } diff --git a/test/scenario_test/show_ted/srmpls/input/polad.cfg.yaml b/test/scenario_test/show_ted/srmpls/input/polad.cfg.yaml index 1a5e381f..c3e3b881 100644 --- a/test/scenario_test/show_ted/srmpls/input/polad.cfg.yaml +++ b/test/scenario_test/show_ted/srmpls/input/polad.cfg.yaml @@ -2,7 +2,7 @@ global: pcep: address: "0.0.0.0" port: 4189 - grpc-server: + grpcServer: address: "127.0.0.1" port: 50052 log: @@ -12,6 +12,6 @@ global: enable: true source: "gobgp" gobgp: - grpc-client: + grpcClient: address: "127.0.0.1" port: 50051 diff --git a/test/scenario_test/show_ted/srmpls/topo.clab.yaml b/test/scenario_test/show_ted/srmpls/topo.clab.yaml index 6d029bc4..8a6a4581 100644 --- a/test/scenario_test/show_ted/srmpls/topo.clab.yaml +++ b/test/scenario_test/show_ted/srmpls/topo.clab.yaml @@ -2,7 +2,7 @@ name: srmpls topology: kinds: juniper_vjunosrouter: - image: vrnetlab/juniper_vjunos-router:24.2R1-S2.5 + image: vrnetlab/juniper_vjunos-router:25.2R1.9 nodes: pola: kind: linux diff --git a/test/scenario_test/show_ted/srv6-usid/expected/srv6-usid.json b/test/scenario_test/show_ted/srv6-usid/expected/srv6-usid.json new file mode 100644 index 00000000..f0f6e877 --- /dev/null +++ b/test/scenario_test/show_ted/srv6-usid/expected/srv6-usid.json @@ -0,0 +1,99 @@ +{ + "ted": [ + { + "asn": 65000, + "hostname": "jun-rt1", + "isisAreaID": "49.0000", + "links": [ + { + "adjSid": 0, + "localIP": "None", + "metrics": [ + { + "type": "METRIC_TYPE_IGP", + "value": 10 + }, + { + "type": "METRIC_TYPE_TE", + "value": 10 + } + ], + "remoteIP": "None", + "remoteNode": "0000.0aff.0002" + } + ], + "prefixes": [ + { + "prefix": "fd00::/64" + }, + { + "prefix": "fcbb:bb00:1001::/48" + } + ], + "routerID": "0000.0aff.0001", + "srgbBegin": 0, + "srgbEnd": 0, + "srv6SIDs": [ + { + "endpointBehavior": { + "Behavior": 48, + "Flags": 0, + "Algorithm": 0 + }, + "multiTopoIDs": [ + 2 + ], + "sids": [ + "fcbb:bb00:1001::" + ] + } + ] + }, + { + "asn": 65000, + "hostname": "jun-rt2", + "isisAreaID": "49.0000", + "links": [ + { + "adjSid": 0, + "localIP": "None", + "metrics": [ + { + "type": "METRIC_TYPE_IGP", + "value": 10 + }, + { + "type": "METRIC_TYPE_TE", + "value": 10 + } + ], + "remoteIP": "None", + "remoteNode": "0000.0aff.0001" + } + ], + "prefixes": [ + { + "prefix": "fcbb:bb00:1002::/48" + } + ], + "routerID": "0000.0aff.0002", + "srgbBegin": 0, + "srgbEnd": 0, + "srv6SIDs": [ + { + "endpointBehavior": { + "Behavior": 48, + "Flags": 0, + "Algorithm": 0 + }, + "multiTopoIDs": [ + 2 + ], + "sids": [ + "fcbb:bb00:1002::" + ] + } + ] + } + ] +} diff --git a/test/scenario_test/show_ted/srv6-usid/input/gobgpd.cfg.yaml b/test/scenario_test/show_ted/srv6-usid/input/gobgpd.cfg.yaml new file mode 100644 index 00000000..3945da09 --- /dev/null +++ b/test/scenario_test/show_ted/srv6-usid/input/gobgpd.cfg.yaml @@ -0,0 +1,11 @@ +global: + config: + as: 65000 + router-id: "10.255.0.255" +neighbors: + - config: + peer-as: 65000 + neighbor-address: "10.100.0.1" + afi-safis: + - config: + afi-safi-name: ls diff --git a/test/scenario_test/show_ted/srv6-usid/input/polad.cfg.yaml b/test/scenario_test/show_ted/srv6-usid/input/polad.cfg.yaml new file mode 100644 index 00000000..ebd16397 --- /dev/null +++ b/test/scenario_test/show_ted/srv6-usid/input/polad.cfg.yaml @@ -0,0 +1,17 @@ +global: + pcep: + address: "::" + port: 4189 + grpcServer: + address: "127.0.0.1" + port: 50052 + log: + path: "/var/log/pola/" + name: "polad.log" + ted: + enable: true + source: "gobgp" + gobgp: + grpcClient: + address: "127.0.0.1" + port: 50051 diff --git a/test/scenario_test/show_ted/srv6-usid/jun-rt1_conf.txt b/test/scenario_test/show_ted/srv6-usid/jun-rt1_conf.txt new file mode 100644 index 00000000..8b7c352f --- /dev/null +++ b/test/scenario_test/show_ted/srv6-usid/jun-rt1_conf.txt @@ -0,0 +1,133 @@ +interfaces { + ge-0/0/0 { + description to:rt2; + unit 0 { + family iso; + family inet6; + } + } + ge-0/0/1 { + description to:gobgp; + unit 0 { + family inet { + address 10.100.0.1/24; + } + family inet6 { + address fd00::1/64; + } + } + } + lo0 { + unit 0 { + family iso { + address 49.0000.0000.0aff.0001.00; + } + family inet6 { + address fd00:ffff::1/128; + } + } + } +} +policy-options { + policy-statement IGP-REDISTRIBUTE { + term 1 { + from protocol direct; + then accept; + } + } + policy-statement TE { + term 1 { + from family traffic-engineering; + then accept; + } + } +} +routing-options { + source-packet-routing { + srv6 { + block usid-block { + fcbb:bb00:1001::/32; + local-micro-sid { + maximum-static-sids 1791; + } + } + locator loc-rt1 { + fcbb:bb00:1001::/48; + micro-sid { + block-name usid-block; + flavor { + psp; + usd; + } + } + } + no-reduced-srh; + } + } + router-id 10.255.0.1; + autonomous-system 65000; + forwarding-table { + srv6-chain-merge; + } +} +protocols { + bgp { + group GOBGP { + type internal; + local-address 10.100.0.1; + family traffic-engineering { + unicast; + } + export TE; + neighbor 10.100.0.2; + } + } + isis { + interface ge-0/0/0.0 { + level 2 { + srv6-adjacency-segment { + unprotected { + locator loc-rt1 { + micro-adjacency-sid; + } + } + } + } + point-to-point; + } + interface lo0.0 { + passive; + } + source-packet-routing { + srv6 { + locator loc-rt1 micro-node-sid; + } + } + level 1 disable; + level 2 wide-metrics-only; + traffic-engineering { + l3-unicast-topology; + ipv6; + advertisement always; + } + no-ipv4-routing; + topologies ipv6-unicast; + export IGP-REDISTRIBUTE; + } + mpls { + traffic-engineering { + database { + import { + l3-unicast-topology { + bgp-link-state; + } + policy TE; + } + } + } + } + source-packet-routing { + srv6; + preserve-nexthop-hierarchy; + } +} diff --git a/test/scenario_test/show_ted/srv6-usid/jun-rt2_conf.txt b/test/scenario_test/show_ted/srv6-usid/jun-rt2_conf.txt new file mode 100644 index 00000000..5ae03b7a --- /dev/null +++ b/test/scenario_test/show_ted/srv6-usid/jun-rt2_conf.txt @@ -0,0 +1,89 @@ +interfaces { + ge-0/0/0 { + description to:rt1; + unit 0 { + family iso; + family inet6; + } + } + fxp0 { + unit 0 { + family inet { + address 10.0.0.15/24; + } + family inet6 { + address 2001:db8::2/64; + } + } + } + lo0 { + unit 0 { + family iso { + address 49.0000.0000.0aff.0002.00; + } + family inet6 { + address fd00:ffff::2/128; + } + } + } +} +routing-options { + source-packet-routing { + srv6 { + block usid-block { + fcbb:bb00:1002::/32; + local-micro-sid { + maximum-static-sids 1791; + } + } + locator loc-rt2 { + fcbb:bb00:1002::/48; + micro-sid { + block-name usid-block; + flavor { + psp; + usd; + } + } + } + no-reduced-srh; + } + } + router-id 10.255.0.2; + autonomous-system 65000; + forwarding-table { + srv6-chain-merge; + } +} +protocols { + isis { + interface ge-0/0/0.0 { + level 2 { + srv6-adjacency-segment { + unprotected { + locator loc-rt2 { + micro-adjacency-sid; + } + } + } + } + point-to-point; + } + interface lo0.0 { + passive; + } + source-packet-routing { + srv6 { + locator loc-rt2 micro-node-sid; + } + } + level 1 disable; + level 2 wide-metrics-only; + no-ipv4-routing; + topologies ipv6-unicast; + } + source-packet-routing { + srv6; + preserve-nexthop-hierarchy; + } +} diff --git a/test/scenario_test/show_ted/srv6-usid/topo.clab.yaml b/test/scenario_test/show_ted/srv6-usid/topo.clab.yaml new file mode 100644 index 00000000..aac26d9b --- /dev/null +++ b/test/scenario_test/show_ted/srv6-usid/topo.clab.yaml @@ -0,0 +1,39 @@ +name: srv6-usid +topology: + kinds: + juniper_vjunosrouter: + image: vrnetlab/juniper_vjunos-router:25.2R1.9 + nodes: + pola: + kind: linux + image: golang:1.24.2 + network-mode: container:gobgp + startup-delay: 10 + binds: + - ../../../bin/polad:/bin/polad + - ../../../bin/pola:/bin/pola + - input/polad.cfg.yaml:/polad.cfg.yaml + cmd: /bin/polad -f /polad.cfg.yaml & + gobgp: + kind: linux + image: golang:1.24.2 + binds: + - ../../../bin/gobgpd:/bin/gobgpd + - ../../../bin/gobgp:/bin/gobgp + - input/gobgpd.cfg.yaml:/gobgpd.cfg.yaml + exec: + - apt update + - apt install -y iproute2 iputils-ping + - ip a add dev eth1 10.100.0.2/24 + - ip -6 a add dev eth1 fd00::2/64 + - ip -6 r add fd00:ffff::/64 via fd00::1 + cmd: /bin/gobgpd -f /gobgpd.cfg.yaml & + jun-rt1: + kind: juniper_vjunosrouter + startup-config: jun-rt1_conf.txt + jun-rt2: + kind: juniper_vjunosrouter + startup-config: jun-rt2_conf.txt + links: + - endpoints: ["jun-rt1:ge-0/0/0", "jun-rt2:ge-0/0/0"] + - endpoints: ["gobgp:eth1", "jun-rt1:ge-0/0/1"] diff --git a/test/scenario_test/show_ted/test_show_ted.py b/test/scenario_test/show_ted/test_show_ted.py index 32d6a306..2c0959db 100644 --- a/test/scenario_test/show_ted/test_show_ted.py +++ b/test/scenario_test/show_ted/test_show_ted.py @@ -33,8 +33,31 @@ def test__srmpls(self, clab_deploy): time.sleep(60) output = json.loads(subprocess.run("docker exec -it clab-srmpls-pola /bin/pola -p 50052 ted -j", shell=True, capture_output=True, text=True).stdout) + print("output is", output) with open(TEST_SRMPLS_DIR+"/expected/srmpls.json") as f: expected_output = json.load(f) # Run "pola ted" cmd and ensure it returns the expected result. assert DeepDiff(output, expected_output, ignore_order=True) == {} + + + def test__srv6_usid(self, clab_deploy): + TEST_SRV6_USID_DIR = self.TEST_SHOW_TED_DIR + "/srv6-usid" + # deploy test environment by containerlab + clab_deploy(TEST_SRV6_USID_DIR) + + # wait for vJunosRouter booting + while subprocess.run("docker exec -it clab-srv6-usid-gobgp ping fd00:ffff::2 -c 1", shell=True).returncode != 0: + print("Wait for deploy vJunosRouter ...") + time.sleep(10) + + print("Wait for pola's TED to finish syncing...") + time.sleep(60) + + output = json.loads(subprocess.run("docker exec -it clab-srv6-usid-pola /bin/pola -p 50052 ted -j", shell=True, capture_output=True, text=True).stdout) + print("output is", output) + with open(TEST_SRV6_USID_DIR+"/expected/srv6-usid.json") as f: + expected_output = json.load(f) + + # Run "pola ted" cmd and ensure it returns the expected result. + assert DeepDiff(output, expected_output, ignore_order=True) == {} diff --git a/tools/grpc/go/add_sr-policy/add_sr-policy.go b/tools/grpc/go/add_sr-policy/add_sr-policy.go index 5b29a379..c628a98b 100644 --- a/tools/grpc/go/add_sr-policy/add_sr-policy.go +++ b/tools/grpc/go/add_sr-policy/add_sr-policy.go @@ -15,7 +15,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" ) func main() { @@ -34,24 +34,25 @@ func main() { } }() - c := pb.NewPceServiceClient(conn) + c := pb.NewPCEServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() ssAddr := netip.MustParseAddr("192.0.2.1") - r, err := c.CreateSRPolicy(ctx, &pb.CreateSRPolicyInput{ + r, err := c.CreateSRPolicy(ctx, &pb.CreateSRPolicyRequest{ Asn: 65000, - SRPolicy: &pb.SRPolicy{ + SrPolicy: &pb.SRPolicy{ PcepSessionAddr: ssAddr.AsSlice(), - SrcRouterID: "0000.0aff.0001", - DstRouterID: "0000.0aff.0004", + SrcRouterId: "0000.0aff.0001", + DstRouterId: "0000.0aff.0004", Color: uint32(100), PolicyName: "sample-name", - Type: pb.SRPolicyType_DYNAMIC, - Metric: pb.MetricType_TE, + Type: pb.SRPolicyType_SR_POLICY_TYPE_DYNAMIC, + Metric: pb.MetricType_METRIC_TYPE_TE, }, + SidValidate: true, }) if err != nil { log.Fatalf("c.CreateSRPolicy error: %v", err) diff --git a/tools/grpc/go/add_sr-policy_no_ls/add_sr-policy_no_ls.go b/tools/grpc/go/add_sr-policy_no_ls/add_sr-policy_no_ls.go index 8e17cd7b..328347a9 100644 --- a/tools/grpc/go/add_sr-policy_no_ls/add_sr-policy_no_ls.go +++ b/tools/grpc/go/add_sr-policy_no_ls/add_sr-policy_no_ls.go @@ -15,7 +15,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" ) func main() { @@ -34,7 +34,7 @@ func main() { } }() - c := pb.NewPceServiceClient(conn) + c := pb.NewPCEServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() @@ -43,8 +43,8 @@ func main() { srcAddr := netip.MustParseAddr("192.0.2.1") dstAddr := netip.MustParseAddr("192.0.2.2") - r, err := c.CreateSRPolicyWithoutLinkState(ctx, &pb.CreateSRPolicyInput{ - SRPolicy: &pb.SRPolicy{ + r, err := c.CreateSRPolicy(ctx, &pb.CreateSRPolicyRequest{ + SrPolicy: &pb.SRPolicy{ PcepSessionAddr: ssAddr.AsSlice(), SrcAddr: srcAddr.AsSlice(), DstAddr: dstAddr.AsSlice(), @@ -56,9 +56,10 @@ func main() { {Sid: "16004"}, }, }, + SidValidate: false, }) if err != nil { - log.Fatalf("c.CreateSRPolicyWithoutLinkState error: %v", err) + log.Fatalf("c.CreateSRPolicy error: %v", err) } log.Printf("Success: %#v", r) diff --git a/tools/grpc/go/del_session/del_session.go b/tools/grpc/go/del_session/del_session.go index 5703562d..2b871b1e 100644 --- a/tools/grpc/go/del_session/del_session.go +++ b/tools/grpc/go/del_session/del_session.go @@ -15,7 +15,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" ) func main() { @@ -34,12 +34,12 @@ func main() { } }() - c := pb.NewPceServiceClient(conn) + c := pb.NewPCEServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - ss := &pb.Session{ + ss := &pb.DeleteSessionRequest{ Addr: netip.MustParseAddr("192.0.2.1").AsSlice(), } diff --git a/tools/grpc/go/show_session/show_session.go b/tools/grpc/go/show_session/show_session.go index 5a153a51..13313687 100644 --- a/tools/grpc/go/show_session/show_session.go +++ b/tools/grpc/go/show_session/show_session.go @@ -16,8 +16,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - empty "github.com/golang/protobuf/ptypes/empty" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" ) func main() { @@ -37,13 +36,12 @@ func main() { } }() - c := pb.NewPceServiceClient(conn) + c := pb.NewPCEServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - var empty empty.Empty - ret, err := c.GetSessionList(ctx, &empty) + ret, err := c.GetSessionList(ctx, &pb.GetSessionListRequest{}) if err != nil { log.Fatalf("unable to get session list from server: %v", err) } diff --git a/tools/grpc/go/show_sr-policy/show_sr-policy_list.go b/tools/grpc/go/show_sr-policy/show_sr-policy_list.go index 4afd752d..4c5f224d 100644 --- a/tools/grpc/go/show_sr-policy/show_sr-policy_list.go +++ b/tools/grpc/go/show_sr-policy/show_sr-policy_list.go @@ -16,8 +16,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - empty "github.com/golang/protobuf/ptypes/empty" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" ) func main() { @@ -37,18 +36,17 @@ func main() { } }() - c := pb.NewPceServiceClient(conn) + c := pb.NewPCEServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - var empty empty.Empty - ret, err := c.GetSRPolicyList(ctx, &empty) + ret, err := c.GetSRPolicyList(ctx, &pb.GetSRPolicyListRequest{}) if err != nil { log.Fatalf("unable to get SR policy list from server: %v", err) } - for i, srPolicy := range ret.GetSRPolicies() { + for i, srPolicy := range ret.GetSrPolicies() { fmt.Printf("srPolicy(%d): \n", i) sessionAddr := net.IP(srPolicy.GetPcepSessionAddr()) fmt.Printf(" sessionAddr: %s\n", sessionAddr.String()) diff --git a/tools/grpc/go/show_ted/show_ted.go b/tools/grpc/go/show_ted/show_ted.go index 8afff069..a2591b4d 100644 --- a/tools/grpc/go/show_ted/show_ted.go +++ b/tools/grpc/go/show_ted/show_ted.go @@ -15,8 +15,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - empty "github.com/golang/protobuf/ptypes/empty" - pb "github.com/nttcom/pola/api/grpc" + pb "github.com/nttcom/pola/api/pola/v1" ) func main() { @@ -35,14 +34,12 @@ func main() { } }() - c := pb.NewPceServiceClient(conn) + c := pb.NewPCEServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - var empty empty.Empty - - ret, err := c.GetTed(ctx, &empty) + ret, err := c.GetTED(ctx, &pb.GetTEDRequest{}) if err != nil { log.Fatalf("unable to get TED info: %v", err) } @@ -55,6 +52,9 @@ func main() { for _, link := range node.GetLsLinks() { fmt.Printf("link info: %#v\n", link) } + for _, srv6SID := range node.GetLsSrv6Sids() { + fmt.Printf("srv6SID info: %#v\n", srv6SID) + } fmt.Println() } }