github.com/osrg/gobgp/v3@v3.30.0/pkg/zebra/zapi_test.go (about)

     1  // Copyright (C) 2014, 2015 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 zebra
    17  
    18  import (
    19  	"encoding/binary"
    20  	"net"
    21  	"syscall"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func Test_Header(t *testing.T) {
    29  	assert := assert.New(t)
    30  
    31  	command := map[uint8]APIType{
    32  		2: zapi3IPv4RouteAdd,
    33  		3: zapi3IPv4RouteAdd,
    34  		4: zapi4IPv4RouteAdd,
    35  		5: zapi6Frr7RouteAdd,
    36  		6: zapi6Frr7RouteAdd,
    37  	}
    38  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
    39  		//decodeFromBytes
    40  		buf := make([]byte, HeaderSize(v))
    41  		binary.BigEndian.PutUint16(buf[0:], HeaderSize(v))
    42  		buf[2] = headerMarker
    43  		if v >= 4 {
    44  			buf[2] = frrHeaderMarker
    45  		}
    46  		buf[3] = v
    47  		switch v {
    48  		case 2:
    49  			binary.BigEndian.PutUint16(buf[4:], uint16(command[v]))
    50  		case 3, 4:
    51  			binary.BigEndian.PutUint16(buf[4:], uint16(0)) // vrf id
    52  			binary.BigEndian.PutUint16(buf[6:], uint16(command[v]))
    53  		case 5, 6:
    54  			binary.BigEndian.PutUint32(buf[4:], uint32(0)) // vrf id
    55  			binary.BigEndian.PutUint16(buf[8:], uint16(command[v]))
    56  		}
    57  		h := &Header{}
    58  		err := h.decodeFromBytes(buf)
    59  		assert.Equal(nil, err)
    60  
    61  		//serialize
    62  		buf, err = h.serialize()
    63  		assert.Equal(nil, err)
    64  		h2 := &Header{}
    65  		err = h2.decodeFromBytes(buf)
    66  		assert.Equal(nil, err)
    67  		assert.Equal(h, h2)
    68  
    69  		// header_size mismatch
    70  		buf = make([]byte, HeaderSize(v)-1) // mismatch value
    71  		binary.BigEndian.PutUint16(buf[0:], HeaderSize(v))
    72  		buf[2] = headerMarker
    73  		if v >= 4 {
    74  			buf[2] = frrHeaderMarker
    75  		}
    76  		buf[3] = v
    77  		h3 := &Header{}
    78  		err = h3.decodeFromBytes(buf)
    79  		assert.NotEqual(nil, err, "err should be nil")
    80  	}
    81  }
    82  
    83  func Test_interfaceUpdateBody(t *testing.T) {
    84  	assert := assert.New(t)
    85  
    86  	addSize := map[uint8]uint8{2: 39, 3: 44, 4: 50, 5: 50, 6: 54}
    87  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
    88  		//decodeFromBytes
    89  		buf := make([]byte, interfaceNameSize+addSize[v])
    90  		pos := interfaceNameSize
    91  		binary.BigEndian.PutUint32(buf[pos:], 1) //Index
    92  		pos += 4
    93  		buf[pos] = byte(interfaceActive) //Status
    94  		pos++
    95  		binary.BigEndian.PutUint64(buf[pos:], 1)
    96  		pos += 8 // flags
    97  		if v > 3 {
    98  			buf[pos] = byte(ptmEnableOff) // ptm enable
    99  			pos++
   100  			buf[pos] = byte(ptmStatusUnknown) // ptm status
   101  			pos++
   102  		}
   103  		binary.BigEndian.PutUint32(buf[pos:], 1)
   104  		pos += 4 // metric
   105  		if v > 3 {
   106  			binary.BigEndian.PutUint32(buf[pos:], 10000)
   107  			pos += 4 // speed
   108  		}
   109  		binary.BigEndian.PutUint32(buf[pos:], 1500)
   110  		pos += 4 // MTU
   111  		binary.BigEndian.PutUint32(buf[pos:], 1500)
   112  		pos += 4 // MTU6
   113  		binary.BigEndian.PutUint32(buf[pos:], 200)
   114  		pos += 4    // bandwidth
   115  		if v == 6 { // "frr7.2", ""
   116  			binary.BigEndian.PutUint32(buf[pos:], 1)
   117  			pos += 4 // link Ifindex
   118  		}
   119  		if v > 2 {
   120  			binary.BigEndian.PutUint32(buf[pos:], uint32(linkTypeEther))
   121  			pos += 4 // Linktype
   122  		}
   123  		binary.BigEndian.PutUint32(buf[pos:], 6)
   124  		pos += 4 // hwaddr_len
   125  		mac, _ := net.ParseMAC("01:23:45:67:89:ab")
   126  		copy(buf[pos:pos+6], []byte(mac))
   127  		pos += 6
   128  		if v > 2 {
   129  			buf[pos] = byte(0) // link param
   130  			pos++
   131  		}
   132  		b := &interfaceUpdateBody{}
   133  		software := NewSoftware(v, "")
   134  		err := b.decodeFromBytes(buf, v, software)
   135  		assert.Equal(nil, err)
   136  		assert.Equal("01:23:45:67:89:ab", b.hardwareAddr.String())
   137  		buf = make([]byte, interfaceNameSize+32) //size mismatch
   138  		b = &interfaceUpdateBody{}
   139  		err = b.decodeFromBytes(buf, v, software)
   140  		assert.NotEqual(nil, err)
   141  	}
   142  }
   143  
   144  func Test_interfaceAddressUpdateBody(t *testing.T) {
   145  	assert := assert.New(t)
   146  
   147  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
   148  		//decodeFromBytes
   149  		buf := make([]byte, 15)
   150  		pos := 0
   151  		binary.BigEndian.PutUint32(buf[pos:], 0) // index
   152  		pos += 4
   153  		buf[pos] = 0x01 // flags
   154  		pos++
   155  		buf[pos] = 0x2 // family
   156  		pos++
   157  		ip := net.ParseIP("192.168.100.1").To4() // prefix
   158  		copy(buf[pos:pos+4], []byte(ip))
   159  		pos += 4
   160  		buf[pos] = byte(24) // prefix len
   161  		pos++
   162  		dst := net.ParseIP("192.168.100.255").To4() // destination
   163  		copy(buf[pos:pos+4], []byte(dst))
   164  
   165  		b := &interfaceAddressUpdateBody{}
   166  		software := NewSoftware(v, "")
   167  		err := b.decodeFromBytes(buf, v, software)
   168  		require.NoError(t, err)
   169  
   170  		assert.Equal(uint32(0), b.index)
   171  		assert.Equal(interfaceAddressFlag(1), b.flags)
   172  		assert.Equal("192.168.100.1", b.prefix.String())
   173  		assert.Equal(uint8(24), b.length)
   174  		assert.Equal("192.168.100.255", b.destination.String())
   175  
   176  		// af invalid
   177  		buf[5] = 0x4
   178  		pos++
   179  		b = &interfaceAddressUpdateBody{}
   180  		err = b.decodeFromBytes(buf, v, software)
   181  		assert.NotEqual(nil, err)
   182  	}
   183  }
   184  
   185  func Test_routerIDUpdateBody(t *testing.T) {
   186  	assert := assert.New(t)
   187  
   188  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
   189  		//decodeFromBytes
   190  		buf := make([]byte, 6)
   191  		pos := 0
   192  		buf[pos] = 0x2
   193  		pos++
   194  		ip := net.ParseIP("192.168.100.1").To4()
   195  		copy(buf[pos:pos+4], []byte(ip))
   196  		pos += 4
   197  		buf[pos] = byte(32)
   198  
   199  		b := &routerIDUpdateBody{}
   200  		software := NewSoftware(v, "")
   201  		err := b.decodeFromBytes(buf, v, software)
   202  		assert.Equal(nil, err)
   203  		assert.Equal("192.168.100.1", b.prefix.String())
   204  		assert.Equal(uint8(32), b.length)
   205  
   206  		// af invalid
   207  		buf[0] = 0x4
   208  		pos++
   209  		b = &routerIDUpdateBody{}
   210  		err = b.decodeFromBytes(buf, v, software)
   211  		assert.NotEqual(nil, err)
   212  	}
   213  }
   214  
   215  func Test_IPRouteBody_IPv4(t *testing.T) {
   216  	assert := assert.New(t)
   217  
   218  	size := map[uint8]uint8{2: 26, 3: 26, 4: 31, 5: 38, 6: 42}
   219  	command := map[uint8]APIType{
   220  		2: zapi3IPv4RouteAdd,
   221  		3: zapi3IPv4RouteAdd,
   222  		4: zapi4IPv4RouteAdd,
   223  		5: zapi6Frr7RouteAdd,
   224  		6: RouteAdd,
   225  	}
   226  	routeType := routeConnect
   227  	message := map[uint8]MessageFlag{
   228  		2: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU,
   229  		3: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU,
   230  		4: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi4MessageMTU,
   231  		5: MessageNexthop | MessageDistance | MessageMetric | MessageMTU,
   232  		6: MessageNexthop | MessageDistance | MessageMetric | MessageMTU,
   233  	}
   234  	messageWithoutNexthop := map[uint8]MessageFlag{
   235  		2: zapi4MessageDistance | zapi4MessageMetric,
   236  		3: zapi4MessageDistance | zapi4MessageMetric,
   237  		4: zapi4MessageDistance | zapi4MessageMetric,
   238  		5: MessageDistance | MessageMetric,
   239  		6: MessageDistance | MessageMetric,
   240  	}
   241  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
   242  		//decodeFromBytes IPV4_ROUTE
   243  		buf := make([]byte, size[v])
   244  		buf[0] = byte(routeType)
   245  		pos := 1
   246  		software := NewSoftware(v, "")
   247  		switch v {
   248  		case 2, 3:
   249  			buf[pos] = byte(FlagSelected.ToEach(v, software))
   250  			pos++
   251  		case 4, 5, 6:
   252  			binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
   253  			pos += 2
   254  			binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, software)))
   255  			pos += 4
   256  		}
   257  		if v == 6 {
   258  			binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit
   259  			pos += 4
   260  		} else {
   261  			buf[pos] = uint8(message[v]) // before frr7.4: 8bit
   262  			pos++
   263  		}
   264  		if v > 4 {
   265  			buf[pos] = byte(SafiUnicast) //SAFI
   266  			pos++
   267  			buf[pos] = byte(syscall.AF_INET) //Family
   268  			pos++
   269  		}
   270  		buf[pos] = 24 // PrefixLen
   271  		pos++
   272  		ip := net.ParseIP("192.168.100.0").To4()
   273  		copy(buf[pos:pos+3], []byte(ip))
   274  		pos += 3
   275  		switch v {
   276  		case 2, 3, 4:
   277  			buf[pos] = byte(1) // Number of Nexthops
   278  			pos++
   279  		case 5, 6:
   280  			binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
   281  			pos += 2
   282  			binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
   283  			pos += 4
   284  			buf[pos] = byte(nexthopTypeIPv4IFIndex)
   285  			pos++
   286  		}
   287  		if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
   288  			buf[pos] = 1
   289  			pos++
   290  		}
   291  		nexthop := net.ParseIP("0.0.0.0").To4()
   292  		copy(buf[pos:pos+4], []byte(nexthop))
   293  		pos += 4
   294  		if v < 5 {
   295  			buf[pos] = 1 // Number of Ifindex
   296  			pos++
   297  		}
   298  		binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex
   299  		pos += 4
   300  		buf[pos] = 0 // distance
   301  		pos++
   302  		binary.BigEndian.PutUint32(buf[pos:], 1) // metric
   303  		pos += 4
   304  		binary.BigEndian.PutUint32(buf[pos:], 1) // mtu
   305  		pos += 4
   306  		r := &IPRouteBody{API: command[v]}
   307  		err := r.decodeFromBytes(buf, v, software)
   308  		assert.Equal(nil, err)
   309  		assert.Equal("192.168.100.0", r.Prefix.Prefix.String())
   310  		assert.Equal(uint8(0x18), r.Prefix.PrefixLen)
   311  		assert.Equal(message[v], r.Message)
   312  		assert.Equal("0.0.0.0", r.Nexthops[0].Gate.String())
   313  		switch v {
   314  		case 2, 3, 4:
   315  			assert.Equal(uint32(1), r.Nexthops[1].Ifindex)
   316  		case 5, 6:
   317  			assert.Equal(uint32(1), r.Nexthops[0].Ifindex)
   318  		}
   319  		assert.Equal(uint8(0), r.Distance)
   320  		assert.Equal(uint32(1), r.Metric)
   321  		assert.Equal(uint32(1), r.Mtu)
   322  
   323  		//serialize
   324  		buf, err = r.serialize(v, software)
   325  		assert.Equal(nil, err)
   326  		switch v {
   327  		case 2, 3:
   328  			assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3])
   329  			pos = 3
   330  		case 4, 5:
   331  			tmpFlag := byte(0xff & FlagSelected.ToEach(v, software))
   332  			assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, byte(message[v])}, buf[0:8])
   333  			pos = 8
   334  		case 6: // frr 7.5: MessageFlag: 32bit
   335  			tmpFlag := byte(0xff & FlagSelected.ToEach(v, software))
   336  			assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, 0x00, 0x00, 0x00, byte(message[v])}, buf[0:11])
   337  			pos = 11
   338  		}
   339  		switch v {
   340  		case 2, 3, 4:
   341  			assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // SAFI
   342  			pos += 2
   343  		case 5, 6:
   344  			assert.Equal(byte(0x1), buf[pos]) // SAFI
   345  			pos++
   346  			assert.Equal(byte(0x2), buf[pos]) // Family
   347  			pos++
   348  
   349  		}
   350  
   351  		assert.Equal(byte(24), buf[pos])
   352  		pos++
   353  		ip = net.ParseIP("192.168.100.0").To4()
   354  		assert.Equal([]byte(ip)[0:3], buf[pos:pos+3])
   355  		pos += 3
   356  		switch v {
   357  		case 2, 3, 4:
   358  			assert.Equal(byte(2), buf[pos]) // number of nexthop
   359  			pos++
   360  		case 5, 6:
   361  			assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // number of nexthop
   362  			pos += 2
   363  			assert.Equal([]byte{0x0, 0x0, 0x0, 0x0}, buf[pos:pos+4]) // vrfid
   364  			pos += 4
   365  		}
   366  		switch v {
   367  		case 2, 3:
   368  			assert.Equal(byte(backwardNexthopTypeIPv4), buf[pos])
   369  			assert.Equal(byte(nexthopTypeIFIndex), buf[pos+5])
   370  			pos += 10
   371  		case 4:
   372  			assert.Equal(byte(nexthopTypeIPv4), buf[pos])
   373  			assert.Equal(byte(nexthopTypeIFIndex), buf[pos+5])
   374  			pos += 10
   375  		case 5, 6:
   376  			assert.Equal(byte(nexthopTypeIPv4IFIndex), buf[pos])
   377  			pos += 9
   378  		}
   379  		if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
   380  			assert.Equal(byte(0x1), buf[pos])
   381  			pos++
   382  		}
   383  		assert.Equal(byte(0x0), buf[pos]) // distance
   384  		bi := make([]byte, 4)
   385  		binary.BigEndian.PutUint32(bi, 1)
   386  		assert.Equal(bi, buf[pos+1:pos+5]) //metric
   387  		assert.Equal(bi, buf[pos+5:pos+9]) //mtu
   388  
   389  		// length invalid
   390  		buf = make([]byte, size[v]-8)
   391  		buf[0] = byte(routeConnect)
   392  		pos = 1
   393  		switch v {
   394  		case 2, 3:
   395  			buf[pos] = byte(FlagSelected.ToEach(v, software))
   396  			pos++
   397  		case 4, 5, 6:
   398  			binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
   399  			pos += 2
   400  			binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, software)))
   401  			pos += 4
   402  		}
   403  		if v == 6 {
   404  			binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit
   405  			pos += 4
   406  		} else {
   407  			buf[pos] = uint8(message[v]) // before frr7.4: 8bit
   408  			pos++
   409  		}
   410  
   411  		if v > 4 {
   412  			buf[pos] = byte(SafiUnicast) //SAFI
   413  			pos++
   414  			buf[pos] = byte(syscall.AF_INET) //Family
   415  			pos++
   416  		}
   417  		buf[pos] = 24 // PrefixLen
   418  		pos++
   419  		ip = net.ParseIP("192.168.100.0").To4()
   420  		copy(buf[pos:pos+3], []byte(ip))
   421  		pos += 3
   422  		switch v {
   423  		case 2, 3, 4:
   424  			buf[pos] = byte(1) // Number of Nexthops
   425  			pos++
   426  		case 5, 6:
   427  			binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
   428  			pos += 2
   429  			binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
   430  			pos += 4
   431  			buf[pos] = byte(nexthopTypeIPv4IFIndex)
   432  			pos++
   433  		}
   434  		if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
   435  			buf[pos] = 1
   436  			pos++
   437  		}
   438  		nexthop = net.ParseIP("0.0.0.0").To4()
   439  		copy(buf[pos:pos+4], []byte(nexthop))
   440  		pos += 4
   441  		if v < 5 {
   442  			buf[pos] = 1 // Number of Ifindex
   443  			pos++
   444  		}
   445  		binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex
   446  		pos += 4
   447  
   448  		r = &IPRouteBody{API: command[v]}
   449  		err = r.decodeFromBytes(buf, v, software)
   450  		switch v {
   451  		case 2, 3, 4:
   452  			assert.Equal("MessageMetric message length invalid pos:14 rest:14", err.Error())
   453  		case 5:
   454  			assert.Equal("MessageMetric message length invalid pos:19 rest:19", err.Error())
   455  		case 6:
   456  			assert.Equal("MessageMetric message length invalid pos:20 rest:20", err.Error())
   457  		}
   458  
   459  		// no nexthop
   460  		switch v {
   461  		case 2, 3, 4:
   462  			buf = make([]byte, size[v]-14)
   463  		case 5:
   464  			buf = make([]byte, size[v]-19)
   465  		case 6:
   466  			buf = make([]byte, size[v]-20)
   467  		}
   468  		buf[0] = byte(routeType)
   469  		pos = 1
   470  		switch v {
   471  		case 2, 3:
   472  			buf[pos] = byte(FlagSelected.ToEach(v, software))
   473  			pos++
   474  		case 4, 5, 6:
   475  			binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
   476  			pos += 2
   477  			binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, software)))
   478  			pos += 4
   479  		}
   480  
   481  		if v == 6 {
   482  			binary.BigEndian.PutUint32(buf[pos:], uint32(messageWithoutNexthop[v])) // frr7.5: 32bit
   483  			pos += 4
   484  		} else {
   485  			buf[pos] = byte(messageWithoutNexthop[v]) // before frr7.4: 8bit
   486  			pos++
   487  		}
   488  
   489  		if v > 4 {
   490  			buf[pos] = byte(SafiUnicast) //SAFI
   491  			pos++
   492  			buf[pos] = byte(syscall.AF_INET) //Family
   493  			pos++
   494  		}
   495  		buf[pos] = 24 // PrefixLen
   496  		pos++
   497  		ip = net.ParseIP("192.168.100.0").To4()
   498  		copy(buf[pos:pos+3], []byte(ip))
   499  		pos += 3
   500  		buf[pos] = 1 // distance
   501  		pos++
   502  		binary.BigEndian.PutUint32(buf[pos:], 0) //metric
   503  		pos += 4
   504  		r = &IPRouteBody{API: command[v]}
   505  		err = r.decodeFromBytes(buf, v, software)
   506  		assert.Equal(nil, err)
   507  	}
   508  }
   509  
   510  func Test_IPRouteBody_IPv6(t *testing.T) {
   511  	assert := assert.New(t)
   512  	size := map[uint8]uint8{2: 43, 3: 43, 4: 48, 5: 55, 6: 59}
   513  	command := map[uint8]APIType{
   514  		2: zapi3IPv6RouteAdd,
   515  		3: zapi3IPv6RouteAdd,
   516  		4: zapi4IPv6RouteAdd,
   517  		5: zapi6Frr7RouteAdd,
   518  		6: zapi6Frr7RouteAdd,
   519  	}
   520  	routeType := routeConnect
   521  	message := map[uint8]MessageFlag{
   522  		2: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU,
   523  		3: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU,
   524  		4: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi4MessageMTU,
   525  		5: MessageNexthop | MessageDistance | MessageMetric | MessageMTU,
   526  		6: MessageNexthop | MessageDistance | MessageMetric | MessageMTU,
   527  	}
   528  	nexthopType := map[uint8]nexthopType{
   529  		2: backwardNexthopTypeIPv6,
   530  		3: backwardNexthopTypeIPv6,
   531  		4: nexthopTypeIPv6,
   532  		5: nexthopTypeIPv6IFIndex,
   533  		6: nexthopTypeIPv6IFIndex,
   534  	}
   535  	messageWithoutNexthop := map[uint8]MessageFlag{
   536  		2: zapi4MessageDistance | zapi4MessageMetric,
   537  		3: zapi4MessageDistance | zapi4MessageMetric,
   538  		4: zapi4MessageDistance | zapi4MessageMetric,
   539  		5: MessageDistance | MessageMetric,
   540  		6: MessageDistance | MessageMetric,
   541  	}
   542  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
   543  		//decodeFromBytes IPV6_ROUTE
   544  		buf := make([]byte, size[v])
   545  		buf[0] = byte(routeType)
   546  		pos := 1
   547  		software := NewSoftware(v, "")
   548  		switch v {
   549  		case 2, 3:
   550  			buf[pos] = byte(FlagSelected.ToEach(v, software))
   551  			pos++
   552  		case 4, 5, 6:
   553  			binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
   554  			pos += 2
   555  			binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, software)))
   556  			pos += 4
   557  		}
   558  
   559  		if v == 6 {
   560  			binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit
   561  			pos += 4
   562  		} else {
   563  			buf[pos] = uint8(message[v]) // before frr7.4: 8bit
   564  			pos++
   565  		}
   566  
   567  		if v > 4 {
   568  			buf[pos] = byte(SafiUnicast) //SAFI
   569  			pos++
   570  			buf[pos] = byte(syscall.AF_INET6) //Family
   571  			pos++
   572  		}
   573  		buf[pos] = 64 // prefixLen
   574  		pos++
   575  		ip := net.ParseIP("2001:db8:0:f101::").To16()
   576  		copy(buf[pos:pos+8], []byte(ip))
   577  		pos += 8
   578  		switch v {
   579  		case 2, 3, 4:
   580  			buf[pos] = byte(1) // Number of Nexthops
   581  			pos++
   582  		case 5, 6:
   583  			binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
   584  			pos += 2
   585  			binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
   586  			pos += 4
   587  			buf[pos] = byte(nexthopTypeIPv6IFIndex)
   588  			pos++
   589  		}
   590  		if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
   591  			buf[pos] = 1
   592  			pos++
   593  		}
   594  		nexthop := net.ParseIP("::").To16()
   595  		copy(buf[pos:pos+16], []byte(nexthop))
   596  		pos += 16
   597  		if v < 5 {
   598  			buf[pos] = 1 // Number of Ifindex
   599  			pos++
   600  		}
   601  		binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex
   602  		pos += 4
   603  		buf[pos] = 0 // distance
   604  		pos++
   605  		binary.BigEndian.PutUint32(buf[pos:], 1) // metric
   606  		pos += 4
   607  		binary.BigEndian.PutUint32(buf[pos:], 1) // mtu
   608  		pos += 4
   609  		r := &IPRouteBody{API: command[v]}
   610  		err := r.decodeFromBytes(buf, v, software)
   611  		assert.Equal(nil, err)
   612  		assert.Equal("2001:db8:0:f101::", r.Prefix.Prefix.String())
   613  		assert.Equal(uint8(64), r.Prefix.PrefixLen)
   614  		assert.Equal(message[v], r.Message)
   615  		assert.Equal("::", r.Nexthops[0].Gate.String())
   616  		switch v {
   617  		case 2, 3, 4:
   618  			assert.Equal(uint32(1), r.Nexthops[1].Ifindex)
   619  		case 5, 6:
   620  			assert.Equal(uint32(1), r.Nexthops[0].Ifindex)
   621  		}
   622  		assert.Equal(uint8(0), r.Distance)
   623  		assert.Equal(uint32(1), r.Metric)
   624  		assert.Equal(uint32(1), r.Mtu)
   625  
   626  		//serialize
   627  		buf, err = r.serialize(v, software)
   628  		assert.Equal(nil, err)
   629  		switch v {
   630  		case 2, 3:
   631  			assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3])
   632  			pos = 3
   633  		case 4, 5:
   634  			tmpFlag := byte(0xff & FlagSelected.ToEach(v, software))
   635  			assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, byte(message[v])}, buf[0:8])
   636  			pos = 8
   637  		case 6: // frr 7.5: MessageFlag: 32bit
   638  			tmpFlag := byte(0xff & FlagSelected.ToEach(v, software))
   639  			assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, 0x00, 0x00, 0x00, byte(message[v])}, buf[0:11])
   640  			pos = 11
   641  		}
   642  		switch v {
   643  		case 2, 3, 4:
   644  			assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // SAFI
   645  			pos += 2
   646  		case 5, 6:
   647  			assert.Equal(byte(0x1), buf[pos]) // SAFI
   648  			pos++
   649  			assert.Equal(byte(syscall.AF_INET6), buf[pos]) // Family
   650  			pos++
   651  		}
   652  		assert.Equal(byte(64), buf[pos])
   653  		pos++
   654  		ip = net.ParseIP("2001:db8:0:f101::").To16()
   655  		assert.Equal([]byte(ip)[0:8], buf[pos:pos+8])
   656  		pos += 8
   657  		switch v {
   658  		case 2, 3, 4:
   659  			assert.Equal(byte(2), buf[pos]) // number of nexthop
   660  			pos++
   661  		case 5, 6:
   662  			assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // number of nexthop
   663  			pos += 2
   664  			assert.Equal([]byte{0x0, 0x0, 0x0, 0x0}, buf[pos:pos+4]) // vrfid
   665  			pos += 4
   666  		}
   667  		assert.Equal(byte(nexthopType[v]), buf[pos])
   668  		pos++
   669  		if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
   670  			assert.Equal(byte(0x1), buf[pos])
   671  			pos++
   672  		}
   673  		ip = net.ParseIP("::").To16()
   674  		assert.Equal([]byte(ip), buf[pos:pos+16])
   675  		pos += 16
   676  		switch v { // Only Quagga (ZAPI version 2,3) and FRR 3.x (ZAPI version 4)
   677  		case 2, 3:
   678  			assert.Equal(byte(nexthopTypeIFIndex), buf[pos])
   679  			pos++
   680  		case 4:
   681  			assert.Equal(byte(nexthopTypeIFIndex), buf[pos])
   682  			pos++
   683  		}
   684  		bi := make([]byte, 4)
   685  		binary.BigEndian.PutUint32(bi, 1)
   686  		assert.Equal(bi, buf[pos:pos+4]) // Ifindex
   687  		pos += 4
   688  		assert.Equal(byte(0x0), buf[pos])  // distance
   689  		assert.Equal(bi, buf[pos+1:pos+5]) //metric
   690  		assert.Equal(bi, buf[pos+5:pos+9]) //mtu
   691  
   692  		// length invalid
   693  		buf = make([]byte, size[v]+7)
   694  		buf[0] = byte(routeType)
   695  		pos = 1
   696  		switch v {
   697  		case 2, 3:
   698  			buf[pos] = byte(FlagSelected.ToEach(v, software))
   699  			pos++
   700  		case 4, 5, 6:
   701  			binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
   702  			pos += 2
   703  			binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, software)))
   704  			pos += 4
   705  		}
   706  
   707  		if v == 6 {
   708  			binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit
   709  			pos += 4
   710  		} else {
   711  			buf[pos] = uint8(message[v]) // before frr7.4: 8bit
   712  			pos++
   713  		}
   714  
   715  		if v > 4 {
   716  			buf[pos] = byte(SafiUnicast) //SAFI
   717  			pos++
   718  			buf[pos] = byte(syscall.AF_INET6) //Family
   719  			pos++
   720  		}
   721  		buf[pos] = 64 // prefixLen
   722  		pos++
   723  		ip = net.ParseIP("2001:db8:0:f101::").To16()
   724  		copy(buf[pos:pos+8], []byte(ip))
   725  		pos += 8
   726  		switch v {
   727  		case 2, 3, 4:
   728  			buf[pos] = byte(1) // Number of Nexthops
   729  			pos++
   730  		case 5, 6:
   731  			binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops
   732  			pos += 2
   733  			binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid
   734  			pos += 4
   735  			buf[pos] = byte(nexthopTypeIPv6IFIndex)
   736  			pos++
   737  		}
   738  		if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
   739  			buf[pos] = 1
   740  			pos++
   741  		}
   742  		nexthop = net.ParseIP("::").To16()
   743  		copy(buf[pos:pos+16], []byte(nexthop))
   744  		pos += 16
   745  		if v < 5 {
   746  			buf[pos] = 1 // Number of Ifindex
   747  			pos++
   748  		}
   749  		binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex
   750  		pos += 4
   751  
   752  		r = &IPRouteBody{API: command[v]}
   753  		err = r.decodeFromBytes(buf, v, software)
   754  		switch v {
   755  		case 2, 3:
   756  			assert.Equal("message length invalid (last) pos:39 rest:46, message:0x1f", err.Error())
   757  		case 4:
   758  			assert.Equal("message length invalid (last) pos:39 rest:46, message:0x2f", err.Error())
   759  		case 5:
   760  			assert.Equal("message length invalid (last) pos:44 rest:51, message:0x17", err.Error())
   761  		case 6:
   762  			assert.Equal("message length invalid (last) pos:45 rest:52, message:0x17", err.Error())
   763  		}
   764  
   765  		// no nexthop
   766  		switch v {
   767  		case 2, 3, 4:
   768  			buf = make([]byte, size[v]-32)
   769  		case 5:
   770  			buf = make([]byte, size[v]-37)
   771  		case 6:
   772  			buf = make([]byte, size[v]-38)
   773  		}
   774  		buf[0] = byte(routeType)
   775  		pos = 1
   776  		switch v {
   777  		case 2, 3:
   778  			buf[pos] = byte(FlagSelected.ToEach(v, software))
   779  			pos++
   780  		case 4, 5, 6:
   781  			binary.BigEndian.PutUint16(buf[pos:], 0) //Instance
   782  			pos += 2
   783  			binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, software)))
   784  			pos += 4
   785  		}
   786  
   787  		if v == 6 {
   788  			binary.BigEndian.PutUint32(buf[pos:], uint32(messageWithoutNexthop[v])) // frr7.5: 32bit
   789  			pos += 4
   790  		} else {
   791  			buf[pos] = byte(messageWithoutNexthop[v]) // before frr7.4: 8bit
   792  			pos++
   793  		}
   794  
   795  		if v > 4 {
   796  			buf[pos] = byte(SafiUnicast) //SAFI
   797  			pos++
   798  			buf[pos] = byte(syscall.AF_INET) //Family
   799  			pos++
   800  		}
   801  		buf[pos] = 16 // PrefixLen
   802  		pos++
   803  		ip = net.ParseIP("2501::").To16()
   804  		copy(buf[pos:pos+2], []byte(ip))
   805  		pos += 2
   806  		buf[pos] = 1                             //distance
   807  		binary.BigEndian.PutUint32(buf[pos:], 0) //metic
   808  		r = &IPRouteBody{API: command[v]}
   809  		err = r.decodeFromBytes(buf, v, software)
   810  		assert.Equal(nil, err)
   811  	}
   812  }
   813  
   814  // NexthopLookup exists in only quagga (zebra API version 2 and 3)
   815  func Test_nexthopLookupBody(t *testing.T) {
   816  	assert := assert.New(t)
   817  
   818  	//ipv4
   819  	//decodeFromBytes
   820  	pos := 0
   821  	buf := make([]byte, 18)
   822  	ip := net.ParseIP("192.168.50.0").To4()
   823  	copy(buf[0:4], []byte(ip)) // addr
   824  	pos += 4
   825  	binary.BigEndian.PutUint32(buf[pos:], 10) // metric
   826  	pos += 4
   827  	buf[pos] = byte(1) // numNexthop
   828  	pos++
   829  	buf[pos] = byte(4)
   830  	pos++
   831  	ip = net.ParseIP("172.16.1.101").To4()
   832  	copy(buf[pos:pos+4], []byte(ip))
   833  	pos += 4
   834  	binary.BigEndian.PutUint32(buf[pos:], 3)
   835  
   836  	//b := &nexthopLookupBody{api: zapi3IPv4NexthopLookup}
   837  	b := &lookupBody{api: zapi3IPv4NexthopLookup}
   838  	v := uint8(2)
   839  	software := NewSoftware(v, "")
   840  	err := b.decodeFromBytes(buf, v, software)
   841  	assert.Equal(nil, err)
   842  	assert.Equal("192.168.50.0", b.addr.String())
   843  	assert.Equal(uint32(10), b.metric)
   844  	assert.Equal(uint32(3), b.nexthops[0].Ifindex)
   845  	assert.Equal(nexthopType(4), b.nexthops[0].Type)
   846  	assert.Equal("172.16.1.101", b.nexthops[0].Gate.String())
   847  
   848  	//serialize
   849  	buf, err = b.serialize(v, software)
   850  	ip = net.ParseIP("192.168.50.0").To4()
   851  	assert.Equal(nil, err)
   852  	assert.Equal([]byte(ip)[0:4], buf[0:4])
   853  
   854  	// length invalid
   855  	buf = make([]byte, 3)
   856  	//b = &nexthopLookupBody{api: zapi3IPv4NexthopLookup}
   857  	b = &lookupBody{api: zapi3IPv4NexthopLookup}
   858  	err = b.decodeFromBytes(buf, v, software)
   859  	assert.NotEqual(nil, err)
   860  
   861  	//ipv6
   862  	//decodeFromBytes
   863  	pos = 0
   864  	buf = make([]byte, 46)
   865  	ip = net.ParseIP("2001:db8:0:f101::").To16()
   866  	copy(buf[0:16], []byte(ip))
   867  	pos += 16
   868  	binary.BigEndian.PutUint32(buf[pos:], 10)
   869  	pos += 4
   870  	buf[pos] = byte(1)
   871  	pos++
   872  	buf[pos] = byte(7)
   873  	pos++
   874  	ip = net.ParseIP("2001:db8:0:1111::1").To16()
   875  	copy(buf[pos:pos+16], []byte(ip))
   876  	pos += 16
   877  	binary.BigEndian.PutUint32(buf[pos:], 3)
   878  
   879  	b = &lookupBody{api: zapi3IPv6NexthopLookup}
   880  	err = b.decodeFromBytes(buf, v, software)
   881  	assert.Equal(nil, err)
   882  	assert.Equal("2001:db8:0:f101::", b.addr.String())
   883  	assert.Equal(uint32(10), b.metric)
   884  	assert.Equal(uint32(3), b.nexthops[0].Ifindex)
   885  	assert.Equal(nexthopType(7), b.nexthops[0].Type)
   886  	assert.Equal("2001:db8:0:1111::1", b.nexthops[0].Gate.String())
   887  
   888  	//serialize
   889  	buf, err = b.serialize(v, software)
   890  	ip = net.ParseIP("2001:db8:0:f101::").To16()
   891  	assert.Equal(nil, err)
   892  	assert.Equal([]byte(ip)[0:16], buf[0:16])
   893  
   894  	// length invalid
   895  	buf = make([]byte, 15)
   896  	b = &lookupBody{api: zapi3IPv6NexthopLookup}
   897  	err = b.decodeFromBytes(buf, v, software)
   898  	assert.NotEqual(nil, err)
   899  }
   900  
   901  // ImportLookup exists in only quagga (zebra API version 2 and 3)
   902  func Test_importLookupBody(t *testing.T) {
   903  	assert := assert.New(t)
   904  
   905  	//decodeFromBytes
   906  	pos := 0
   907  	buf := make([]byte, 18)
   908  	ip := net.ParseIP("192.168.50.0").To4()
   909  	copy(buf[0:4], []byte(ip))
   910  	pos += 4
   911  	binary.BigEndian.PutUint32(buf[pos:], 10)
   912  	pos += 4
   913  	buf[pos] = byte(1)
   914  	pos++
   915  	buf[pos] = byte(4)
   916  	pos++
   917  	ip = net.ParseIP("172.16.1.101").To4()
   918  	copy(buf[pos:pos+4], []byte(ip))
   919  	pos += 4
   920  	binary.BigEndian.PutUint32(buf[pos:], 3)
   921  
   922  	b := &lookupBody{api: zapi3IPv4ImportLookup}
   923  	v := uint8(2)
   924  	software := NewSoftware(v, "")
   925  	err := b.decodeFromBytes(buf, v, software)
   926  	assert.Equal(nil, err)
   927  	assert.Equal("192.168.50.0", b.addr.String())
   928  	assert.Equal(uint32(10), b.metric)
   929  	assert.Equal(uint32(3), b.nexthops[0].Ifindex)
   930  	assert.Equal(nexthopType(4), b.nexthops[0].Type)
   931  	assert.Equal("172.16.1.101", b.nexthops[0].Gate.String())
   932  
   933  	//serialize
   934  	b.prefixLength = uint8(24)
   935  	buf, err = b.serialize(v, software)
   936  	ip = net.ParseIP("192.168.50.0").To4()
   937  	assert.Equal(nil, err)
   938  	assert.Equal(uint8(24), buf[0])
   939  	assert.Equal([]byte(ip)[0:4], buf[1:5])
   940  
   941  	// length invalid
   942  	buf = make([]byte, 3)
   943  	b = &lookupBody{api: zapi3IPv4ImportLookup}
   944  	err = b.decodeFromBytes(buf, v, software)
   945  	assert.NotEqual(nil, err)
   946  }
   947  
   948  func Test_NexthopRegisterBody(t *testing.T) {
   949  	assert := assert.New(t)
   950  
   951  	// Input binary
   952  	bufIn := []byte{
   953  		0x01, uint8(syscall.AF_INET >> 8), uint8(syscall.AF_INET & 0xff), 0x20, // connected(1 byte)=1, afi(2 bytes)=AF_INET, prefix_len(1 byte)=32
   954  		0xc0, 0xa8, 0x01, 0x01, // prefix(4 bytes)="192.168.1.1"
   955  		0x00, uint8(syscall.AF_INET6 >> 8), uint8(syscall.AF_INET6 & 0xff), 0x80, // connected(1 byte)=0, afi(2 bytes)=AF_INET6, prefix_len(1 byte)=128
   956  		0x20, 0x01, 0x0d, 0xb8, // prefix(16 bytes)="2001:db8:1:1::1"
   957  		0x00, 0x01, 0x00, 0x01,
   958  		0x00, 0x00, 0x00, 0x00,
   959  		0x00, 0x00, 0x00, 0x01,
   960  	}
   961  	command := map[uint8]APIType{
   962  		2: zapi3NexthopRegister,
   963  		3: zapi3NexthopRegister,
   964  		4: zapi4NexthopRegister,
   965  		5: zapi5Frr5NexthopRegister,
   966  		6: nexthopRegister,
   967  	}
   968  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
   969  		// Test decodeFromBytes()
   970  		software := NewSoftware(v, "")
   971  		b := &NexthopRegisterBody{api: command[v].ToCommon(v, software)}
   972  		err := b.decodeFromBytes(bufIn, v, software)
   973  		assert.Nil(err)
   974  
   975  		// Test decoded values
   976  		assert.Equal(uint8(1), b.Nexthops[0].connected)
   977  		assert.Equal(uint16(syscall.AF_INET), b.Nexthops[0].Family)
   978  		assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Nexthops[0].Prefix)
   979  		assert.Equal(uint8(0), b.Nexthops[1].connected)
   980  		assert.Equal(uint16(syscall.AF_INET6), b.Nexthops[1].Family)
   981  		assert.Equal(net.ParseIP("2001:db8:1:1::1").To16(), b.Nexthops[1].Prefix)
   982  
   983  		// Test serialize()
   984  		bufOut, err := b.serialize(v, software)
   985  		assert.Nil(err)
   986  
   987  		// Test serialised value
   988  		assert.Equal(bufIn, bufOut)
   989  	}
   990  }
   991  
   992  func Test_NexthopUpdateBody(t *testing.T) {
   993  	assert := assert.New(t)
   994  
   995  	size := map[uint8]uint8{2: 21, 3: 21, 4: 22, 5: 26, 6: 34}
   996  	command := map[uint8]APIType{
   997  		2: zapi3NexthopUpdate,
   998  		3: zapi3NexthopUpdate,
   999  		4: zapi4NexthopUpdate,
  1000  		5: zapi5Frr5NexthopUpdate,
  1001  		6: nexthopUpdate,
  1002  	}
  1003  	nexthopType := map[uint8]nexthopType{
  1004  		2: backwardNexthopTypeIPv4IFIndex,
  1005  		3: backwardNexthopTypeIPv4IFIndex,
  1006  		4: nexthopTypeIPv4IFIndex,
  1007  		5: nexthopTypeIPv4IFIndex,
  1008  		6: nexthopTypeIPv4IFIndex,
  1009  	}
  1010  
  1011  	for v := MinZapiVer; v <= MaxZapiVer; v++ {
  1012  		// Input binary
  1013  		bufIn := make([]byte, size[v])
  1014  		pos := 0
  1015  		if v == 6 { // frr7.5
  1016  			// message flag
  1017  			copy(bufIn[pos:pos+4], []byte{0x00, 0x00, 0x00, 0x00})
  1018  			pos += 4
  1019  		}
  1020  		// afi(2 bytes)=AF_INET, prefix_len(1 byte)=32, prefix(4 bytes)="192.168.1.1"
  1021  		copy(bufIn[pos:pos+7], []byte{0x00, 0x02, 0x20, 0xc0, 0xa8, 0x01, 0x01})
  1022  		pos += 7
  1023  
  1024  		if v > 4 { // Type(1byte), Instance(2byte)
  1025  			copy(bufIn[pos:pos+3], []byte{byte(routeConnect), 0x00, 0x00})
  1026  			pos += 3
  1027  		}
  1028  		if v > 3 { // Distance
  1029  			bufIn[pos] = 0
  1030  			pos++
  1031  		}
  1032  		// metric(4 bytes)=1, number of nexthops(1 byte)=1
  1033  		copy(bufIn[pos:pos+5], []byte{0x00, 0x00, 0x00, 0x01, 0x01})
  1034  		pos += 5
  1035  		if v == 6 { // version == 6 and not frr6
  1036  			binary.BigEndian.PutUint32(bufIn[pos:], 0) //vrfid
  1037  			pos += 4
  1038  		}
  1039  		bufIn[pos] = byte(nexthopType[v])
  1040  		pos++
  1041  		if v == 6 { // frr7.3 and later
  1042  			bufIn[pos] = byte(0) // nexthop flag
  1043  			pos++
  1044  		}
  1045  		// nexthop_ip(4 bytes)="192.168.0.1", nexthop_Ifindex(4 byte)=2
  1046  		copy(bufIn[pos:pos+8], []byte{0xc0, 0xa8, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02})
  1047  		pos += 8
  1048  		if v == 5 { // frr7.3&7.4 (latest software of zapi v6) depends on nexthop flag
  1049  			bufIn[pos] = byte(0) // label num
  1050  			pos++
  1051  		}
  1052  
  1053  		// Test decodeFromBytes()
  1054  		software := NewSoftware(v, "")
  1055  		b := &NexthopUpdateBody{API: command[v].ToCommon(v, software)}
  1056  		err := b.decodeFromBytes(bufIn, v, software)
  1057  		assert.Nil(err)
  1058  
  1059  		// Test decoded values
  1060  		assert.Equal(uint8(syscall.AF_INET), b.Prefix.Family)
  1061  		assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Prefix.Prefix)
  1062  		assert.Equal(uint32(1), b.Metric)
  1063  		nexthop := Nexthop{
  1064  			Type:    nexthopType[v],
  1065  			Gate:    net.ParseIP("192.168.1.1").To4(),
  1066  			Ifindex: uint32(2),
  1067  		}
  1068  		assert.Equal(1, len(b.Nexthops))
  1069  		assert.Equal(nexthop, b.Nexthops[0])
  1070  	}
  1071  }
  1072  
  1073  func Test_GetLabelChunkBody(t *testing.T) {
  1074  	assert := assert.New(t)
  1075  
  1076  	// Test only with ZAPI version 5 and 6
  1077  	routeType := RouteBGP
  1078  	for v := uint8(5); v <= MaxZapiVer; v++ {
  1079  		//decodeFromBytes
  1080  		buf := make([]byte, 12)
  1081  		buf[0] = byte(routeType)                // Route Type
  1082  		binary.BigEndian.PutUint16(buf[1:], 0)  //Instance
  1083  		buf[3] = 0                              //Keep
  1084  		binary.BigEndian.PutUint32(buf[4:], 80) //Start
  1085  		binary.BigEndian.PutUint32(buf[8:], 89) //End
  1086  
  1087  		b := &GetLabelChunkBody{}
  1088  		software := NewSoftware(v, "")
  1089  		err := b.decodeFromBytes(buf, v, software)
  1090  		assert.Equal(nil, err)
  1091  
  1092  		//serialize
  1093  		b.ChunkSize = 10
  1094  		buf, err = b.serialize(v, software)
  1095  		assert.Equal(nil, err)
  1096  		assert.Equal(byte(routeType), buf[0])
  1097  		bi := make([]byte, 4)
  1098  		binary.BigEndian.PutUint32(bi, 10)
  1099  		assert.Equal(bi, buf[4:8]) // Chunksize
  1100  	}
  1101  }
  1102  
  1103  func Test_vrfLabelBody(t *testing.T) {
  1104  	assert := assert.New(t)
  1105  	// Test only with ZAPI version 5 and 6
  1106  	for v := uint8(5); v <= MaxZapiVer; v++ {
  1107  		//decodeFromBytes
  1108  		bufIn := make([]byte, 6)
  1109  		binary.BigEndian.PutUint32(bufIn[0:], 80) //label
  1110  		bufIn[4] = byte(afiIP)
  1111  		bufIn[5] = byte(lspBGP)
  1112  		b := &vrfLabelBody{}
  1113  		software := NewSoftware(v, "")
  1114  		err := b.decodeFromBytes(bufIn, v, software)
  1115  		assert.Equal(nil, err)
  1116  		//serialize
  1117  		var bufOut []byte
  1118  		bufOut, err = b.serialize(v, software)
  1119  		assert.Equal(nil, err)
  1120  		assert.Equal(bufIn, bufOut)
  1121  	}
  1122  }
  1123  
  1124  func FuzzZapi(f *testing.F) {
  1125  
  1126  	f.Fuzz(func(t *testing.T, data []byte) {
  1127  
  1128  		if len(data) < 16 {
  1129  			return
  1130  		}
  1131  
  1132  		for v := MinZapiVer; v <= MaxZapiVer; v++ {
  1133  
  1134  			ZAPIHeaderSize := int(HeaderSize(v))
  1135  
  1136  			hd := &Header{}
  1137  			err := hd.decodeFromBytes(data[:ZAPIHeaderSize])
  1138  
  1139  			if err != nil {
  1140  				return
  1141  			}
  1142  
  1143  			software := NewSoftware(v, "")
  1144  			parseMessage(hd, data[:ZAPIHeaderSize], software)
  1145  		}
  1146  	})
  1147  }