diff options
author | Tatsushi Demachi <tdemachi@gmail.com> | 2017-02-10 20:38:17 +0900 |
---|---|---|
committer | Tatsushi Demachi <tdemachi@gmail.com> | 2017-02-10 20:57:11 +0900 |
commit | e84bf755a9740d5bca3405da494d3c4a85d30679 (patch) | |
tree | 295c691d7537bacbb00a232a91f2724b763bb20f /zebra | |
parent | 3703916e558624e383794b015b8f8e69422654c1 (diff) |
zebra: Process per-route MTU zebra message
Since Quagga 1.0.20160309, it implements per-route MTU handling which
adds MTU attribute to every ZEBRA_IPV4_ROUTE_ADD and
ZEBRA_IPV6_ROUTE_ADD messages. It causes "message length invalid" error
when GoBGP receives messages from Zebra and as the result, routes from
Zebra are no longer added to GoBGP.
This fixes the issue by decoding/encoding MTU attribute properly.
Now parsed MTU attribute is not used anywhere, just kept in an internal
structure.
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/zapi.go | 20 | ||||
-rw-r--r-- | zebra/zapi_test.go | 28 |
2 files changed, 35 insertions, 13 deletions
diff --git a/zebra/zapi.go b/zebra/zapi.go index 25647257..dcee2d7a 100644 --- a/zebra/zapi.go +++ b/zebra/zapi.go @@ -211,6 +211,7 @@ const ( MESSAGE_IFINDEX = 0x02 MESSAGE_DISTANCE = 0x04 MESSAGE_METRIC = 0x08 + MESSAGE_MTU = 0x10 ) // Message Flags @@ -662,6 +663,7 @@ type IPRouteBody struct { Ifindexs []uint32 Distance uint8 Metric uint32 + Mtu uint32 Api API_TYPE } @@ -716,6 +718,11 @@ func (b *IPRouteBody) Serialize() ([]byte, error) { binary.BigEndian.PutUint32(bbuf, b.Metric) buf = append(buf, bbuf...) } + if b.Message&MESSAGE_MTU > 0 { + bbuf := make([]byte, 4) + binary.BigEndian.PutUint32(bbuf, b.Mtu) + buf = append(buf, bbuf...) + } return buf, nil } @@ -769,6 +776,11 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error { rest += 4 } + if b.Message&MESSAGE_MTU > 0 { + // mtu(4) + rest += 4 + } + if len(data[pos:]) != rest { return fmt.Errorf("message length invalid") } @@ -803,13 +815,17 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error { pos += 1 b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) } + if b.Message&MESSAGE_MTU > 0 { + pos += 4 + b.Mtu = binary.BigEndian.Uint32(data[pos : pos+4]) + } return nil } func (b *IPRouteBody) String() string { - s := fmt.Sprintf("type: %s, flags: %s, message: %d, prefix: %s, length: %d, nexthop: %s, distance: %d, metric: %d", - b.Type.String(), b.Flags.String(), b.Message, b.Prefix.String(), b.PrefixLength, b.Nexthops[0].String(), b.Distance, b.Metric) + s := fmt.Sprintf("type: %s, flags: %s, message: %d, prefix: %s, length: %d, nexthop: %s, distance: %d, metric: %d, mtu: %d", + b.Type.String(), b.Flags.String(), b.Message, b.Prefix.String(), b.PrefixLength, b.Nexthops[0].String(), b.Distance, b.Metric, b.Mtu) return s } diff --git a/zebra/zapi_test.go b/zebra/zapi_test.go index 696374b4..ac4862f0 100644 --- a/zebra/zapi_test.go +++ b/zebra/zapi_test.go @@ -152,10 +152,10 @@ func Test_IPRouteBody_IPv4(t *testing.T) { assert := assert.New(t) //DecodeFromBytes IPV4_ROUTE - buf := make([]byte, 22) + buf := make([]byte, 26) buf[0] = byte(ROUTE_CONNECT) buf[1] = byte(FLAG_SELECTED) - buf[2] = MESSAGE_NEXTHOP | MESSAGE_DISTANCE | MESSAGE_METRIC + buf[2] = MESSAGE_NEXTHOP | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU buf[3] = 24 ip := net.ParseIP("192.168.100.0").To4() copy(buf[4:7], []byte(ip)) @@ -168,22 +168,24 @@ func Test_IPRouteBody_IPv4(t *testing.T) { 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.String()) assert.Equal(uint8(0x18), r.PrefixLength) - assert.Equal(uint8(MESSAGE_NEXTHOP|MESSAGE_DISTANCE|MESSAGE_METRIC), r.Message) + assert.Equal(uint8(MESSAGE_NEXTHOP|MESSAGE_DISTANCE|MESSAGE_METRIC|MESSAGE_MTU), r.Message) assert.Equal("0.0.0.0", r.Nexthops[0].String()) assert.Equal(uint32(1), r.Ifindexs[0]) assert.Equal(uint8(0), r.Distance) assert.Equal(uint32(1), r.Metric) + assert.Equal(uint32(1), r.Mtu) //Serialize buf, err = r.Serialize() assert.Equal(nil, err) - assert.Equal([]byte{0x2, 0x10, 0xd}, buf[0:3]) + assert.Equal([]byte{0x2, 0x10, 0x1d}, 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() @@ -194,7 +196,8 @@ func Test_IPRouteBody_IPv4(t *testing.T) { bi := make([]byte, 4) binary.BigEndian.PutUint32(bi, 1) - assert.Equal(bi, buf[21:]) + assert.Equal(bi, buf[21:25]) + assert.Equal(bi, buf[25:]) // length invalid buf = make([]byte, 18) @@ -224,7 +227,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) { copy(buf[4:7], []byte(ip)) buf[7] = 1 binary.BigEndian.PutUint32(buf[8:], 0) - r = &IPRouteBody{Api: IPV6_ROUTE_ADD} + r = &IPRouteBody{Api: IPV4_ROUTE_ADD} err = r.DecodeFromBytes(buf, 2) assert.Equal(nil, err) @@ -234,10 +237,10 @@ func Test_IPRouteBody_IPv6(t *testing.T) { assert := assert.New(t) //DecodeFromBytes IPV6_ROUTE - buf := make([]byte, 39) + buf := make([]byte, 43) buf[0] = byte(ROUTE_CONNECT) buf[1] = byte(FLAG_SELECTED) - buf[2] = MESSAGE_NEXTHOP | MESSAGE_DISTANCE | MESSAGE_METRIC + buf[2] = MESSAGE_NEXTHOP | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU buf[3] = 64 ip := net.ParseIP("2001:db8:0:f101::").To16() copy(buf[4:12], []byte(ip)) @@ -251,22 +254,24 @@ func Test_IPRouteBody_IPv6(t *testing.T) { 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.String()) assert.Equal(uint8(64), r.PrefixLength) - assert.Equal(uint8(MESSAGE_NEXTHOP|MESSAGE_DISTANCE|MESSAGE_METRIC), r.Message) + assert.Equal(uint8(MESSAGE_NEXTHOP|MESSAGE_DISTANCE|MESSAGE_METRIC|MESSAGE_MTU), r.Message) assert.Equal("::", r.Nexthops[0].String()) assert.Equal(uint32(1), r.Ifindexs[0]) assert.Equal(uint8(0), r.Distance) assert.Equal(uint32(1), r.Metric) + assert.Equal(uint32(1), r.Mtu) //Serialize buf, err = r.Serialize() assert.Equal(nil, err) - assert.Equal([]byte{0x2, 0x10, 0xd}, buf[0:3]) + assert.Equal([]byte{0x2, 0x10, 0x1d}, 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() @@ -284,7 +289,8 @@ func Test_IPRouteBody_IPv6(t *testing.T) { assert.Equal(byte(0), buf[37]) bi = make([]byte, 4) binary.BigEndian.PutUint32(bi, 1) - assert.Equal(bi, buf[38:]) + assert.Equal(bi, buf[38:42]) + assert.Equal(bi, buf[42:]) // length invalid buf = make([]byte, 50) |