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  }