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