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 }