mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
zebra/zapi: Support NEXTHOP_UPDATE message
Signed-off-by: IWASE Yusuke <[email protected]>
This commit is contained in:
committed by
FUJITA Tomonori
parent
0e53acd88f
commit
087ea75850
+110
@@ -1026,6 +1026,111 @@ func (b *ImportLookupBody) String() string {
|
||||
return s
|
||||
}
|
||||
|
||||
type NexthopUpdateBody struct {
|
||||
Api API_TYPE
|
||||
Family uint16
|
||||
// Note: Ignores PrefixLength (uint8),
|
||||
// because this field should be always:
|
||||
// - 32 if Address Family is AF_INET
|
||||
// - 128 if Address Family is AF_INET6
|
||||
Prefix net.IP
|
||||
Metric uint32
|
||||
Nexthops []*Nexthop
|
||||
}
|
||||
|
||||
func (b *NexthopUpdateBody) Serialize() ([]byte, error) {
|
||||
// Address Family (2 bytes)
|
||||
buf := make([]byte, 3)
|
||||
binary.BigEndian.PutUint16(buf, b.Family)
|
||||
|
||||
// Prefix Length (1 byte) + Prefix (variable)
|
||||
switch b.Family {
|
||||
case uint16(syscall.AF_INET):
|
||||
buf[2] = byte(net.IPv4len * 8)
|
||||
buf = append(buf, b.Prefix.To4()...)
|
||||
case uint16(syscall.AF_INET6):
|
||||
buf[2] = byte(net.IPv6len * 8)
|
||||
buf = append(buf, b.Prefix.To16()...)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid address family: %d", b.Family)
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (b *NexthopUpdateBody) DecodeFromBytes(data []byte, version uint8) error {
|
||||
// Address Family (2 bytes)
|
||||
b.Family = binary.BigEndian.Uint16(data[0:2])
|
||||
isV4 := b.Family == uint16(syscall.AF_INET)
|
||||
addrLen := int(net.IPv4len)
|
||||
if !isV4 {
|
||||
addrLen = net.IPv6len
|
||||
}
|
||||
// Note: Ignores Prefix Length (1 byte)
|
||||
offset := 3
|
||||
|
||||
// Prefix (variable)
|
||||
if isV4 {
|
||||
b.Prefix = net.IP(data[offset : offset+addrLen]).To4()
|
||||
} else {
|
||||
b.Prefix = net.IP(data[offset : offset+addrLen]).To16()
|
||||
}
|
||||
offset += addrLen
|
||||
|
||||
// Metric (4 bytes)
|
||||
// Number of Nexthops (1 byte)
|
||||
if len(data[offset:]) < 4+1 {
|
||||
return fmt.Errorf("invalid message length: missing metric(4 bytes) or nexthops(1 byte): %d<5", len(data[offset:]))
|
||||
}
|
||||
b.Metric = binary.BigEndian.Uint32(data[offset : offset+4])
|
||||
offset += 4
|
||||
nexthopsNum := int(data[offset])
|
||||
offset += 1
|
||||
|
||||
// List of Nexthops
|
||||
b.Nexthops = []*Nexthop{}
|
||||
for i := 0; i < nexthopsNum; i++ {
|
||||
nh := &Nexthop{}
|
||||
nh.Type = NEXTHOP_FLAG(data[offset])
|
||||
offset += 1
|
||||
|
||||
switch nh.Type {
|
||||
case NEXTHOP_IPV4, NEXTHOP_IPV6:
|
||||
if isV4 {
|
||||
nh.Addr = net.IP(data[offset : offset+addrLen]).To4()
|
||||
} else {
|
||||
nh.Addr = net.IP(data[offset : offset+addrLen]).To16()
|
||||
}
|
||||
offset += addrLen
|
||||
|
||||
case NEXTHOP_IPV4_IFINDEX, NEXTHOP_IPV4_IFNAME, NEXTHOP_IPV6_IFINDEX, NEXTHOP_IPV6_IFNAME:
|
||||
if isV4 {
|
||||
nh.Addr = net.IP(data[offset : offset+addrLen]).To4()
|
||||
} else {
|
||||
nh.Addr = net.IP(data[offset : offset+addrLen]).To16()
|
||||
}
|
||||
offset += addrLen
|
||||
nh.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4])
|
||||
offset += 4
|
||||
|
||||
case NEXTHOP_IFINDEX, NEXTHOP_IFNAME:
|
||||
nh.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4])
|
||||
offset += 4
|
||||
}
|
||||
b.Nexthops = append(b.Nexthops, nh)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *NexthopUpdateBody) String() string {
|
||||
s := fmt.Sprintf("family: %d, prefix: %s, metric: %d", b.Family, b.Prefix.String(), b.Metric)
|
||||
for _, nh := range b.Nexthops {
|
||||
s = s + fmt.Sprintf(", nexthop:{%s}", nh.String())
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Header Header
|
||||
Body Body
|
||||
@@ -1073,6 +1178,11 @@ func ParseMessage(hdr *Header, data []byte) (*Message, error) {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Zebra",
|
||||
}).Debugf("ipv4 import lookup message received: %v", data)
|
||||
case NEXTHOP_UPDATE:
|
||||
m.Body = &NexthopUpdateBody{Api: m.Header.Command}
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Zebra",
|
||||
}).Debugf("nexthop update message received: %v", data)
|
||||
default:
|
||||
return nil, fmt.Errorf("Unknown zapi command: %d", m.Header.Command)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"encoding/binary"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -450,3 +451,35 @@ func Test_ImportLookupBody(t *testing.T) {
|
||||
err = b.DecodeFromBytes(buf, 2)
|
||||
assert.NotEqual(nil, err)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Test DecodeFromBytes()
|
||||
b := &NexthopUpdateBody{Api: NEXTHOP_UPDATE}
|
||||
err := b.DecodeFromBytes(bufIn, 2)
|
||||
assert.Nil(err)
|
||||
|
||||
// Test decoded values
|
||||
assert.Equal(uint16(syscall.AF_INET), b.Family)
|
||||
assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Prefix)
|
||||
assert.Equal(uint32(1), b.Metric)
|
||||
nexthop := &Nexthop{
|
||||
Type: NEXTHOP_FLAG(NEXTHOP_IPV4_IFINDEX),
|
||||
Addr: net.ParseIP("192.168.1.1").To4(),
|
||||
Ifindex: uint32(2),
|
||||
}
|
||||
assert.Equal(1, len(b.Nexthops))
|
||||
assert.Equal(nexthop, b.Nexthops[0])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user