From e80b6ece00bec96ec331c839f9a61cf19027295e Mon Sep 17 00:00:00 2001 From: ISHIDA Wataru Date: Wed, 22 Feb 2017 06:51:59 +0000 Subject: packet/bgp: fix mp-reach-nlri attribute decoder/encoder Current mp-reach-nlri attribute decoder/encoder assumes NLRI's address family and that of nexthop is the same. However, when extended nexthop capability(RFC5549) is negotiated, this is not the case. This commit removes the assumption. Signed-off-by: ISHIDA Wataru --- packet/bgp/bgp.go | 20 ++++++++++---------- packet/bgp/bgp_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index a911c411..3afb7a9e 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -5189,20 +5189,20 @@ func (p *PathAttributeMpReachNLRI) DecodeFromBytes(data []byte) error { } nexthopbin := value[4 : 4+nexthoplen] if nexthoplen > 0 { - addrlen := 4 - if afi == AFI_IP6 { - addrlen = 16 - } + v4addrlen := 4 + v6addrlen := 16 offset := 0 if safi == SAFI_MPLS_VPN { offset = 8 } switch nexthoplen { - case 2 * (offset + addrlen): - p.LinkLocalNexthop = nexthopbin[offset+addrlen+offset : 2*(offset+addrlen)] + case 2 * (offset + v6addrlen): + p.LinkLocalNexthop = nexthopbin[offset+v6addrlen+offset : 2*(offset+v6addrlen)] fallthrough - case offset + addrlen: - p.Nexthop = nexthopbin[offset : offset+addrlen] + case offset + v6addrlen: + p.Nexthop = nexthopbin[offset : offset+v6addrlen] + case offset + v4addrlen: + p.Nexthop = nexthopbin[offset : offset+v4addrlen] default: return NewMessageError(eCode, eSubCode, value, "mpreach nexthop length is incorrect") } @@ -5235,7 +5235,7 @@ func (p *PathAttributeMpReachNLRI) Serialize() ([]byte, error) { afi := p.AFI safi := p.SAFI nexthoplen := 4 - if afi == AFI_IP6 { + if afi == AFI_IP6 || p.Nexthop.To4() == nil { nexthoplen = 16 } offset := 0 @@ -5254,7 +5254,7 @@ func (p *PathAttributeMpReachNLRI) Serialize() ([]byte, error) { buf[2] = safi buf[3] = uint8(nexthoplen) if nexthoplen != 0 { - if afi == AFI_IP6 { + if p.Nexthop.To4() == nil { copy(buf[4+offset:], p.Nexthop.To16()) if p.LinkLocalNexthop != nil { copy(buf[4+offset+16:], p.LinkLocalNexthop.To16()) diff --git a/packet/bgp/bgp_test.go b/packet/bgp/bgp_test.go index e0f1a5ca..e6d38873 100644 --- a/packet/bgp/bgp_test.go +++ b/packet/bgp/bgp_test.go @@ -739,3 +739,37 @@ func Test_MpReachNLRIWithVPNv6Prefix(t *testing.T) { // Test serialised value assert.Equal(bufin, bufout) } + +func Test_MpReachNLRIWithIPv4PrefixWithIPv6Nexthop(t *testing.T) { + assert := assert.New(t) + bufin := []byte{ + 0x80, 0x0e, 0x19, // flags(1), type(1), length(1) + 0x00, 0x01, 0x01, 0x10, // afi(1), safi(1), nexthoplen(1) + 0x20, 0x01, 0x0d, 0xb8, // nexthop(32) + 0x00, 0x01, 0x00, 0x00, // = "2001:db8:1::1" + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, // reserved(1) + 0x18, 0xc0, 0xa8, 0x0a, // nlri(7) + } + // Test DecodeFromBytes() + p := &PathAttributeMpReachNLRI{} + err := p.DecodeFromBytes(bufin) + assert.Nil(err) + // Test decoded values + assert.Equal(BGPAttrFlag(0x80), p.Flags) + assert.Equal(BGPAttrType(0xe), p.Type) + assert.Equal(uint16(0x19), p.Length) + assert.Equal(uint16(AFI_IP), p.AFI) + assert.Equal(uint8(SAFI_UNICAST), p.SAFI) + assert.Equal(net.ParseIP("2001:db8:1::1"), p.Nexthop) + value := []AddrPrefixInterface{ + NewIPAddrPrefix(24, "192.168.10.0"), + } + assert.Equal(value, p.Value) + // Test Serialize() + bufout, err := p.Serialize() + assert.Nil(err) + // Test serialised value + assert.Equal(bufin, bufout) +} -- cgit v1.2.3