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  }