github.com/osrg/gobgp/v3@v3.30.0/pkg/apiutil/capability.go (about) 1 // Copyright (C) 2018 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 "fmt" 20 21 api "github.com/osrg/gobgp/v3/api" 22 "github.com/osrg/gobgp/v3/pkg/packet/bgp" 23 proto "google.golang.org/protobuf/proto" 24 apb "google.golang.org/protobuf/types/known/anypb" 25 ) 26 27 func NewMultiProtocolCapability(a *bgp.CapMultiProtocol) *api.MultiProtocolCapability { 28 afi, safi := bgp.RouteFamilyToAfiSafi(a.CapValue) 29 return &api.MultiProtocolCapability{ 30 Family: ToApiFamily(afi, safi), 31 } 32 } 33 34 func NewRouteRefreshCapability(a *bgp.CapRouteRefresh) *api.RouteRefreshCapability { 35 return &api.RouteRefreshCapability{} 36 } 37 38 func NewCarryingLabelInfoCapability(a *bgp.CapCarryingLabelInfo) *api.CarryingLabelInfoCapability { 39 return &api.CarryingLabelInfoCapability{} 40 } 41 42 func NewExtendedNexthopCapability(a *bgp.CapExtendedNexthop) *api.ExtendedNexthopCapability { 43 tuples := make([]*api.ExtendedNexthopCapabilityTuple, 0, len(a.Tuples)) 44 for _, t := range a.Tuples { 45 tuples = append(tuples, &api.ExtendedNexthopCapabilityTuple{ 46 NlriFamily: ToApiFamily(t.NLRIAFI, uint8(t.NLRISAFI)), 47 NexthopFamily: ToApiFamily(t.NexthopAFI, bgp.SAFI_UNICAST), 48 }) 49 } 50 return &api.ExtendedNexthopCapability{ 51 Tuples: tuples, 52 } 53 } 54 55 func NewGracefulRestartCapability(a *bgp.CapGracefulRestart) *api.GracefulRestartCapability { 56 tuples := make([]*api.GracefulRestartCapabilityTuple, 0, len(a.Tuples)) 57 for _, t := range a.Tuples { 58 tuples = append(tuples, &api.GracefulRestartCapabilityTuple{ 59 Family: ToApiFamily(t.AFI, t.SAFI), 60 Flags: uint32(t.Flags), 61 }) 62 } 63 return &api.GracefulRestartCapability{ 64 Flags: uint32(a.Flags), 65 Time: uint32(a.Time), 66 Tuples: tuples, 67 } 68 } 69 70 func NewFourOctetASNumberCapability(a *bgp.CapFourOctetASNumber) *api.FourOctetASNCapability { 71 return &api.FourOctetASNCapability{ 72 Asn: a.CapValue, 73 } 74 } 75 76 func NewAddPathCapability(a *bgp.CapAddPath) *api.AddPathCapability { 77 tuples := make([]*api.AddPathCapabilityTuple, 0, len(a.Tuples)) 78 for _, t := range a.Tuples { 79 afi, safi := bgp.RouteFamilyToAfiSafi(t.RouteFamily) 80 tuples = append(tuples, &api.AddPathCapabilityTuple{ 81 Family: ToApiFamily(afi, safi), 82 Mode: api.AddPathCapabilityTuple_Mode(t.Mode), 83 }) 84 } 85 return &api.AddPathCapability{ 86 Tuples: tuples, 87 } 88 } 89 90 func NewEnhancedRouteRefreshCapability(a *bgp.CapEnhancedRouteRefresh) *api.EnhancedRouteRefreshCapability { 91 return &api.EnhancedRouteRefreshCapability{} 92 } 93 94 func NewLongLivedGracefulRestartCapability(a *bgp.CapLongLivedGracefulRestart) *api.LongLivedGracefulRestartCapability { 95 tuples := make([]*api.LongLivedGracefulRestartCapabilityTuple, 0, len(a.Tuples)) 96 for _, t := range a.Tuples { 97 tuples = append(tuples, &api.LongLivedGracefulRestartCapabilityTuple{ 98 Family: ToApiFamily(t.AFI, uint8(t.SAFI)), 99 Flags: uint32(t.Flags), 100 Time: t.RestartTime, 101 }) 102 } 103 return &api.LongLivedGracefulRestartCapability{ 104 Tuples: tuples, 105 } 106 } 107 108 func NewRouteRefreshCiscoCapability(a *bgp.CapRouteRefreshCisco) *api.RouteRefreshCiscoCapability { 109 return &api.RouteRefreshCiscoCapability{} 110 } 111 112 func NewFQDNCapability(a *bgp.CapFQDN) *api.FqdnCapability { 113 return &api.FqdnCapability{ 114 HostName: a.HostName, 115 DomainName: a.DomainName, 116 } 117 } 118 119 func NewSoftwareVersionCapability(a *bgp.CapSoftwareVersion) *api.SoftwareVersionCapability { 120 return &api.SoftwareVersionCapability{ 121 SoftwareVersion: a.SoftwareVersion, 122 } 123 } 124 125 func NewUnknownCapability(a *bgp.CapUnknown) *api.UnknownCapability { 126 return &api.UnknownCapability{ 127 Code: uint32(a.CapCode), 128 Value: a.CapValue, 129 } 130 } 131 132 func MarshalCapability(value bgp.ParameterCapabilityInterface) (*apb.Any, error) { 133 var m proto.Message 134 switch n := value.(type) { 135 case *bgp.CapMultiProtocol: 136 m = NewMultiProtocolCapability(n) 137 case *bgp.CapRouteRefresh: 138 m = NewRouteRefreshCapability(n) 139 case *bgp.CapCarryingLabelInfo: 140 m = NewCarryingLabelInfoCapability(n) 141 case *bgp.CapExtendedNexthop: 142 m = NewExtendedNexthopCapability(n) 143 case *bgp.CapGracefulRestart: 144 m = NewGracefulRestartCapability(n) 145 case *bgp.CapFourOctetASNumber: 146 m = NewFourOctetASNumberCapability(n) 147 case *bgp.CapAddPath: 148 m = NewAddPathCapability(n) 149 case *bgp.CapEnhancedRouteRefresh: 150 m = NewEnhancedRouteRefreshCapability(n) 151 case *bgp.CapLongLivedGracefulRestart: 152 m = NewLongLivedGracefulRestartCapability(n) 153 case *bgp.CapRouteRefreshCisco: 154 m = NewRouteRefreshCiscoCapability(n) 155 case *bgp.CapFQDN: 156 m = NewFQDNCapability(n) 157 case *bgp.CapSoftwareVersion: 158 m = NewSoftwareVersionCapability(n) 159 case *bgp.CapUnknown: 160 m = NewUnknownCapability(n) 161 default: 162 return nil, fmt.Errorf("invalid capability type to marshal: %+v", value) 163 } 164 return apb.New(m) 165 } 166 167 func MarshalCapabilities(values []bgp.ParameterCapabilityInterface) ([]*apb.Any, error) { 168 caps := make([]*apb.Any, 0, len(values)) 169 for _, value := range values { 170 a, err := MarshalCapability(value) 171 if err != nil { 172 return nil, err 173 } 174 caps = append(caps, a) 175 } 176 return caps, nil 177 } 178 179 func unmarshalCapability(a *apb.Any) (bgp.ParameterCapabilityInterface, error) { 180 value, err := a.UnmarshalNew() 181 if err != nil { 182 return nil, fmt.Errorf("failed to unmarshal capability: %s", err) 183 } 184 switch a := value.(type) { 185 case *api.MultiProtocolCapability: 186 return bgp.NewCapMultiProtocol(ToRouteFamily(a.Family)), nil 187 case *api.RouteRefreshCapability: 188 return bgp.NewCapRouteRefresh(), nil 189 case *api.CarryingLabelInfoCapability: 190 return bgp.NewCapCarryingLabelInfo(), nil 191 case *api.ExtendedNexthopCapability: 192 tuples := make([]*bgp.CapExtendedNexthopTuple, 0, len(a.Tuples)) 193 for _, t := range a.Tuples { 194 var nhAfi uint16 195 switch t.NexthopFamily.Afi { 196 case api.Family_AFI_IP: 197 nhAfi = bgp.AFI_IP 198 case api.Family_AFI_IP6: 199 nhAfi = bgp.AFI_IP6 200 default: 201 return nil, fmt.Errorf("invalid address family for nexthop afi in extended nexthop capability: %s", t.NexthopFamily) 202 } 203 tuples = append(tuples, bgp.NewCapExtendedNexthopTuple(ToRouteFamily(t.NlriFamily), nhAfi)) 204 } 205 return bgp.NewCapExtendedNexthop(tuples), nil 206 case *api.GracefulRestartCapability: 207 tuples := make([]*bgp.CapGracefulRestartTuple, 0, len(a.Tuples)) 208 for _, t := range a.Tuples { 209 var forward bool 210 if t.Flags&0x80 > 0 { 211 forward = true 212 } 213 tuples = append(tuples, bgp.NewCapGracefulRestartTuple(ToRouteFamily(t.Family), forward)) 214 } 215 var restarting bool 216 if a.Flags&0x08 > 0 { 217 restarting = true 218 } 219 var notification bool 220 if a.Flags&0x04 > 0 { 221 notification = true 222 } 223 return bgp.NewCapGracefulRestart(restarting, notification, uint16(a.Time), tuples), nil 224 case *api.FourOctetASNCapability: 225 return bgp.NewCapFourOctetASNumber(a.Asn), nil 226 case *api.AddPathCapability: 227 tuples := make([]*bgp.CapAddPathTuple, 0, len(a.Tuples)) 228 for _, t := range a.Tuples { 229 tuples = append(tuples, bgp.NewCapAddPathTuple(ToRouteFamily(t.Family), bgp.BGPAddPathMode(t.Mode))) 230 } 231 return bgp.NewCapAddPath(tuples), nil 232 case *api.EnhancedRouteRefreshCapability: 233 return bgp.NewCapEnhancedRouteRefresh(), nil 234 case *api.LongLivedGracefulRestartCapability: 235 tuples := make([]*bgp.CapLongLivedGracefulRestartTuple, 0, len(a.Tuples)) 236 for _, t := range a.Tuples { 237 var forward bool 238 if t.Flags&0x80 > 0 { 239 forward = true 240 } 241 tuples = append(tuples, bgp.NewCapLongLivedGracefulRestartTuple(ToRouteFamily(t.Family), forward, t.Time)) 242 } 243 return bgp.NewCapLongLivedGracefulRestart(tuples), nil 244 case *api.RouteRefreshCiscoCapability: 245 return bgp.NewCapRouteRefreshCisco(), nil 246 case *api.FqdnCapability: 247 return bgp.NewCapFQDN(a.HostName, a.DomainName), nil 248 case *api.SoftwareVersionCapability: 249 return bgp.NewCapSoftwareVersion(a.SoftwareVersion), nil 250 case *api.UnknownCapability: 251 return bgp.NewCapUnknown(bgp.BGPCapabilityCode(a.Code), a.Value), nil 252 } 253 return nil, fmt.Errorf("invalid capability type to unmarshal: %s", a.TypeUrl) 254 } 255 256 func UnmarshalCapabilities(values []*apb.Any) ([]bgp.ParameterCapabilityInterface, error) { 257 caps := make([]bgp.ParameterCapabilityInterface, 0, len(values)) 258 for _, value := range values { 259 c, err := unmarshalCapability(value) 260 if err != nil { 261 return nil, err 262 } 263 caps = append(caps, c) 264 } 265 return caps, nil 266 }