diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-07-29 17:14:00 +0000 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-04-04 22:07:46 +0900 |
commit | 00f8406cb6a207341ea4f68a8fa294f31eb7bc7b (patch) | |
tree | e423c96b98f08c9254e62e3dc689ba04d97c8059 | |
parent | 806e4c250b1eca27162b1515a7f6b712c9b79f1e (diff) |
packet/bgp: add extended-nexthop capability
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | gobgp/cmd/neighbor.go | 32 | ||||
-rw-r--r-- | packet/bgp/bgp.go | 83 | ||||
-rw-r--r-- | packet/bgp/bgp_test.go | 19 | ||||
-rw-r--r-- | server/fsm.go | 15 |
4 files changed, 148 insertions, 1 deletions
diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index 32a01876..5ab7e32c 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -292,7 +292,37 @@ func showNeighbor(args []string) error { fmt.Printf(" Remote:\n%s", s) } } - + case bgp.BGP_CAP_EXTENDED_NEXTHOP: + fmt.Printf(" %s:\t%s\n", c.Code(), support) + exnhStr := func(e *bgp.CapExtendedNexthop) string { + lines := make([]string, 0, len(e.Tuples)) + for _, t := range e.Tuples { + var nhafi string + switch int(t.NexthopAFI) { + case bgp.AFI_IP: + nhafi = "ipv4" + case bgp.AFI_IP6: + nhafi = "ipv6" + default: + nhafi = fmt.Sprintf("%d", t.NexthopAFI) + } + line := fmt.Sprintf("nlri: %s, nexthop: %s", bgp.AfiSafiToRouteFamily(t.NLRIAFI, uint8(t.NLRISAFI)), nhafi) + lines = append(lines, line) + } + return strings.Join(lines, "\n") + } + if m := lookup(c, p.Conf.LocalCap); m != nil { + e := m.(*bgp.CapExtendedNexthop) + if s := exnhStr(e); len(s) > 0 { + fmt.Printf(" Local: %s\n", s) + } + } + if m := lookup(c, p.Conf.RemoteCap); m != nil { + e := m.(*bgp.CapExtendedNexthop) + if s := exnhStr(e); len(s) > 0 { + fmt.Printf(" Remote: %s\n", s) + } + } default: fmt.Printf(" %s:\t%s\n", c.Code(), support) } 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)) + } } diff --git a/server/fsm.go b/server/fsm.go index 2f93ff03..e680f8ec 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -561,6 +561,21 @@ func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInt caps = append(caps, bgp.NewCapLongLivedGracefulRestart(ltuples)) } } + + // unnumbered BGP + if pConf.Config.NeighborInterface != "" { + tuples := []*bgp.CapExtendedNexthopTuple{} + families, _ := config.AfiSafis(pConf.AfiSafis).ToRfList() + for _, family := range families { + if family == bgp.RF_IPv6_UC { + continue + } + tuple := bgp.NewCapExtendedNexthopTuple(family, bgp.AFI_IP6) + tuples = append(tuples, tuple) + } + cap := bgp.NewCapExtendedNexthop(tuples) + caps = append(caps, cap) + } return caps } |