github.com/osrg/gobgp/v3@v3.30.0/pkg/apiutil/util.go (about)

     1  // Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package apiutil
    17  
    18  import (
    19  	"encoding/json"
    20  	"fmt"
    21  	"net"
    22  	"time"
    23  
    24  	api "github.com/osrg/gobgp/v3/api"
    25  	"github.com/osrg/gobgp/v3/pkg/packet/bgp"
    26  	tspb "google.golang.org/protobuf/types/known/timestamppb"
    27  )
    28  
    29  // workaround. This for the json format compatibility. Once we update senario tests, we can remove this.
    30  type Path struct {
    31  	Nlri  bgp.AddrPrefixInterface      `json:"nlri"`
    32  	Age   int64                        `json:"age"`
    33  	Best  bool                         `json:"best"`
    34  	Attrs []bgp.PathAttributeInterface `json:"attrs"`
    35  	Stale bool                         `json:"stale"`
    36  	// true if the path has been filtered out due to max path count reached
    37  	SendMaxFiltered bool   `json:"send-max-filtered,omitempty"`
    38  	Withdrawal      bool   `json:"withdrawal,omitempty"`
    39  	SourceID        net.IP `json:"source-id,omitempty"`
    40  	NeighborIP      net.IP `json:"neighbor-ip,omitempty"`
    41  }
    42  
    43  type Destination struct {
    44  	Paths []*Path
    45  }
    46  
    47  func (d *Destination) MarshalJSON() ([]byte, error) {
    48  	return json.Marshal(d.Paths)
    49  }
    50  
    51  func NewDestination(dst *api.Destination) *Destination {
    52  	l := make([]*Path, 0, len(dst.Paths))
    53  	for _, p := range dst.Paths {
    54  		nlri, _ := GetNativeNlri(p)
    55  		attrs, _ := GetNativePathAttributes(p)
    56  		l = append(l, &Path{
    57  			Nlri:            nlri,
    58  			Age:             p.Age.AsTime().Unix(),
    59  			Best:            p.Best,
    60  			Attrs:           attrs,
    61  			Stale:           p.Stale,
    62  			SendMaxFiltered: p.SendMaxFiltered,
    63  			Withdrawal:      p.IsWithdraw,
    64  			SourceID:        net.ParseIP(p.SourceId),
    65  			NeighborIP:      net.ParseIP(p.NeighborIp),
    66  		})
    67  	}
    68  	return &Destination{Paths: l}
    69  }
    70  
    71  func NewPath(nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, age time.Time) (*api.Path, error) {
    72  	n, err := MarshalNLRI(nlri)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	a, err := MarshalPathAttributes(attrs)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	return &api.Path{
    81  		Nlri:       n,
    82  		Pattrs:     a,
    83  		Age:        tspb.New(age),
    84  		IsWithdraw: isWithdraw,
    85  		Family:     ToApiFamily(nlri.AFI(), nlri.SAFI()),
    86  		Identifier: nlri.PathIdentifier(),
    87  	}, nil
    88  }
    89  
    90  func getNLRI(family bgp.RouteFamily, buf []byte) (bgp.AddrPrefixInterface, error) {
    91  	afi, safi := bgp.RouteFamilyToAfiSafi(family)
    92  	nlri, err := bgp.NewPrefixFromRouteFamily(afi, safi)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	if err := nlri.DecodeFromBytes(buf); err != nil {
    97  		return nil, err
    98  	}
    99  	return nlri, nil
   100  }
   101  
   102  func GetNativeNlri(p *api.Path) (bgp.AddrPrefixInterface, error) {
   103  	if p.Family == nil {
   104  		return nil, fmt.Errorf("family cannot be nil")
   105  	}
   106  	if len(p.NlriBinary) > 0 {
   107  		return getNLRI(ToRouteFamily(p.Family), p.NlriBinary)
   108  	}
   109  	return UnmarshalNLRI(ToRouteFamily(p.Family), p.Nlri)
   110  }
   111  
   112  func GetNativePathAttributes(p *api.Path) ([]bgp.PathAttributeInterface, error) {
   113  	pattrsLen := len(p.PattrsBinary)
   114  	if pattrsLen > 0 {
   115  		pattrs := make([]bgp.PathAttributeInterface, 0, pattrsLen)
   116  		for _, attr := range p.PattrsBinary {
   117  			a, err := bgp.GetPathAttribute(attr)
   118  			if err != nil {
   119  				return nil, err
   120  			}
   121  			err = a.DecodeFromBytes(attr)
   122  			if err != nil {
   123  				return nil, err
   124  			}
   125  			pattrs = append(pattrs, a)
   126  		}
   127  		return pattrs, nil
   128  	}
   129  	return UnmarshalPathAttributes(p.Pattrs)
   130  }
   131  
   132  func ToRouteFamily(f *api.Family) bgp.RouteFamily {
   133  	return bgp.AfiSafiToRouteFamily(uint16(f.Afi), uint8(f.Safi))
   134  }
   135  
   136  func ToApiFamily(afi uint16, safi uint8) *api.Family {
   137  	return &api.Family{
   138  		Afi:  api.Family_Afi(afi),
   139  		Safi: api.Family_Safi(safi),
   140  	}
   141  }