summaryrefslogtreecommitdiffhomepage
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/pkg/zebra/zapi.go73
-rw-r--r--internal/pkg/zebra/zapi_test.go1139
2 files changed, 864 insertions, 348 deletions
diff --git a/internal/pkg/zebra/zapi.go b/internal/pkg/zebra/zapi.go
index 351a5f37..6489675d 100644
--- a/internal/pkg/zebra/zapi.go
+++ b/internal/pkg/zebra/zapi.go
@@ -1038,8 +1038,9 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8) (*Client,
// Send HELLO/ROUTER_ID_ADD messages to negotiate the Zebra message version.
c.SendHello()
c.SendRouterIDAdd()
- if version >= 4 {
- c.SendLabelManagerConnect()
+
+ if version > 4 {
+ c.SendLabelManagerConnectAsync()
}
receiveSingleMsg := func() (*Message, error) {
@@ -1341,7 +1342,7 @@ func (c *Client) SendNexthopRegister(vrfId uint32, body *NexthopRegisterBody, is
func (c *Client) SendLabelManagerConnect() error {
if c.Version < 4 {
- return fmt.Errorf("LABEL_MANAGER_CONNECT is not supported in version: %d", c.Version)
+ return fmt.Errorf("LABEL_MANAGER_CONNECT is not supported in zebra API version: %d", c.Version)
}
command := FRR_LABEL_MANAGER_CONNECT
proto := FRR_ROUTE_BGP
@@ -1359,6 +1360,28 @@ func (c *Client) SendLabelManagerConnect() error {
Instance: 0,
})
}
+
+// Reference: zread_label_manager_connect function in zebra/zserv.c of FRR3.x (ZAPI)
+// Reference: zread_label_manager_connect function in zebra/zapi_msg.c of FRR5.x and 6.x (ZAPI5 and 6)
+
+func (c *Client) SendLabelManagerConnectAsync() error {
+ if c.Version < 5 {
+ return fmt.Errorf("LABEL_MANAGER_CONNECT_ASYNC is not supported in zebra API version: %d", c.Version)
+ }
+ command := FRR_ZAPI5_LABEL_MANAGER_CONNECT_ASYNC
+ proto := FRR_ZAPI5_ROUTE_BGP
+ if c.Version == 6 {
+ command = FRR_ZAPI6_LABEL_MANAGER_CONNECT_ASYNC
+ proto = FRR_ZAPI6_ROUTE_BGP
+ }
+ return c.SendCommand(
+ command, 0,
+ &LabelManagerConnectBody{
+ RedistDefault: proto,
+ Instance: 0,
+ })
+}
+
func (c *Client) SendGetLabelChunk(body *GetLabelChunkBody) error {
if c.Version < 4 {
return fmt.Errorf("GET_LABEL_CHUNK is not supported in version: %d", c.Version)
@@ -1612,7 +1635,7 @@ type InterfaceUpdateBody struct {
// Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR3.x (ZAPI4)
// Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR5.x (ZAPI5)
func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8) error {
- if len(data) < INTERFACE_NAMSIZ+29 {
+ if len(data) < INTERFACE_NAMSIZ+33 {
return fmt.Errorf("lack of bytes. need %d but %d", INTERFACE_NAMSIZ+29, len(data))
}
@@ -1647,7 +1670,7 @@ func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8) error
}
b.HardwareAddr = data[4 : 4+l]
}
- if version >= 5 {
+ if version >= 3 {
LinkParam := data[4+l]
if LinkParam > 0 {
data = data[5+l:]
@@ -1824,6 +1847,8 @@ func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily {
return bgp.RF_IPv4_VPN
case FRR_SAFI_ENCAP, SAFI_ENCAP:
return bgp.RF_IPv4_ENCAP
+ default:
+ return bgp.RF_IPv4_UC
}
case syscall.AF_INET6:
switch b.SAFI {
@@ -1835,6 +1860,8 @@ func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily {
return bgp.RF_IPv6_VPN
case FRR_SAFI_ENCAP, SAFI_ENCAP:
return bgp.RF_IPv6_ENCAP
+ default:
+ return bgp.RF_IPv6_UC
}
default:
switch b.SAFI {
@@ -1860,6 +1887,8 @@ func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily {
return bgp.RF_IPv4_MPLS
case FRR_ZAPI5_SAFI_FLOWSPEC:
return bgp.RF_FS_IPv4_UC
+ default:
+ return bgp.RF_IPv4_UC
}
case syscall.AF_INET6:
switch b.SAFI {
@@ -1875,6 +1904,8 @@ func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily {
return bgp.RF_IPv6_MPLS
case FRR_ZAPI5_SAFI_FLOWSPEC:
return bgp.RF_FS_IPv6_UC
+ default:
+ return bgp.RF_IPv6_UC
}
default:
switch b.SAFI {
@@ -1885,7 +1916,6 @@ func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily {
}
}
}
- return bgp.RF_OPAQUE
}
func (b *IPRouteBody) IsWithdraw(version uint8) bool {
@@ -2087,7 +2117,7 @@ func (b *IPRouteBody) Serialize(version uint8) ([]byte, error) {
// Reference: zapi_route_decode function in lib/zclient.c of FRR5.x (ZAPI5)
func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error {
if b == nil {
- return fmt.Errorf("[IPRouteBody DecodeFromBytes] IPRouteBody is nil")
+ return fmt.Errorf("IPRouteBody is nil")
}
b.Prefix.Family = addressFamilyFromApi(b.Api, version)
/* REDSTRIBUTE_IPV4_ADD|DEL and REDSITRBUTE_IPV6_ADD|DEL have merged to
@@ -2126,10 +2156,11 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error {
b.Prefix.PrefixLen = data[1]
if b.Prefix.PrefixLen > addrBitLen {
- return fmt.Errorf("prefix length is greater than %d", addrByteLen*8)
+ return fmt.Errorf("prefix length %d is greater than %d", b.Prefix.PrefixLen, addrBitLen)
}
- pos := 2
- rest := len(data[pos:]) + 2
+ data = data[2:]
+ pos := 0
+ rest := len(data)
buf := make([]byte, addrByteLen)
byteLen := int((b.Prefix.PrefixLen + 7) / 8)
@@ -2139,7 +2170,6 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error {
copy(buf, data[pos:pos+byteLen])
b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, buf)
pos += byteLen
-
if (version == 4 && b.Message&FRR_MESSAGE_SRCPFX > 0) ||
(version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_SRCPFX > 0) {
if pos+1 > rest {
@@ -2152,10 +2182,10 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error {
pos += 1
buf = make([]byte, addrByteLen)
byteLen = int((b.SrcPrefix.PrefixLen + 7) / 8)
- copy(buf, data[pos:pos+byteLen])
if pos+byteLen > rest {
return fmt.Errorf("MESSAGE_SRCPFX message length invalid pos:%d rest:%d", pos, rest)
}
+ copy(buf, data[pos:pos+byteLen])
b.SrcPrefix.Prefix = ipFromFamily(b.Prefix.Family, buf)
pos += byteLen
}
@@ -2316,9 +2346,8 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error {
pos += 4
}
if pos != rest {
- return fmt.Errorf("message length invalid")
+ return fmt.Errorf("message length invalid pos:%d rest:%d", pos, rest)
}
-
return nil
}
@@ -2388,13 +2417,15 @@ func decodeNexthopsFromBytes(nexthops *[]Nexthop, data []byte, family uint8, ver
if nexthop.LabelNum > MPLS_MAX_LABEL {
nexthop.LabelNum = MPLS_MAX_LABEL
}
- nexthop.MplsLabels = make([]uint32, nexthop.LabelNum)
- for n := uint8(0); n < nexthop.LabelNum; n++ {
- /* Frr uses stream_put for mpls label array.
- stream_put is unaware of byteorder coversion.
- Therefore LittleEndian is used instead of BigEndian. */
- nexthop.MplsLabels[n] = binary.LittleEndian.Uint32(data[offset : offset+4])
- offset += 4
+ if nexthop.LabelNum > 0 {
+ nexthop.MplsLabels = make([]uint32, nexthop.LabelNum)
+ for n := uint8(0); n < nexthop.LabelNum; n++ {
+ /* Frr uses stream_put for mpls label array.
+ stream_put is unaware of byteorder coversion.
+ Therefore LittleEndian is used instead of BigEndian. */
+ nexthop.MplsLabels[n] = binary.LittleEndian.Uint32(data[offset : offset+4])
+ offset += 4
+ }
}
}
*nexthops = append(*nexthops, nexthop)
diff --git a/internal/pkg/zebra/zapi_test.go b/internal/pkg/zebra/zapi_test.go
index 12cb5f93..91056afd 100644
--- a/internal/pkg/zebra/zapi_test.go
+++ b/internal/pkg/zebra/zapi_test.go
@@ -29,313 +29,709 @@ import (
func Test_Header(t *testing.T) {
assert := assert.New(t)
- //DecodeFromBytes
- buf := make([]byte, 6)
- binary.BigEndian.PutUint16(buf[0:], 10)
- buf[2] = HEADER_MARKER
- buf[3] = 2
- binary.BigEndian.PutUint16(buf[4:], uint16(IPV4_ROUTE_ADD))
- h := &Header{}
- err := h.DecodeFromBytes(buf)
- assert.Equal(nil, err)
-
- //Serialize
- buf, err = h.Serialize()
- assert.Equal(nil, err)
- h2 := &Header{}
- err = h2.DecodeFromBytes(buf)
- assert.Equal(nil, err)
- assert.Equal(h, h2)
-
- // header_size mismatch
- buf = make([]byte, HeaderSize(2)-1)
- binary.BigEndian.PutUint16(buf[0:], 10)
- buf[2] = 0xff
- buf[3] = 0x02
- h3 := &Header{}
- err = h3.DecodeFromBytes(buf)
- assert.NotEqual(nil, err)
+ command := map[uint8]API_TYPE{
+ 2: IPV4_ROUTE_ADD,
+ 3: IPV4_ROUTE_ADD,
+ 4: FRR_IPV4_ROUTE_ADD,
+ 5: FRR_ZAPI5_IPV4_ROUTE_ADD,
+ 6: FRR_ZAPI6_ROUTE_ADD,
+ }
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ //DecodeFromBytes
+ buf := make([]byte, HeaderSize(v))
+ binary.BigEndian.PutUint16(buf[0:], HeaderSize(v))
+ buf[2] = HEADER_MARKER
+ if v >= 4 {
+ buf[2] = FRR_HEADER_MARKER
+ }
+ buf[3] = v
+ switch v {
+ case 2:
+ binary.BigEndian.PutUint16(buf[4:], uint16(command[v]))
+ case 3, 4:
+ binary.BigEndian.PutUint16(buf[4:], uint16(0)) // vrf id
+ binary.BigEndian.PutUint16(buf[6:], uint16(command[v]))
+ case 5, 6:
+ binary.BigEndian.PutUint32(buf[4:], uint32(0)) // vrf id
+ binary.BigEndian.PutUint16(buf[8:], uint16(command[v]))
+ }
+ h := &Header{}
+ err := h.DecodeFromBytes(buf)
+ assert.Equal(nil, err)
+
+ //Serialize
+ buf, err = h.Serialize()
+ assert.Equal(nil, err)
+ h2 := &Header{}
+ err = h2.DecodeFromBytes(buf)
+ assert.Equal(nil, err)
+ assert.Equal(h, h2)
+
+ // header_size mismatch
+ buf = make([]byte, HeaderSize(v)-1) // mismatch value
+ binary.BigEndian.PutUint16(buf[0:], HeaderSize(v))
+ buf[2] = HEADER_MARKER
+ if v >= 4 {
+ buf[2] = FRR_HEADER_MARKER
+ }
+ buf[3] = v
+ h3 := &Header{}
+ err = h3.DecodeFromBytes(buf)
+ assert.NotEqual(nil, err, "err should be nil")
+ }
}
func Test_InterfaceUpdateBody(t *testing.T) {
assert := assert.New(t)
- //DecodeFromBytes
- buf := make([]byte, INTERFACE_NAMSIZ+49)
- pos := INTERFACE_NAMSIZ
- binary.BigEndian.PutUint32(buf[pos:], 1)
- pos += 4
- buf[pos] = byte(INTERFACE_ACTIVE)
- pos += 1
- binary.BigEndian.PutUint64(buf[pos:], 1)
- pos += 8 // flags
- binary.BigEndian.PutUint32(buf[pos:], 1)
- pos += 4 // metric
- binary.BigEndian.PutUint32(buf[pos:], 1500)
- pos += 4 // MTU
- binary.BigEndian.PutUint32(buf[pos:], 1500)
- pos += 4 // MTU6
- binary.BigEndian.PutUint32(buf[pos:], 200)
- pos += 4 // bandwidth
- binary.BigEndian.PutUint32(buf[pos:], 6)
- pos += 4 // hwaddr_len
- mac, _ := net.ParseMAC("01:23:45:67:89:ab")
- copy(buf[pos:pos+6], []byte(mac))
- pos += 4
- b := &InterfaceUpdateBody{}
- err := b.DecodeFromBytes(buf, 2)
- assert.Equal(nil, err)
- assert.Equal("01:23:45:67:89:ab", b.HardwareAddr.String())
-
- buf = make([]byte, INTERFACE_NAMSIZ+28)
- b = &InterfaceUpdateBody{}
- err = b.DecodeFromBytes(buf, 2)
- assert.NotEqual(nil, err)
+ addSize := map[uint8]uint8{2: 39, 3: 44, 4: 50, 5: 50, 6: 50}
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ //DecodeFromBytes
+ buf := make([]byte, INTERFACE_NAMSIZ+addSize[v])
+ pos := INTERFACE_NAMSIZ
+ binary.BigEndian.PutUint32(buf[pos:], 1) //Index
+ pos += 4
+ buf[pos] = byte(INTERFACE_ACTIVE) //Status
+ pos += 1
+ binary.BigEndian.PutUint64(buf[pos:], 1)
+ pos += 8 // flags
+ if v > 3 {
+ buf[pos] = byte(PTM_ENABLE_OFF) // ptm enable
+ pos += 1
+ buf[pos] = byte(PTM_STATUS_UNKNOWN) // ptm status
+ pos += 1
+ }
+ binary.BigEndian.PutUint32(buf[pos:], 1)
+ pos += 4 // metric
+ if v > 3 {
+ binary.BigEndian.PutUint32(buf[pos:], 10000)
+ pos += 4 // speed
+ }
+ binary.BigEndian.PutUint32(buf[pos:], 1500)
+ pos += 4 // MTU
+ binary.BigEndian.PutUint32(buf[pos:], 1500)
+ pos += 4 // MTU6
+ binary.BigEndian.PutUint32(buf[pos:], 200)
+ pos += 4 // bandwidth
+ if v > 2 {
+ binary.BigEndian.PutUint32(buf[pos:], uint32(LINK_TYPE_ETHER))
+ pos += 4 // Linktype
+ }
+ binary.BigEndian.PutUint32(buf[pos:], 6)
+ pos += 4 // hwaddr_len
+ mac, _ := net.ParseMAC("01:23:45:67:89:ab")
+ copy(buf[pos:pos+6], []byte(mac))
+ pos += 6
+ if v > 2 {
+ buf[pos] = byte(0) // link param
+ pos += 1
+ }
+ b := &InterfaceUpdateBody{}
+ err := b.DecodeFromBytes(buf, v)
+ assert.Equal(nil, err)
+ assert.Equal("01:23:45:67:89:ab", b.HardwareAddr.String())
+ buf = make([]byte, INTERFACE_NAMSIZ+32) //size mismatch
+ b = &InterfaceUpdateBody{}
+ err = b.DecodeFromBytes(buf, v)
+ assert.NotEqual(nil, err)
+ }
}
func Test_InterfaceAddressUpdateBody(t *testing.T) {
assert := assert.New(t)
- //DecodeFromBytes
- buf := make([]byte, 15)
- pos := 0
- binary.BigEndian.PutUint32(buf[pos:], 0) // index
- pos += 4
- buf[pos] = 0x01 // flags
- pos += 1
- buf[pos] = 0x2 // family
- pos += 1
- ip := net.ParseIP("192.168.100.1").To4() // prefix
- copy(buf[pos:pos+4], []byte(ip))
- pos += 4
- buf[pos] = byte(24) // prefix len
- pos += 1
- dst := net.ParseIP("192.168.100.255").To4() // destination
- copy(buf[pos:pos+4], []byte(dst))
-
- b := &InterfaceAddressUpdateBody{}
- err := b.DecodeFromBytes(buf, 2)
- require.NoError(t, err)
-
- assert.Equal(uint32(0), b.Index)
- assert.Equal(INTERFACE_ADDRESS_FLAG(1), b.Flags)
- assert.Equal("192.168.100.1", b.Prefix.String())
- assert.Equal(uint8(24), b.Length)
- assert.Equal("192.168.100.255", b.Destination.String())
-
- // af invalid
- buf[5] = 0x4
- pos += 1
- b = &InterfaceAddressUpdateBody{}
- err = b.DecodeFromBytes(buf, 2)
- assert.NotEqual(nil, err)
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ //DecodeFromBytes
+ buf := make([]byte, 15)
+ pos := 0
+ binary.BigEndian.PutUint32(buf[pos:], 0) // index
+ pos += 4
+ buf[pos] = 0x01 // flags
+ pos += 1
+ buf[pos] = 0x2 // family
+ pos += 1
+ ip := net.ParseIP("192.168.100.1").To4() // prefix
+ copy(buf[pos:pos+4], []byte(ip))
+ pos += 4
+ buf[pos] = byte(24) // prefix len
+ pos += 1
+ dst := net.ParseIP("192.168.100.255").To4() // destination
+ copy(buf[pos:pos+4], []byte(dst))
+
+ b := &InterfaceAddressUpdateBody{}
+ err := b.DecodeFromBytes(buf, v)
+ require.NoError(t, err)
+
+ assert.Equal(uint32(0), b.Index)
+ assert.Equal(INTERFACE_ADDRESS_FLAG(1), b.Flags)
+ assert.Equal("192.168.100.1", b.Prefix.String())
+ assert.Equal(uint8(24), b.Length)
+ assert.Equal("192.168.100.255", b.Destination.String())
+
+ // af invalid
+ buf[5] = 0x4
+ pos += 1
+ b = &InterfaceAddressUpdateBody{}
+ err = b.DecodeFromBytes(buf, v)
+ assert.NotEqual(nil, err)
+ }
}
func Test_RouterIDUpdateBody(t *testing.T) {
assert := assert.New(t)
- //DecodeFromBytes
- buf := make([]byte, 6)
- pos := 0
- buf[pos] = 0x2
- pos += 1
- ip := net.ParseIP("192.168.100.1").To4()
- copy(buf[pos:pos+4], []byte(ip))
- pos += 4
- buf[pos] = byte(32)
-
- b := &RouterIDUpdateBody{}
- err := b.DecodeFromBytes(buf, 2)
- assert.Equal(nil, err)
- assert.Equal("192.168.100.1", b.Prefix.String())
- assert.Equal(uint8(32), b.Length)
-
- // af invalid
- buf[0] = 0x4
- pos += 1
- b = &RouterIDUpdateBody{}
- err = b.DecodeFromBytes(buf, 2)
- assert.NotEqual(nil, err)
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ //DecodeFromBytes
+ buf := make([]byte, 6)
+ pos := 0
+ buf[pos] = 0x2
+ pos += 1
+ ip := net.ParseIP("192.168.100.1").To4()
+ copy(buf[pos:pos+4], []byte(ip))
+ pos += 4
+ buf[pos] = byte(32)
+
+ b := &RouterIDUpdateBody{}
+ err := b.DecodeFromBytes(buf, v)
+ assert.Equal(nil, err)
+ assert.Equal("192.168.100.1", b.Prefix.String())
+ assert.Equal(uint8(32), b.Length)
+
+ // af invalid
+ buf[0] = 0x4
+ pos += 1
+ b = &RouterIDUpdateBody{}
+ err = b.DecodeFromBytes(buf, v)
+ assert.NotEqual(nil, err)
+ }
}
func Test_IPRouteBody_IPv4(t *testing.T) {
assert := assert.New(t)
- //DecodeFromBytes IPV4_ROUTE
- buf := make([]byte, 26)
- buf[0] = byte(ROUTE_CONNECT)
- buf[1] = byte(FLAG_SELECTED)
- buf[2] = byte(MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU)
- buf[3] = 24
- ip := net.ParseIP("192.168.100.0").To4()
- copy(buf[4:7], []byte(ip))
-
- buf[7] = 1
- nexthop := net.ParseIP("0.0.0.0").To4()
- copy(buf[8:12], []byte(nexthop))
-
- buf[12] = 1
- binary.BigEndian.PutUint32(buf[13:], 1)
- buf[17] = 0 // distance
- binary.BigEndian.PutUint32(buf[18:], 1)
- binary.BigEndian.PutUint32(buf[22:], 1)
- r := &IPRouteBody{Api: IPV4_ROUTE_ADD}
- err := r.DecodeFromBytes(buf, 2)
-
- assert.Equal(nil, err)
- assert.Equal("192.168.100.0", r.Prefix.Prefix.String())
- assert.Equal(uint8(0x18), r.Prefix.PrefixLen)
- assert.Equal(MESSAGE_NEXTHOP|MESSAGE_IFINDEX|MESSAGE_DISTANCE|MESSAGE_METRIC|MESSAGE_MTU, r.Message)
- assert.Equal("0.0.0.0", r.Nexthops[0].Gate.String())
- assert.Equal(uint32(1), r.Nexthops[1].Ifindex)
- assert.Equal(uint8(0), r.Distance)
- assert.Equal(uint32(1), r.Metric)
- assert.Equal(uint32(1), r.Mtu)
-
- //Serialize
- buf, err = r.Serialize(2)
- assert.Equal(nil, err)
- assert.Equal([]byte{0x2, 0x10, 0x1f}, buf[0:3])
- assert.Equal([]byte{0x0, 0x1}, buf[3:5])
- assert.Equal(byte(24), buf[5])
- ip = net.ParseIP("192.168.100.0").To4()
- assert.Equal([]byte(ip)[0:3], buf[6:9])
- assert.Equal(byte(2), buf[9])
- assert.Equal(byte(NEXTHOP_TYPE_IPV4), buf[10])
- assert.Equal(byte(NEXTHOP_TYPE_IFINDEX), buf[15])
- assert.Equal(byte(0x0), buf[20])
-
- bi := make([]byte, 4)
- binary.BigEndian.PutUint32(bi, 1)
- assert.Equal(bi, buf[21:25])
- assert.Equal(bi, buf[25:])
-
- // length invalid
- buf = make([]byte, 18)
- buf[0] = byte(ROUTE_CONNECT)
- buf[1] = byte(FLAG_SELECTED)
- buf[2] = byte(MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC)
- buf[3] = 24
- ip = net.ParseIP("192.168.100.0").To4()
- copy(buf[4:7], []byte(ip))
- buf[7] = 1
- nexthop = net.ParseIP("0.0.0.0").To4()
- copy(buf[8:12], []byte(nexthop))
- buf[12] = 1
- binary.BigEndian.PutUint32(buf[13:], 1)
-
- r = &IPRouteBody{Api: IPV4_ROUTE_ADD}
- err = r.DecodeFromBytes(buf, 2)
- assert.Equal("MESSAGE_METRIC message length invalid pos:16 rest:16", err.Error())
-
- // no nexthop
- buf = make([]byte, 12)
- buf[0] = byte(ROUTE_CONNECT)
- buf[1] = byte(FLAG_SELECTED)
- buf[2] = byte(MESSAGE_DISTANCE | MESSAGE_METRIC)
- buf[3] = 24
- ip = net.ParseIP("192.168.100.0").To4()
- copy(buf[4:7], []byte(ip))
- buf[7] = 1
- binary.BigEndian.PutUint32(buf[8:], 0)
- r = &IPRouteBody{Api: IPV4_ROUTE_ADD}
- err = r.DecodeFromBytes(buf, 2)
- assert.Equal(nil, err)
-
+ size := map[uint8]uint8{2: 26, 3: 26, 4: 31, 5: 38, 6: 38}
+ command := map[uint8]API_TYPE{
+ 2: IPV4_ROUTE_ADD,
+ 3: IPV4_ROUTE_ADD,
+ 4: FRR_IPV4_ROUTE_ADD,
+ 5: FRR_ZAPI5_IPV4_ROUTE_ADD,
+ 6: FRR_ZAPI6_ROUTE_ADD,
+ }
+ routeType := map[uint8]ROUTE_TYPE{
+ 2: ROUTE_CONNECT,
+ 3: ROUTE_CONNECT,
+ 4: FRR_ROUTE_CONNECT,
+ 5: FRR_ZAPI5_ROUTE_CONNECT,
+ 6: FRR_ZAPI6_ROUTE_CONNECT,
+ }
+ message := map[uint8]MESSAGE_FLAG{
+ 2: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU,
+ 3: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU,
+ 4: FRR_MESSAGE_NEXTHOP | FRR_MESSAGE_IFINDEX | FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC | FRR_MESSAGE_MTU,
+ 5: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU,
+ 6: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU,
+ }
+ messageWithoutNexthop := map[uint8]MESSAGE_FLAG{
+ 2: MESSAGE_DISTANCE | MESSAGE_METRIC,
+ 3: MESSAGE_DISTANCE | MESSAGE_METRIC,
+ 4: FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC,
+ 5: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC,
+ 6: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC,
+ }
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ //DecodeFromBytes IPV4_ROUTE
+ buf := make([]byte, size[v])
+ buf[0] = byte(routeType[v])
+ pos := 1
+ switch v {
+ case 2, 3:
+ buf[pos] = byte(FLAG_SELECTED)
+ pos += 1
+ case 4, 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED))
+ pos += 4
+ }
+ buf[pos] = byte(message[v])
+ pos += 1
+ if v > 4 {
+ buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI
+ pos += 1
+ buf[pos] = byte(syscall.AF_INET) //Family
+ pos += 1
+ }
+ buf[pos] = 24 // PrefixLen
+ pos += 1
+ ip := net.ParseIP("192.168.100.0").To4()
+ copy(buf[pos:pos+3], []byte(ip))
+ pos += 3
+ switch v {
+ case 2, 3, 4:
+ buf[pos] = byte(1) // Number of Nexthops
+ pos += 1
+ case 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
+ pos += 4
+ buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV4_IFINDEX)
+ pos += 1
+ }
+ nexthop := net.ParseIP("0.0.0.0").To4()
+ copy(buf[pos:pos+4], []byte(nexthop))
+ pos += 4
+ if v < 5 {
+ buf[pos] = 1 // Number of ifindex
+ pos += 1
+ }
+ binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex
+ pos += 4
+ buf[pos] = 0 // distance
+ pos += 1
+ binary.BigEndian.PutUint32(buf[pos:], 1) // metric
+ pos += 4
+ binary.BigEndian.PutUint32(buf[pos:], 1) // mtu
+ pos += 4
+ r := &IPRouteBody{Api: command[v]}
+ err := r.DecodeFromBytes(buf, v)
+ assert.Equal(nil, err)
+ assert.Equal("192.168.100.0", r.Prefix.Prefix.String())
+ assert.Equal(uint8(0x18), r.Prefix.PrefixLen)
+ assert.Equal(message[v], r.Message)
+ assert.Equal("0.0.0.0", r.Nexthops[0].Gate.String())
+ switch v {
+ case 2, 3, 4:
+ assert.Equal(uint32(1), r.Nexthops[1].Ifindex)
+ case 5, 6:
+ assert.Equal(uint32(1), r.Nexthops[0].Ifindex)
+ }
+ assert.Equal(uint8(0), r.Distance)
+ assert.Equal(uint32(1), r.Metric)
+ assert.Equal(uint32(1), r.Mtu)
+
+ //Serialize
+ buf, err = r.Serialize(v)
+ assert.Equal(nil, err)
+ switch v {
+ case 2, 3:
+ assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3])
+ pos = 3
+ case 4, 5, 6:
+ assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, byte(message[v])}, buf[0:8])
+ pos = 8
+ }
+ switch v {
+ case 2, 3, 4:
+ assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // SAFI
+ pos += 2
+ case 5, 6:
+ assert.Equal(byte(0x1), buf[pos]) // SAFI
+ pos += 1
+ assert.Equal(byte(0x2), buf[pos]) // Family
+ pos += 1
+
+ }
+ assert.Equal(byte(24), buf[pos])
+ pos += 1
+ ip = net.ParseIP("192.168.100.0").To4()
+ assert.Equal([]byte(ip)[0:3], buf[pos:pos+3])
+ pos += 3
+ switch v {
+ case 2, 3, 4:
+ assert.Equal(byte(2), buf[pos]) // number of nexthop
+ pos += 1
+ case 5, 6:
+ assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // number of nexthop
+ pos += 2
+ assert.Equal([]byte{0x0, 0x0, 0x0, 0x0}, buf[pos:pos+4]) // vrfid
+ pos += 4
+ }
+ switch v {
+ case 2, 3:
+ assert.Equal(byte(NEXTHOP_TYPE_IPV4), buf[pos])
+ assert.Equal(byte(NEXTHOP_TYPE_IFINDEX), buf[pos+5])
+ pos += 10
+ case 4:
+ assert.Equal(byte(FRR_NEXTHOP_TYPE_IPV4), buf[pos])
+ assert.Equal(byte(FRR_NEXTHOP_TYPE_IFINDEX), buf[pos+5])
+ pos += 10
+ case 5, 6:
+ assert.Equal(byte(FRR_NEXTHOP_TYPE_IPV4_IFINDEX), buf[pos])
+ pos += 9
+ }
+ assert.Equal(byte(0x0), buf[pos]) // distance
+ bi := make([]byte, 4)
+ binary.BigEndian.PutUint32(bi, 1)
+ assert.Equal(bi, buf[pos+1:pos+5]) //metric
+ assert.Equal(bi, buf[pos+5:pos+9]) //mtu
+
+ // length invalid
+ buf = make([]byte, size[v]-8)
+ buf[0] = byte(routeType[v])
+ pos = 1
+ switch v {
+ case 2, 3:
+ buf[pos] = byte(FLAG_SELECTED)
+ pos += 1
+ case 4, 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED))
+ pos += 4
+ }
+ buf[pos] = byte(message[v])
+ pos += 1
+ if v > 4 {
+ buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI
+ pos += 1
+ buf[pos] = byte(syscall.AF_INET) //Family
+ pos += 1
+ }
+ buf[pos] = 24 // PrefixLen
+ pos += 1
+ ip = net.ParseIP("192.168.100.0").To4()
+ copy(buf[pos:pos+3], []byte(ip))
+ pos += 3
+ switch v {
+ case 2, 3, 4:
+ buf[pos] = byte(1) // Number of Nexthops
+ pos += 1
+ case 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
+ pos += 4
+ buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV4_IFINDEX)
+ pos += 1
+ }
+ nexthop = net.ParseIP("0.0.0.0").To4()
+ copy(buf[pos:pos+4], []byte(nexthop))
+ pos += 4
+ if v < 5 {
+ buf[pos] = 1 // Number of ifindex
+ pos += 1
+ }
+ binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex
+ pos += 4
+
+ r = &IPRouteBody{Api: command[v]}
+ err = r.DecodeFromBytes(buf, v)
+ switch v {
+ case 2, 3, 4:
+ assert.Equal("MESSAGE_METRIC message length invalid pos:14 rest:14", err.Error())
+ case 5, 6:
+ assert.Equal("MESSAGE_METRIC message length invalid pos:19 rest:19", err.Error())
+ }
+
+ // no nexthop
+ switch v {
+ case 2, 3, 4:
+ buf = make([]byte, size[v]-14)
+ case 5, 6:
+ buf = make([]byte, size[v]-19)
+ }
+ buf[0] = byte(routeType[v])
+ pos = 1
+ switch v {
+ case 2, 3:
+ buf[pos] = byte(FLAG_SELECTED)
+ pos += 1
+ case 4, 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED))
+ pos += 4
+ }
+ buf[pos] = byte(messageWithoutNexthop[v])
+ pos += 1
+ if v > 4 {
+ buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI
+ pos += 1
+ buf[pos] = byte(syscall.AF_INET) //Family
+ pos += 1
+ }
+ buf[pos] = 24 // PrefixLen
+ pos += 1
+ ip = net.ParseIP("192.168.100.0").To4()
+ copy(buf[pos:pos+3], []byte(ip))
+ pos += 3
+ buf[pos] = 1 // distance
+ pos += 1
+ binary.BigEndian.PutUint32(buf[pos:], 0) //metric
+ pos += 4
+ r = &IPRouteBody{Api: command[v]}
+ err = r.DecodeFromBytes(buf, v)
+ assert.Equal(nil, err)
+ }
}
func Test_IPRouteBody_IPv6(t *testing.T) {
assert := assert.New(t)
-
- //DecodeFromBytes IPV6_ROUTE
- buf := make([]byte, 43)
- buf[0] = byte(ROUTE_CONNECT)
- buf[1] = byte(FLAG_SELECTED)
- buf[2] = byte(MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU)
- buf[3] = 64
- ip := net.ParseIP("2001:db8:0:f101::").To16()
- copy(buf[4:12], []byte(ip))
-
- buf[12] = 1
- nexthop := net.ParseIP("::").To16()
- copy(buf[13:29], []byte(nexthop))
- // ifindex
- buf[29] = 1
- binary.BigEndian.PutUint32(buf[30:], 1)
-
- buf[34] = 0 // distance
- binary.BigEndian.PutUint32(buf[35:], 1)
- binary.BigEndian.PutUint32(buf[39:], 1)
- r := &IPRouteBody{Api: IPV6_ROUTE_ADD}
- err := r.DecodeFromBytes(buf, 2)
-
- assert.Equal(nil, err)
- assert.Equal("2001:db8:0:f101::", r.Prefix.Prefix.String())
- assert.Equal(uint8(64), r.Prefix.PrefixLen)
- assert.Equal(MESSAGE_NEXTHOP|MESSAGE_IFINDEX|MESSAGE_DISTANCE|MESSAGE_METRIC|MESSAGE_MTU, r.Message)
- assert.Equal("::", r.Nexthops[0].Gate.String())
- assert.Equal(uint32(1), r.Nexthops[1].Ifindex)
- assert.Equal(uint8(0), r.Distance)
- assert.Equal(uint32(1), r.Metric)
- assert.Equal(uint32(1), r.Mtu)
-
- //Serialize
- buf, err = r.Serialize(2)
- assert.Equal(nil, err)
- assert.Equal([]byte{0x2, 0x10, 0x1f}, buf[0:3])
- assert.Equal([]byte{0x0, 0x1}, buf[3:5])
- assert.Equal(byte(64), buf[5])
- ip = net.ParseIP("2001:db8:0:f101::").To16()
- assert.Equal([]byte(ip)[0:8], buf[6:14])
- assert.Equal(byte(2), buf[14])
- assert.Equal(byte(NEXTHOP_TYPE_IPV6), buf[15])
- ip = net.ParseIP("::").To16()
- assert.Equal([]byte(ip), buf[16:32])
- assert.Equal(byte(NEXTHOP_TYPE_IFINDEX), buf[32])
- bi := make([]byte, 4)
- binary.BigEndian.PutUint32(bi, 1)
- assert.Equal(bi, buf[33:37])
-
- //distance
- assert.Equal(byte(0), buf[37])
- bi = make([]byte, 4)
- binary.BigEndian.PutUint32(bi, 1)
- assert.Equal(bi, buf[38:42])
- assert.Equal(bi, buf[42:])
-
- // length invalid
- buf = make([]byte, 50)
- buf[0] = byte(ROUTE_CONNECT)
- buf[1] = byte(FLAG_SELECTED)
- buf[2] = byte(MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC)
- buf[3] = 24
- ip = net.ParseIP("2001:db8:0:f101::").To4()
- copy(buf[4:12], []byte(ip))
- buf[13] = 1
- nexthop = net.ParseIP("::").To16()
- copy(buf[14:30], []byte(nexthop))
- buf[31] = 1
- binary.BigEndian.PutUint32(buf[32:], 1)
-
- r = &IPRouteBody{Api: IPV6_ROUTE_ADD}
- err = r.DecodeFromBytes(buf, 2)
- assert.Equal("message length invalid", err.Error())
-
- // no nexthop
- buf = make([]byte, 11)
- buf[0] = byte(ROUTE_CONNECT)
- buf[1] = byte(FLAG_SELECTED)
- buf[2] = byte(MESSAGE_DISTANCE | MESSAGE_METRIC)
- buf[3] = 16
- ip = net.ParseIP("2501::").To16()
- copy(buf[4:6], []byte(ip))
- buf[6] = 1
- binary.BigEndian.PutUint32(buf[7:], 0)
- r = &IPRouteBody{Api: IPV6_ROUTE_ADD}
- err = r.DecodeFromBytes(buf, 2)
- assert.Equal(nil, err)
+ size := map[uint8]uint8{2: 43, 3: 43, 4: 48, 5: 55, 6: 55}
+ command := map[uint8]API_TYPE{
+ 2: IPV6_ROUTE_ADD,
+ 3: IPV6_ROUTE_ADD,
+ 4: FRR_IPV6_ROUTE_ADD,
+ 5: FRR_ZAPI5_IPV6_ROUTE_ADD,
+ 6: FRR_ZAPI6_ROUTE_ADD,
+ }
+ routeType := map[uint8]ROUTE_TYPE{
+ 2: ROUTE_CONNECT,
+ 3: ROUTE_CONNECT,
+ 4: FRR_ROUTE_CONNECT,
+ 5: FRR_ZAPI5_ROUTE_CONNECT,
+ 6: FRR_ZAPI6_ROUTE_CONNECT,
+ }
+ message := map[uint8]MESSAGE_FLAG{
+ 2: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU,
+ 3: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU,
+ 4: FRR_MESSAGE_NEXTHOP | FRR_MESSAGE_IFINDEX | FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC | FRR_MESSAGE_MTU,
+ 5: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU,
+ 6: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU,
+ }
+ nexthopType := map[uint8]NEXTHOP_TYPE{
+ 2: NEXTHOP_TYPE_IPV6,
+ 3: NEXTHOP_TYPE_IPV6,
+ 4: FRR_NEXTHOP_TYPE_IPV6,
+ 5: FRR_NEXTHOP_TYPE_IPV6_IFINDEX,
+ 6: FRR_NEXTHOP_TYPE_IPV6_IFINDEX,
+ }
+ messageWithoutNexthop := map[uint8]MESSAGE_FLAG{
+ 2: MESSAGE_DISTANCE | MESSAGE_METRIC,
+ 3: MESSAGE_DISTANCE | MESSAGE_METRIC,
+ 4: FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC,
+ 5: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC,
+ 6: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC,
+ }
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ //DecodeFromBytes IPV6_ROUTE
+ buf := make([]byte, size[v])
+ buf[0] = byte(routeType[v])
+ pos := 1
+ switch v {
+ case 2, 3:
+ buf[pos] = byte(FLAG_SELECTED)
+ pos += 1
+ case 4, 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED))
+ pos += 4
+ }
+ buf[pos] = byte(message[v])
+ pos += 1
+ if v > 4 {
+ buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI
+ pos += 1
+ buf[pos] = byte(syscall.AF_INET6) //Family
+ pos += 1
+ }
+ buf[pos] = 64 // prefixLen
+ pos += 1
+ ip := net.ParseIP("2001:db8:0:f101::").To16()
+ copy(buf[pos:pos+8], []byte(ip))
+ pos += 8
+ switch v {
+ case 2, 3, 4:
+ buf[pos] = byte(1) // Number of Nexthops
+ pos += 1
+ case 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
+ pos += 4
+ buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV6_IFINDEX)
+ pos += 1
+ }
+ nexthop := net.ParseIP("::").To16()
+ copy(buf[pos:pos+16], []byte(nexthop))
+ pos += 16
+ if v < 5 {
+ buf[pos] = 1 // Number of ifindex
+ pos += 1
+ }
+ binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex
+ pos += 4
+ buf[pos] = 0 // distance
+ pos += 1
+ binary.BigEndian.PutUint32(buf[pos:], 1) // metric
+ pos += 4
+ binary.BigEndian.PutUint32(buf[pos:], 1) // mtu
+ pos += 4
+ r := &IPRouteBody{Api: command[v]}
+ err := r.DecodeFromBytes(buf, v)
+ assert.Equal(nil, err)
+ assert.Equal("2001:db8:0:f101::", r.Prefix.Prefix.String())
+ assert.Equal(uint8(64), r.Prefix.PrefixLen)
+ assert.Equal(message[v], r.Message)
+ assert.Equal("::", r.Nexthops[0].Gate.String())
+ switch v {
+ case 2, 3, 4:
+ assert.Equal(uint32(1), r.Nexthops[1].Ifindex)
+ case 5, 6:
+ assert.Equal(uint32(1), r.Nexthops[0].Ifindex)
+ }
+ assert.Equal(uint8(0), r.Distance)
+ assert.Equal(uint32(1), r.Metric)
+ assert.Equal(uint32(1), r.Mtu)
+
+ //Serialize
+ buf, err = r.Serialize(v)
+ assert.Equal(nil, err)
+ switch v {
+ case 2, 3:
+ assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3])
+ pos = 3
+ case 4, 5, 6:
+ assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, byte(message[v])}, buf[0:8])
+ pos = 8
+ }
+ switch v {
+ case 2, 3, 4:
+ assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // SAFI
+ pos += 2
+ case 5, 6:
+ assert.Equal(byte(0x1), buf[pos]) // SAFI
+ pos += 1
+ assert.Equal(byte(syscall.AF_INET6), buf[pos]) // Family
+ pos += 1
+ }
+ assert.Equal(byte(64), buf[pos])
+ pos += 1
+ ip = net.ParseIP("2001:db8:0:f101::").To16()
+ assert.Equal([]byte(ip)[0:8], buf[pos:pos+8])
+ pos += 8
+ switch v {
+ case 2, 3, 4:
+ assert.Equal(byte(2), buf[pos]) // number of nexthop
+ pos += 1
+ case 5, 6:
+ assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // number of nexthop
+ pos += 2
+ assert.Equal([]byte{0x0, 0x0, 0x0, 0x0}, buf[pos:pos+4]) // vrfid
+ pos += 4
+ }
+ assert.Equal(byte(nexthopType[v]), buf[pos])
+ pos += 1
+ ip = net.ParseIP("::").To16()
+ assert.Equal([]byte(ip), buf[pos:pos+16])
+ pos += 16
+ switch v { // Only Quagga (ZAPI version 2,3) and FRR 3.x (ZAPI version 4)
+ case 2, 3:
+ assert.Equal(byte(NEXTHOP_TYPE_IFINDEX), buf[pos])
+ pos += 1
+ case 4:
+ assert.Equal(byte(FRR_NEXTHOP_TYPE_IFINDEX), buf[pos])
+ pos += 1
+ }
+ bi := make([]byte, 4)
+ binary.BigEndian.PutUint32(bi, 1)
+ assert.Equal(bi, buf[pos:pos+4]) // ifindex
+ pos += 4
+ assert.Equal(byte(0x0), buf[pos]) // distance
+ assert.Equal(bi, buf[pos+1:pos+5]) //metric
+ assert.Equal(bi, buf[pos+5:pos+9]) //mtu
+
+ // length invalid
+ buf = make([]byte, size[v]+7)
+ buf[0] = byte(routeType[v])
+ pos = 1
+ switch v {
+ case 2, 3:
+ buf[pos] = byte(FLAG_SELECTED)
+ pos += 1
+ case 4, 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED))
+ pos += 4
+ }
+ buf[pos] = byte(message[v])
+ pos += 1
+ if v > 4 {
+ buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI
+ pos += 1
+ buf[pos] = byte(syscall.AF_INET6) //Family
+ pos += 1
+ }
+ buf[pos] = 64 // prefixLen
+ pos += 1
+ ip = net.ParseIP("2001:db8:0:f101::").To16()
+ copy(buf[pos:pos+8], []byte(ip))
+ pos += 8
+ switch v {
+ case 2, 3, 4:
+ buf[pos] = byte(1) // Number of Nexthops
+ pos += 1
+ case 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
+ pos += 4
+ buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV6_IFINDEX)
+ pos += 1
+ }
+ nexthop = net.ParseIP("::").To16()
+ copy(buf[pos:pos+16], []byte(nexthop))
+ pos += 16
+ if v < 5 {
+ buf[pos] = 1 // Number of ifindex
+ pos += 1
+ }
+ binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex
+ pos += 4
+
+ r = &IPRouteBody{Api: command[v]}
+ err = r.DecodeFromBytes(buf, v)
+ switch v {
+ case 2, 3, 4:
+ assert.Equal("message length invalid pos:39 rest:46", err.Error())
+ case 5, 6:
+ assert.Equal("message length invalid pos:44 rest:51", err.Error())
+ }
+
+ // no nexthop
+ switch v {
+ case 2, 3, 4:
+ buf = make([]byte, size[v]-32)
+ case 5, 6:
+ buf = make([]byte, size[v]-37)
+ }
+ buf[0] = byte(routeType[v])
+ pos = 1
+ switch v {
+ case 2, 3:
+ buf[pos] = byte(FLAG_SELECTED)
+ pos += 1
+ case 4, 5, 6:
+ binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
+ pos += 2
+ binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED))
+ pos += 4
+ }
+ buf[pos] = byte(messageWithoutNexthop[v])
+ pos += 1
+ if v > 4 {
+ buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI
+ pos += 1
+ buf[pos] = byte(syscall.AF_INET) //Family
+ pos += 1
+ }
+ buf[pos] = 16 // PrefixLen
+ pos += 1
+ ip = net.ParseIP("2501::").To16()
+ copy(buf[pos:pos+2], []byte(ip))
+ pos += 2
+ buf[pos] = 1 //distance
+ binary.BigEndian.PutUint32(buf[pos:], 0) //metic
+ r = &IPRouteBody{Api: command[v]}
+ err = r.DecodeFromBytes(buf, v)
+ assert.Equal(nil, err)
+ }
}
+// NexthopLookup exists in only quagga (zebra API version 2 and 3)
func Test_NexthopLookupBody(t *testing.T) {
assert := assert.New(t)
@@ -418,6 +814,7 @@ func Test_NexthopLookupBody(t *testing.T) {
assert.NotEqual(nil, err)
}
+// ImportLookup exists in only quagga (zebra API version 2 and 3)
func Test_ImportLookupBody(t *testing.T) {
assert := assert.New(t)
@@ -475,58 +872,146 @@ func Test_NexthopRegisterBody(t *testing.T) {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
}
- binary.BigEndian.PutUint16(bufIn[1:], syscall.AF_INET)
- binary.BigEndian.PutUint16(bufIn[9:], syscall.AF_INET6)
-
- // Test DecodeFromBytes()
- b := &NexthopRegisterBody{Api: NEXTHOP_REGISTER}
- err := b.DecodeFromBytes(bufIn, 3)
- assert.Nil(err)
-
- // Test decoded values
- assert.Equal(uint8(1), b.Nexthops[0].Connected)
- assert.Equal(uint16(syscall.AF_INET), b.Nexthops[0].Family)
- assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Nexthops[0].Prefix)
- assert.Equal(uint8(0), b.Nexthops[1].Connected)
- assert.Equal(uint16(syscall.AF_INET6), b.Nexthops[1].Family)
- assert.Equal(net.ParseIP("2001:db8:1:1::1").To16(), b.Nexthops[1].Prefix)
-
- // Test Serialize()
- bufOut, err := b.Serialize(3)
- assert.Nil(err)
-
- // Test serialised value
- assert.Equal(bufIn, bufOut)
+ command := map[uint8]API_TYPE{
+ 2: NEXTHOP_REGISTER,
+ 3: NEXTHOP_REGISTER,
+ 4: FRR_NEXTHOP_REGISTER,
+ 5: FRR_ZAPI5_NEXTHOP_REGISTER,
+ 6: FRR_ZAPI6_NEXTHOP_REGISTER,
+ }
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ // Test DecodeFromBytes()
+ b := &NexthopRegisterBody{Api: command[v]}
+ err := b.DecodeFromBytes(bufIn, v)
+ assert.Nil(err)
+
+ // Test decoded values
+ assert.Equal(uint8(1), b.Nexthops[0].Connected)
+ assert.Equal(uint16(syscall.AF_INET), b.Nexthops[0].Family)
+ assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Nexthops[0].Prefix)
+ assert.Equal(uint8(0), b.Nexthops[1].Connected)
+ assert.Equal(uint16(syscall.AF_INET6), b.Nexthops[1].Family)
+ assert.Equal(net.ParseIP("2001:db8:1:1::1").To16(), b.Nexthops[1].Prefix)
+
+ // Test Serialize()
+ bufOut, err := b.Serialize(v)
+ assert.Nil(err)
+
+ // Test serialised value
+ assert.Equal(bufIn, bufOut)
+ }
}
func Test_NexthopUpdateBody(t *testing.T) {
assert := assert.New(t)
- // Input binary
- bufIn := []byte{
- 0x00, 0x02, 0x20, // afi(2 bytes)=AF_INET, prefix_len(1 byte)=32
- 0xc0, 0xa8, 0x01, 0x01, // prefix(4 bytes)="192.168.1.1"
- 0x00, 0x00, 0x00, 0x01, // metric(4 bytes)=1
- 0x01, // nexthops(1 byte)=1
- 0x04, // nexthop_type(1 byte)=NEXTHOP_IPV4_IFINDEX
- 0xc0, 0xa8, 0x01, 0x01, // nexthop_ip(4 bytes)="192.168.0.1"
- 0x00, 0x00, 0x00, 0x02, // nexthop_ifindex(4 byte)=2
+ size := map[uint8]uint8{2: 21, 3: 21, 4: 22, 5: 26, 6: 26}
+ command := map[uint8]API_TYPE{
+ 2: NEXTHOP_UPDATE,
+ 3: NEXTHOP_UPDATE,
+ 4: FRR_NEXTHOP_UPDATE,
+ 5: FRR_ZAPI5_NEXTHOP_UPDATE,
+ 6: FRR_ZAPI6_NEXTHOP_UPDATE,
+ }
+ nexthopType := map[uint8]NEXTHOP_TYPE{
+ 2: NEXTHOP_TYPE_IPV4_IFINDEX,
+ 3: NEXTHOP_TYPE_IPV4_IFINDEX,
+ 4: FRR_NEXTHOP_TYPE_IPV4_IFINDEX,
+ 5: FRR_NEXTHOP_TYPE_IPV4_IFINDEX,
+ 6: FRR_NEXTHOP_TYPE_IPV4_IFINDEX,
+ }
+
+ for v := MinZapiVer; v <= MaxZapiVer; v++ {
+ // Input binary
+ bufIn := make([]byte, size[v])
+ // afi(2 bytes)=AF_INET, prefix_len(1 byte)=32, prefix(4 bytes)="192.168.1.1"
+ copy(bufIn[0:7], []byte{0x00, 0x02, 0x20, 0xc0, 0xa8, 0x01, 0x01})
+ pos := 7
+ if v > 4 { // Type(1byte), Instance(2byte)
+ copy(bufIn[pos:pos+3], []byte{byte(FRR_ZAPI5_ROUTE_CONNECT), 0x00, 0x00})
+ pos += 3
+ }
+ if v > 3 { // Distance
+ bufIn[pos] = 0
+ pos += 1
+ }
+ // metric(4 bytes)=1, number of nexthops(1 byte)=1
+ copy(bufIn[pos:pos+5], []byte{0x00, 0x00, 0x00, 0x01, 0x01})
+ pos += 5
+ bufIn[pos] = byte(nexthopType[v])
+ pos += 1
+ // nexthop_ip(4 bytes)="192.168.0.1", nexthop_ifindex(4 byte)=2
+ copy(bufIn[pos:pos+8], []byte{0xc0, 0xa8, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02})
+ pos += 8
+ if v > 4 {
+ bufIn[pos] = byte(0) // label num
+ pos += 1
+ }
+
+ // Test DecodeFromBytes()
+ b := &NexthopUpdateBody{Api: command[v]}
+ err := b.DecodeFromBytes(bufIn, v)
+ assert.Nil(err)
+
+ // Test decoded values
+ assert.Equal(uint8(syscall.AF_INET), b.Prefix.Family)
+ assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Prefix.Prefix)
+ assert.Equal(uint32(1), b.Metric)
+ nexthop := Nexthop{
+ Type: nexthopType[v],
+ Gate: net.ParseIP("192.168.1.1").To4(),
+ Ifindex: uint32(2),
+ }
+ assert.Equal(1, len(b.Nexthops))
+ assert.Equal(nexthop, b.Nexthops[0])
}
+}
- // Test DecodeFromBytes()
- b := &NexthopUpdateBody{Api: NEXTHOP_UPDATE}
- err := b.DecodeFromBytes(bufIn, 2)
- assert.Nil(err)
-
- // Test decoded values
- assert.Equal(uint8(syscall.AF_INET), b.Prefix.Family)
- assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Prefix.Prefix)
- assert.Equal(uint32(1), b.Metric)
- nexthop := Nexthop{
- Type: NEXTHOP_TYPE(NEXTHOP_TYPE_IPV4_IFINDEX),
- Gate: net.ParseIP("192.168.1.1").To4(),
- Ifindex: uint32(2),
+func Test_GetLabelChunkBody(t *testing.T) {
+ assert := assert.New(t)
+
+ // Test only with ZAPI version 5 and 6
+ routeType := map[uint8]ROUTE_TYPE{5: FRR_ZAPI5_ROUTE_BGP, 6: FRR_ZAPI6_ROUTE_BGP}
+ for v := uint8(5); v <= MaxZapiVer; v++ {
+ //DecodeFromBytes
+ buf := make([]byte, 12)
+ buf[0] = byte(routeType[v]) // Route Type
+ binary.BigEndian.PutUint16(buf[1:], 0) //Instance
+ buf[3] = 0 //Keep
+ binary.BigEndian.PutUint32(buf[4:], 80) //Start
+ binary.BigEndian.PutUint32(buf[8:], 89) //End
+
+ b := &GetLabelChunkBody{}
+ err := b.DecodeFromBytes(buf, v)
+ assert.Equal(nil, err)
+
+ //Serialize
+ b.ChunkSize = 10
+ buf, err = b.Serialize(v)
+ assert.Equal(nil, err)
+ assert.Equal(byte(routeType[v]), buf[0])
+ bi := make([]byte, 4)
+ binary.BigEndian.PutUint32(bi, 10)
+ assert.Equal(bi, buf[4:8]) // Chunksize
+ }
+}
+
+func Test_VrfLabelBody(t *testing.T) {
+ assert := assert.New(t)
+ // Test only with ZAPI version 5 and 6
+ for v := uint8(5); v <= MaxZapiVer; v++ {
+ //DecodeFromBytes
+ bufIn := make([]byte, 6)
+ binary.BigEndian.PutUint32(bufIn[0:], 80) //label
+ bufIn[4] = byte(AFI_IP)
+ bufIn[5] = byte(LSP_BGP)
+ b := &VrfLabelBody{}
+ err := b.DecodeFromBytes(bufIn, v)
+ assert.Equal(nil, err)
+ //Serialize
+ var bufOut []byte
+ bufOut, err = b.Serialize(v)
+ assert.Equal(nil, err)
+ assert.Equal(bufIn, bufOut)
}
- assert.Equal(1, len(b.Nexthops))
- assert.Equal(nexthop, b.Nexthops[0])
}