diff options
Diffstat (limited to 'packet')
-rw-r--r-- | packet/bgp/bgp.go | 83 | ||||
-rw-r--r-- | packet/bgp/bgp_test.go | 19 |
2 files changed, 102 insertions, 0 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index 3afb7a9e..d7479172 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -208,6 +208,7 @@ const ( BGP_CAP_MULTIPROTOCOL BGPCapabilityCode = 1 BGP_CAP_ROUTE_REFRESH BGPCapabilityCode = 2 BGP_CAP_CARRYING_LABEL_INFO BGPCapabilityCode = 4 + BGP_CAP_EXTENDED_NEXTHOP BGPCapabilityCode = 5 BGP_CAP_GRACEFUL_RESTART BGPCapabilityCode = 64 BGP_CAP_FOUR_OCTET_AS_NUMBER BGPCapabilityCode = 65 BGP_CAP_ADD_PATH BGPCapabilityCode = 69 @@ -221,6 +222,7 @@ var CapNameMap = map[BGPCapabilityCode]string{ BGP_CAP_ROUTE_REFRESH: "route-refresh", BGP_CAP_CARRYING_LABEL_INFO: "carrying-label-info", BGP_CAP_GRACEFUL_RESTART: "graceful-restart", + BGP_CAP_EXTENDED_NEXTHOP: "extended-nexthop", BGP_CAP_FOUR_OCTET_AS_NUMBER: "4-octet-as", BGP_CAP_ADD_PATH: "add-path", BGP_CAP_ENHANCED_ROUTE_REFRESH: "enhanced-route-refresh", @@ -336,6 +338,85 @@ type CapCarryingLabelInfo struct { DefaultParameterCapability } +type CapExtendedNexthopTuple struct { + NLRIAFI uint16 + NLRISAFI uint16 + NexthopAFI uint16 +} + +func (c *CapExtendedNexthopTuple) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + NLRIAddressFamily RouteFamily `json:"nlri_address_family"` + NexthopAddressFamily uint16 `json:"nexthop_address_family"` + }{ + NLRIAddressFamily: AfiSafiToRouteFamily(c.NLRIAFI, uint8(c.NLRISAFI)), + NexthopAddressFamily: c.NexthopAFI, + }) +} + +func NewCapExtendedNexthopTuple(af RouteFamily, nexthop uint16) *CapExtendedNexthopTuple { + afi, safi := RouteFamilyToAfiSafi(af) + return &CapExtendedNexthopTuple{ + NLRIAFI: afi, + NLRISAFI: uint16(safi), + NexthopAFI: nexthop, + } +} + +type CapExtendedNexthop struct { + DefaultParameterCapability + Tuples []*CapExtendedNexthopTuple +} + +func (c *CapExtendedNexthop) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + if len(data) < 6 { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityExtendedNexthop bytes available") + } + c.Tuples = []*CapExtendedNexthopTuple{} + for len(data) >= 6 { + t := &CapExtendedNexthopTuple{ + binary.BigEndian.Uint16(data[0:2]), + binary.BigEndian.Uint16(data[2:4]), + binary.BigEndian.Uint16(data[4:6]), + } + c.Tuples = append(c.Tuples, t) + data = data[6:] + } + return nil +} + +func (c *CapExtendedNexthop) Serialize() ([]byte, error) { + buf := make([]byte, len(c.Tuples)*6) + for i, t := range c.Tuples { + binary.BigEndian.PutUint16(buf[i*6:i*6+2], t.NLRIAFI) + binary.BigEndian.PutUint16(buf[i*6+2:i*6+4], t.NLRISAFI) + binary.BigEndian.PutUint16(buf[i*6+4:i*6+6], t.NexthopAFI) + } + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapExtendedNexthop) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Code BGPCapabilityCode `json:"code"` + Tuples []*CapExtendedNexthopTuple `json:"tuples"` + }{ + Code: c.Code(), + Tuples: c.Tuples, + }) +} + +func NewCapExtendedNexthop(tuples []*CapExtendedNexthopTuple) *CapExtendedNexthop { + return &CapExtendedNexthop{ + DefaultParameterCapability{ + CapCode: BGP_CAP_EXTENDED_NEXTHOP, + }, + tuples, + } +} + type CapGracefulRestartTuple struct { AFI uint16 SAFI uint8 @@ -687,6 +768,8 @@ func DecodeCapability(data []byte) (ParameterCapabilityInterface, error) { c = &CapRouteRefresh{} case BGP_CAP_CARRYING_LABEL_INFO: c = &CapCarryingLabelInfo{} + case BGP_CAP_EXTENDED_NEXTHOP: + c = &CapExtendedNexthop{} case BGP_CAP_GRACEFUL_RESTART: c = &CapGracefulRestart{} case BGP_CAP_FOUR_OCTET_AS_NUMBER: diff --git a/packet/bgp/bgp_test.go b/packet/bgp/bgp_test.go index e6d38873..bb93cee5 100644 --- a/packet/bgp/bgp_test.go +++ b/packet/bgp/bgp_test.go @@ -514,6 +514,25 @@ func Test_EVPNIPPrefixRoute(t *testing.T) { t.Error(len(buf2), n2, buf2) t.Log(bytes.Equal(buf1, buf2)) } +} + +func Test_CapExtendedNexthop(t *testing.T) { + assert := assert.New(t) + tuple := NewCapExtendedNexthopTuple(RF_IPv4_UC, AFI_IP6) + n1 := NewCapExtendedNexthop([]*CapExtendedNexthopTuple{tuple}) + buf1, err := n1.Serialize() + assert.Nil(err) + n2, err := DecodeCapability(buf1) + assert.Nil(err) + buf2, _ := n2.Serialize() + if reflect.DeepEqual(n1, n2) { + t.Log("OK") + } else { + t.Error("Something wrong") + t.Error(len(buf1), n1, buf1) + t.Error(len(buf2), n2, buf2) + t.Log(bytes.Equal(buf1, buf2)) + } } |